123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- package main
- import (
- "bytes"
- "fmt"
- "io/ioutil"
- "log"
- "net/http"
- "net/http/httputil"
- "regexp"
- "strings"
- )
- //Zexpressions is the set of regexp being used by zardoz
- var Zexpressions = []string{
- `[[:alpha:]]{4,32}`, // alpha digit token
- `[ ]([A-Za-z0-9-_]{4,}\.)+\w+`, // domain name
- `[ ]/[A-Za-z0-9-_/.]{4,}[ ]`, // URI path (also partial)
- `[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}`, // IP address
- `[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}`, // UUID
- }
- func passAndLearn(resp *http.Response) error {
- ProxyFlow.response = resp
- ProxyFlow.seniority++
- req := ProxyFlow.request
- switch {
- case isAuth(resp):
- log.Println("401: We don't want to store credentials")
- case isError(resp):
- 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")
- resp.Header.Set("Cache-Control", "no-cache, no-store")
- log.Println("Filing inside bad class")
- feedRequest(req, "BAD")
- ControPlane.StatsTokens <- "DOWNGRADE"
- case isSuccess(resp):
- 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")
- resp.Header.Set("Cache-Control", "no-cache, no-store")
- switch {
- case isAuth(resp):
- log.Println("401: We don't want to store credentials")
- case isError(resp):
- log.Println("Filing inside bad class")
- feedRequest(req, "BAD")
- case isSuccess(resp):
- log.Println("Filing inside Good Class: ", resp.StatusCode)
- ControPlane.StatsTokens <- "UPGRADED"
- feedRequest(req, "GOOD")
- }
- return nil
- }
- func sanitizeHeaders(s string) string {
- var collect []string
- ss := strings.ToLower(s)
- for _, zregexp := range Zexpressions {
- re, rerr := regexp.Compile(zregexp)
- if rerr != nil {
- log.Println("Error Compiling regular expression: ", zregexp)
- }
- matched := re.FindAllString(ss, -1)
- if matched == nil {
- matched = []string{"null"}
- }
- collect = append(collect, matched...)
- }
- uMatched := Unique(collect)
- log.Println("Matched: ", uMatched)
- return strings.Join(uMatched, " ")
- }
- 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 {
- requestDump, err := httputil.DumpRequest(req, false)
- 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
- }
- func isSuccess(resp *http.Response) bool {
- return resp.StatusCode <= 299
- }
- func isAuth(resp *http.Response) bool {
- return resp.StatusCode == 401
- }
- func isError(resp *http.Response) bool {
- return resp.StatusCode >= 400 && resp.StatusCode != 401
- }
|