func defaultIcap(w icap.ResponseWriter, req *icap.Request) { h := w.Header() h.Set("ISTag", ISTag) h.Set("Service", "SquidBlocker default ICAP service") if *debug { fmt.Fprintln(os.Stderr, "Printing the full ICAP request") fmt.Fprintln(os.Stderr, req) fmt.Fprintln(os.Stderr, req.Request) } switch req.Method { case "OPTIONS": h.Set("Methods", "REQMOD, RESPMOD") h.Set("Options-TTL", "1800") h.Set("Allow", "204") h.Set("Preview", "0") h.Set("Transfer-Preview", "*") h.Set("Max-Connections", "4000") h.Set("This-Server", "Default ICAP url which bypass all requests adaptation") h.Set("X-Include", "X-Client-IP, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id, X-Server-IP") w.WriteHeader(200, nil, false) case "REQMOD": if *debug { fmt.Fprintln(os.Stderr, "Default REQMOD, you should use the apropriate ICAP URL") } w.WriteHeader(204, nil, false) case "RESPMOD": if *debug { fmt.Fprintln(os.Stderr, "Default RESPMOD, you should use the apropriate ICAP URL") } w.WriteHeader(204, nil, false) default: w.WriteHeader(405, nil, false) if *debug { fmt.Fprintln(os.Stderr, "Invalid request method") } } }
func filterByUrl(w icap.ResponseWriter, req *icap.Request) { h := w.Header() h.Set("ISTag", ISTag) h.Set("Service", "SquidBlocker filter ICAP service") if *debug { fmt.Fprintln(os.Stderr, "Printing the full ICAP request") fmt.Fprintln(os.Stderr, req) fmt.Fprintln(os.Stderr, req.Request) } switch req.Method { case "OPTIONS": h.Set("Methods", "REQMOD, RESPMOD") h.Set("Options-TTL", "1800") h.Set("Allow", "204") h.Set("Preview", "0") h.Set("Transfer-Preview", "*") h.Set("Max-Connections", "4000") h.Set("X-Include", "X-Client-IP, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id") w.WriteHeader(200, nil, false) case "REQMOD": // Check if the method is either OPTIONS\GET\POST\PUT etc // Also to analyse the request stucutre to verify what is the current one used // based on the RFC section at: http://tools.ietf.org/html/rfc7230#section-5.3 // Treat the CONNECT method in a special way due to the fact that it cannot actually be modified. checkhost := "" port := "0" answer := *defaultAnswer var err error if *debug { fmt.Fprintln(os.Stderr, "Default CASE. Request to host: "+req.Request.URL.Host+", Request Method: "+req.Request.Method) fmt.Fprintln(os.Stderr, "The full url from the ICAP client request: "+req.Request.URL.String()) } checkhost, port, err = net.SplitHostPort(req.Request.URL.Host) if err != nil { _ = err checkhost = req.Request.URL.Host } if port != "0" { if *debug { fmt.Fprintln(os.Stderr, "Rquest with port: "+port) } } if req.Request.Method == "CONNECT" && len(checkhost) > 0 && port != "0" { answer = check_tcp(checkhost, port) } else { answer = check(req.Request.URL.String()) } if *debug { fmt.Fprintln(os.Stderr, "ERRlog: reporting answer size => "+strconv.Itoa(len(answer))) fmt.Fprintln(os.Stderr, "ERRlog: reporitng answer => "+answer+", for =>"+req.Request.URL.String()) } // The next part comes to make sure that a DUNO respnse will be handled as the default answer/action if strings.HasPrefix(answer, "DUNO") { answer = *defaultAnswer + " rate=100 default_answer=yes" if *debug { fmt.Fprintln(os.Stderr, "ERRlog: reporting answer startsWith => \"DUNO\", taking default action") if len(*defaultAnswer) > 0 { fmt.Fprintln(os.Stderr, req.Request.URL.String()+" "+*defaultAnswer+" rate=40 default_answer=yes") } else { fmt.Fprintln(os.Stderr, req.Request.URL.String()+" OK state=DUNO") } } } if strings.HasPrefix(answer, "OK") { if *debug { fmt.Fprintln(os.Stderr, "OK response and sending 204 back") } w.WriteHeader(204, nil, false) return } if strings.HasPrefix(answer, "ERR") { if *debug { fmt.Fprintln(os.Stderr, "ERR response and sending 307 redirection back") } resp := new(http.Response) resp.Status = "307 SquidBlocker this url has been filtered!" resp.StatusCode = 307 resp.Proto = "HTTP/1.1" resp.ProtoMajor = 1 resp.ProtoMinor = 1 myMap := make(map[string][]string) //What if it is a connect request myMap["Location"] = append(myMap["Location"], *block_page+"?url="+url.QueryEscape(req.Request.URL.String())) resp.Header = myMap //resp.Body = ioutil.NopCloser(bytes.NewBufferString(body)) //resp.ContentLength = int64(len(body)) resp.Request = req.Request w.WriteHeader(200, resp, true) return } if *debug { fmt.Fprintln(os.Stderr, "Unknown asnwer and scenario, not adapting the request") } w.WriteHeader(204, nil, false) return case "RESPMOD": w.WriteHeader(204, nil, false) default: w.WriteHeader(405, nil, false) if *debug { fmt.Fprintln(os.Stderr, "Invalid request method") } } }