/*
         *
         *
         */
        private void SendRequest2RedirectLocation(RequestObj pRequestObj)
        {
            String lRedirectLocationHTTPS = pRequestObj.ServerWebResponse.GetResponseHeader("Location");
            String lRedirectLocationHTTP  = pRequestObj.getRequestedURL();

            try { RedirectCache.Instance.addElement(lRedirectLocationHTTP, lRedirectLocationHTTPS); } catch { }

            Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Http2Https3XXSameURL \"{0}\" -> \"{1}\"", lRedirectLocationHTTP, lRedirectLocationHTTPS), Logging.Level.DEBUG, pRequestObj.Counter);


            // Close the preceding WebResponse (stream & headers)
            pRequestObj.ServerResponseHeaders.Clear();

            if (pRequestObj.ServerWebResponse != null)
            {
                pRequestObj.ServerWebResponse.Close();
            }

            RequestObj lTmpReqObj = (RequestObj)pRequestObj.Clone();
            Uri        lTmpUri    = new Uri(lRedirectLocationHTTPS);

            lTmpReqObj.Scheme = lTmpUri.Scheme;
            lTmpReqObj.Host   = lTmpUri.Host;
            lTmpReqObj.Path   = lTmpUri.PathAndQuery;
            if (lTmpReqObj.ClientRequestHeaders.ContainsKey("host"))
            {
                lTmpReqObj.ClientRequestHeaders.Remove("host");
                lTmpReqObj.ClientRequestHeaders.Add("host", lTmpReqObj.Host);
            }
            lTmpReqObj.Counter++;


            this.DoHttpProcessing(lTmpReqObj);

            pRequestObj.ServerWebResponse     = lTmpReqObj.ServerWebResponse;
            pRequestObj.ServerResponseHeaders = lTmpReqObj.ServerResponseHeaders;
        }
        /*
         *
         *
         */
        public void HandleClientRequest(RequestObj pRequestObj)
        {
            String lHTTPRequestString = pRequestObj.ClientStreamReader.ReadLine();

            if (String.IsNullOrEmpty(lHTTPRequestString))
            {
                throw new Exception("Client request stream corrupted.");
            }

            // Read the request headers from the client and copy them to the request settings
            // Set values : METHOD scheme://host/Path
            Logging.LogMessage(String.Format("HTTPClientRequest.HandleClientRequest() : HTTP Request string: \"{0}\"", lHTTPRequestString), Logging.Level.DEBUG, pRequestObj.Counter);
            pRequestObj.parseRequestString(lHTTPRequestString);
            this.ReadRequestHeadersFromClient(pRequestObj);

            pRequestObj.Host   = pRequestObj.ClientRequestHeaders["host"].ToString();
            pRequestObj.Scheme = "http";


            /*
             * Verify if request parameters are correct.
             */
            if (!Regex.Match(pRequestObj.Method.ToLower(), @"^\s*(get|put|post|head|delete|trace|options|connect)\s*$").Success)
            {
                throw new WebException("Client request contains an unsupproted request method");
            }


            String lRequestedURL = String.Format("{0}://{1}{2}", pRequestObj.Scheme, pRequestObj.Host, pRequestObj.Path);



            /*
             *   If HTTP request was redirected to an other URL in a previous request
             *   replace current request with the redirect location
             */
            if (RedirectCache.Instance.NeedsRequestBeMapped(lRequestedURL))
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.HandleClientRequest() : REDIRECT(301/302) from \"{0}\" to \"{1}\"", lRequestedURL, RedirectCache.Instance.GetElement(lRequestedURL).URL), Logging.Level.INFO, pRequestObj.Counter);

                // DO SSL STRIPPING THINGS HERE !!!!
                // Replace the URL by the URL saved in the cache ...
                RedirectHost lTmpHost = RedirectCache.Instance.GetElement(pRequestObj.getRequestedURL());

                pRequestObj.Method = "GET";
                pRequestObj.Scheme = lTmpHost.Scheme;
                pRequestObj.Host   = lTmpHost.Host;
                pRequestObj.Path   = lTmpHost.Path;

                lTmpHost.IncCounter();
            } // if (RedirectCac...


            /*
             * If HTTP request was answered with an HSTS server response header
             * conduct an HTTPS request instead of HTTP
             */
            else if (HSTSCache.Instance.GetElement(pRequestObj.Host) != null)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.HandleClientRequest() : HSTS protocol replacement : http://{0} -> https://{0} \n", pRequestObj.Host), Logging.Level.DEBUG, pRequestObj.Counter);
                pRequestObj.Scheme = "https";
            } // if (HSTSCache...


            try
            {
                /*
                 * Forward request according to the URL defined
                 * in the command line parameter.
                 */
                if (!String.IsNullOrEmpty(Config.RedirectToURL) && pRequestObj.Method.ToLower() == "get")
                {
                    HTTPRedirect.getInstance().processRequest(pRequestObj.ClientStream, Config.RedirectToURL, pRequestObj.ClientRequestHeaders);
                }
                else
                {
                    this.DoHttpProcessing(pRequestObj);
                }
            }
            catch (WebException lEx)
            {
                /*
                 * 1. Sending server response
                 */
                var lResponse = lEx.Response as HttpWebResponse;
                if (lResponse != null && lResponse.StatusCode != HttpStatusCode.OK)
                {
                    String ErrorCode = String.Format("HTTP/{0} {1} {2}\n", lResponse.ProtocolVersion, (int)lResponse.StatusCode, lResponse.StatusDescription);
                    pRequestObj.ClientStream.Write(Encoding.ASCII.GetBytes(ErrorCode), 0, ErrorCode.Length);
                }
                else
                {
                    String ErrorCode = String.Format("HTTP/1.1 500 Internal server error\n");
                    pRequestObj.ClientStream.Write(Encoding.ASCII.GetBytes(ErrorCode), 0, ErrorCode.Length);
                } // if (lRespon...

                /*
                 * 2. Sending server response headers
                 */
                if (lEx.Response != null && lEx.Response.Headers != null && lEx.Response.Headers.Count > 0)
                {
                    foreach (String la in lEx.Response.Headers.AllKeys)
                    {
                        String lResp = String.Format("{0}: {1}\n", la, lEx.Response.Headers[la]);
                        pRequestObj.ClientStream.Write(Encoding.ASCII.GetBytes(lResp), 0, lResp.Length);
                    } // foreach (Stri...
                }     // if (lEx.Resp ...

                pRequestObj.ClientStream.Write(Encoding.ASCII.GetBytes("\n"), 0, 1);

                /*
                 * 3. Sending server response body
                 */
                try
                {
                    var resp = new StreamReader(lEx.Response.GetResponseStream()).ReadToEnd();
                    pRequestObj.ClientStream.Write(Encoding.ASCII.GetBytes(resp), 0, resp.Length);
                }
                catch (Exception lEx2)
                {
                    Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing(EXCEPTION2) : {0} -> {1} \n{2}", pRequestObj.getRequestedURL(), lEx.Message, lEx.StackTrace), Logging.Level.ERROR, pRequestObj.Counter);
                }
            }
            catch (Exception lEx)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing(EXCEPTION) : {0} -> {1} \n{2}", pRequestObj.getRequestedURL(), lEx.Message, lEx.StackTrace), Logging.Level.ERROR, pRequestObj.Counter);
            }
            finally
            {
                if (pRequestObj.ClientStreamReader != null)
                {
                    pRequestObj.ClientStreamReader.Close();
                }

                if (pRequestObj.ClientStream != null)
                {
                    pRequestObj.ClientStream.Close();
                }

                if (pRequestObj.ServerWebResponse != null)
                {
                    pRequestObj.ServerWebResponse.Close();
                }
            }
        }
        /*
         *
         *
         */
        public void DoHttpProcessing(RequestObj pRequestObj)
        {
            String lHTTPRequestString = String.Empty;

            Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : Client {0} requested URL : \"{1}\"", pRequestObj.SrcIP, pRequestObj.getRequestedURL()), Logging.Level.INFO, pRequestObj.Counter);


            /*
             * Process HTTP request.
             * 1. Detect HTTP Redirect requests
             * 2. Cache new HTTP Redirect locations
             * 3. Recognize incoming client requests that need to be SSL-Stripped
             * 4. Process reqular HTTP requests
             *
             *
             *
             * 1. Client requests a SSL-Stripping page found in the RedirectCache
             *    The requested URL previously was detected as a "HTTP 301/302 Redirect" to a SSL/TLS protected web site.
             *    Skip the HTTP/Redirect part and directly proxy the data from the SSL/TLS protected website to the user.
             *
             *    Format : SCHEME://HOST
             */



            // 2. Send client request URL to server and parse response headers
            pRequestObj.ServerResponseHeaders.Clear();
            cServerRequestHandler.sendRequestAndParseServerResponseHeader(pRequestObj);

            RedirectType lRedirType = this.DetermineRedirectType(pRequestObj);



            /*
             * The HTTP client request triggers a regular HTML data response.
             * 1. Transfer the server response (Server response string, headers, data)
             */
            if (lRedirType == RedirectType.Http2http2XX)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Http2http2XX \"{0}\" -> \"-\"", pRequestObj.getRequestedURL()), Logging.Level.DEBUG, pRequestObj.Counter);


                /*
                 * The HTTP client request triggers a request to a HTTP URL
                 * 1. Transfer the server response (Server response string, headers, data)
                 */
            }
            else if (lRedirType == RedirectType.Http2Http3XX)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Http2Http3XX \"{0}\" -> \"{1}\"", pRequestObj.getRequestedURL(), pRequestObj.ServerWebResponse.GetResponseHeader("Location")), Logging.Level.DEBUG, pRequestObj.Counter);


                /*
                 * The HTTP client request triggers a request to a HTTP URL
                 * 1. Cache the HTTP/HTTPS mapping
                 * 2. Replace the "https" scheme in the redirect location by "http"
                 * 3. Transfer the server response (Server response string, headers, data)
                 */
            }
            else if (lRedirType == RedirectType.Http2Https3XXDifferentURL)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Http2Http3XXDifferentURL \"{0}\" -> \"{1}\"", pRequestObj.getRequestedURL(), pRequestObj.ServerWebResponse.GetResponseHeader("Location")), Logging.Level.DEBUG, pRequestObj.Counter);
                this.SendRequest2RedirectLocation(pRequestObj);



                /*
                 * 1. Resend the same request again to the same URL but with "https" scheme instead of "http"
                 * 2. Transfer the server response (Server response string, headers, data)
                 */
            }
            else if (lRedirType == RedirectType.Http2Https3XXSameURL)
            {
                // Save redirect information in cache

                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Http2Https3XXSameURL \"{0}\" -> \"{1}\"", pRequestObj.getRequestedURL(), pRequestObj.ServerWebResponse.GetResponseHeader("Location")), Logging.Level.DEBUG, pRequestObj.Counter);
                this.SendRequest2RedirectLocation(pRequestObj);


                /*
                 * The HTTP client request triggers a regular HTML data response.
                 * 1. Transfer the server response (Server response string, headers, data)
                 */
            }
            else if (lRedirType == RedirectType.Https2Http2XX)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Https2Http2XX"), Logging.Level.DEBUG, pRequestObj.Counter);



                /*
                 * This should never happen!!
                 * We're lost in an endless loop!
                 */
            }
            else if (lRedirType == RedirectType.Https2Https3XXSameURL)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Https2HttpsRedirectSameURL\n\n\n\nHOOOOONK\n\n\n"), Logging.Level.DEBUG, pRequestObj.Counter);

                String lLogData = String.Format("HTTPClientRequest.DoHttpProcessing() : \"{0}\" -> \"{1}\"", pRequestObj.getRequestedURL(), pRequestObj.ServerResponseHeaders.Find(item => item.Item1 == "Location"));

                Logging.LogMessage(lLogData, Logging.Level.DEBUG);
            }
            else if (lRedirType == RedirectType.Https2Https3XXDifferentURL)
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Https2HttpsRedirectDiffrentURL"), Logging.Level.DEBUG, pRequestObj.Counter);

                /*
                 * The HTTP client request triggers a request to a HTTP URL
                 * 1. Cache the HTTP/HTTPS mapping
                 * 2. Replace the "https" scheme in the redirect location by "http"
                 * 3. Transfer the server response (Server response string, headers, data)
                 */
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE Https2Https3XXDifferentURL \"{0}\" -> \"{1}\"", pRequestObj.getRequestedURL(), pRequestObj.ServerWebResponse.GetResponseHeader("Location")), Logging.Level.DEBUG, pRequestObj.Counter);
                this.SendRequest2RedirectLocation(pRequestObj);


                /*
                 * This should never happen!!
                 * No clue what to do at this point!
                 */
            }
            else
            {
                Logging.LogMessage(String.Format("HTTPClientRequest.DoHttpProcessing() : TYPE definition error for URL \"{0}\" ", pRequestObj.getRequestedURL()), Logging.Level.DEBUG, pRequestObj.Counter);
            }

            cServerRequestHandler.sendServerResponse2Client(pRequestObj);

            String lPipeData = lPipeData = String.Format("HTTPClientRequest.DoHttpProcessing() : TCP||{0}||{1}||{2}||{3}||{4}||{5}\r\n", pRequestObj.SrcMAC, pRequestObj.SrcIP, pRequestObj.SrcPort, Config.RemoteHostIP, Config.RemoteHostPort, pRequestObj.HTTPLogData);

            Program.WriteToPipe(lPipeData);
        }
