zardoz/classifier.go
2019-12-11 12:10:36 +01:00

136 lines
2.9 KiB
Go

package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"regexp"
"strings"
)
func passAndLearn(resp *http.Response) error {
ProxyFlow.response = resp
ProxyFlow.seniority++
req := ProxyFlow.request
switch {
case resp.StatusCode == 401:
log.Println("401: We don't want to store credentials")
case resp.StatusCode > 399:
buf := bytes.NewBufferString(BlockMessage)
resp.Body = ioutil.NopCloser(buf)
resp.Status = "403 Forbidden"
resp.StatusCode = 403
resp.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())}
resp.Header.Set("Content-Encoding", "none")
log.Println("Filing inside bad class")
feedRequest(req, "BAD")
ControPlane.StatsTokens <- "LEARN-BAD"
default:
log.Println("Filing inside Good Class: ", resp.StatusCode)
feedRequest(req, "GOOD")
}
return nil
}
func blockAndlearn(resp *http.Response) error {
ProxyFlow.response = resp
ProxyFlow.seniority++
req := ProxyFlow.request
buf := bytes.NewBufferString(BlockMessage)
resp.Body = ioutil.NopCloser(buf)
resp.Status = "403 Forbidden"
resp.StatusCode = 403
resp.Header["Content-Length"] = []string{fmt.Sprint(buf.Len())}
resp.Header.Set("Content-Encoding", "none")
switch {
case resp.StatusCode == 401:
log.Println("401: We don't want to store credentials")
case resp.StatusCode > 399:
log.Println("Filing inside bad class")
feedRequest(req, "BAD")
default:
log.Println("Filing inside Good Class: ", resp.StatusCode)
ControPlane.StatsTokens <- "LEARN-GOOD"
feedRequest(req, "GOOD")
}
return nil
}
func sanitizeHeaders(s string) string {
re := regexp.MustCompile(`[a-zA-Z]{4,32}|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})`)
matched := re.FindAllString(s, -1)
uMatched := Unique(matched)
tmpSt := strings.ToLower(strings.Join(uMatched, " "))
log.Println("Matched: " + tmpSt)
return tmpSt
}
func feedRequest(req *http.Request, class string) {
feed := formatRequest(req)
if class == "BAD" {
log.Println("Feeding BAD token: ", feed)
ControPlane.BadTokens <- sanitizeHeaders(feed)
}
if class == "GOOD" {
log.Println("Feeding GOOD Token:", feed)
ControPlane.GoodTokens <- sanitizeHeaders(feed)
}
}
func formatRequest(req *http.Request) string {
ingestBody := req.ContentLength < 2048 && req.ContentLength > 1
log.Println("Ingesting the body: ", ingestBody)
requestDump, err := httputil.DumpRequest(req, ingestBody)
if err != nil {
fmt.Println(err)
}
return fmt.Sprintf("%s\n", requestDump)
}
//Unique returns unique elements in the string
func Unique(slice []string) []string {
// create a map with all the values as key
uniqMap := make(map[string]struct{})
for _, v := range slice {
uniqMap[v] = struct{}{}
}
// turn the map keys into a slice
uniqSlice := make([]string, 0, len(uniqMap))
for v := range uniqMap {
uniqSlice = append(uniqSlice, v)
}
return uniqSlice
}