/* * * */ 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); }
/* * * */ 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); }