Exemple #4
0
        /*
         *
         *
         */
        public void sendRequestAndParseServerResponseHeader(RequestObj pRequestObj)
        {
            char[]       lPostBuffer;
            int          lPOSTBytesRead  = 0;
            int          lTotalBytesRead = 0;
            StreamWriter lSW             = null;
            String       lTmpStr         = String.Empty;
            String       lTmpBuf         = String.Empty;
            String       lPOSTData       = String.Empty;

            Logging.LogMessage(String.Format("HTTPClientRequest.sendRequestAndParseServerResponseHeader() : Requesting URL \"{0}\"", pRequestObj.getRequestedURL()), Logging.Level.DEBUG, pRequestObj.Counter);


            /*
             * Setup the http request to send on behalf of the actual client.
             * Neutralize the server certificate validation.
             */
            ServicePointManager.ServerCertificateValidationCallback = delegate { return(true); };

            pRequestObj.ServerWebRequest                        = (HttpWebRequest)HttpWebRequest.Create(pRequestObj.getRequestedURL());
            pRequestObj.ServerWebRequest.Method                 = pRequestObj.Method;
            pRequestObj.ServerWebRequest.ProtocolVersion        = System.Net.HttpVersion.Version10;
            pRequestObj.ServerWebRequest.Timeout                = 10000;
            pRequestObj.ServerWebRequest.Proxy                  = null;
            pRequestObj.ServerWebRequest.KeepAlive              = false;
            pRequestObj.ServerWebRequest.AllowAutoRedirect      = false;
            pRequestObj.ServerWebRequest.AutomaticDecompression = DecompressionMethods.None;

            this.SetClientRequestHTTPHeaders(pRequestObj.ClientRequestHeaders, ref pRequestObj.ServerWebRequest);



            /*
             * Send POST data to remote server
             */
            if (pRequestObj.Method.ToUpper() == "POST")
            {
                lPostBuffer     = new char[pRequestObj.ClientRequestContentLen];
                lTotalBytesRead = 0;
                lSW             = new StreamWriter(pRequestObj.ServerWebRequest.GetRequestStream());

                while (lTotalBytesRead < pRequestObj.ClientRequestContentLen && (lPOSTBytesRead = pRequestObj.ClientStreamReader.ReadBlock(lPostBuffer, 0, pRequestObj.ClientRequestContentLen)) > 0)
                {
                    lTmpStr = new string(lPostBuffer);

                    lTotalBytesRead += lPOSTBytesRead;
                    lSW.Write(lPostBuffer, 0, lPOSTBytesRead);

                    lTmpBuf += lTmpStr;
                } // while (lTotalBytes...

                if (lSW != null)
                {
                    lSW.Close();
                }

                if (lTmpBuf != null && lTmpBuf.Length > 0)
                {
                    lPOSTData = lTmpBuf.ToString();
                }
            } // if (lMethod.To...


            // Read and parse server response headers
            // Build HTTP request data string

            pRequestObj.ServerWebResponse = (HttpWebResponse)pRequestObj.ServerWebRequest.GetResponse();
            this.ProcessServerResponseHeaders(pRequestObj);

            // Create Data log string
            pRequestObj.HTTPLogData = String.Empty;
            foreach (String lKey in pRequestObj.ServerWebResponse.Headers.AllKeys)
            {
                pRequestObj.HTTPLogData += String.Format("..{0}: {1}", lKey, pRequestObj.ServerWebRequest.Headers[lKey]);
            }

            pRequestObj.HTTPLogData += String.Format("....{0}", lPOSTData);
        }