Example #1
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal int OnRequest(byte[] receiveBuffer, int bytesReceived, bool internalRequest)
        {
            string proxyRequest          = wwwProxy_.defaultEncoding_.GetString(receiveBuffer, 0, bytesReceived);
            int    processedRequestBytes = 0;

            wwwProxy_.log_.Write("Inbound.OnRequest()", proxyRequest);

            Match httpMatch = Regex.Match(proxyRequest, "^([A-Z]+)\\s+(\\S*)?\\s+HTTP/\\d.\\d\r$", RegexOptions.IgnoreCase | RegexOptions.Multiline);

            if (httpMatch.Success)
            {
                string defaultCharset = "iso-8859-1";
                string charset        = defaultCharset;

                string httpVerb = httpMatch.Groups[1].Value;

                if (httpVerb != "CONNECT")
                {
                    Match getEndMatch = Regex.Match(proxyRequest, "\r\n\r\n", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                    if (getEndMatch.Success)
                    {
                        string requestRaw = proxyRequest.Substring(0, getEndMatch.Index);
                        string postRaw    = null;
                        processedRequestBytes = getEndMatch.Index + 4;

                        Match contentEncodingTypeMatch = Regex.Match(proxyRequest, "^Content-Type:\\s+\\S+?\\s*;\\s*charset=(\\S+)?", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        if (contentEncodingTypeMatch.Success)
                        {
                            charset = contentEncodingTypeMatch.Groups[1].Value.ToLower();
                        }

                        Encoding requestEncoding = null;
                        try
                        {
                            requestEncoding = Encoding.GetEncoding(charset);
                        }
                        catch (ArgumentException)
                        {
                            requestEncoding = wwwProxy_.defaultEncoding_;
                        }

                        Match contentLengthMatch = Regex.Match(requestRaw, "^Content-Length:\\s+(\\d+)[ \t]*[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        if (contentLengthMatch.Success)
                        {
                            int contentsLength = Convert.ToInt32(contentLengthMatch.Groups[1].Value);
                            if (proxyRequest.Length >= processedRequestBytes + contentsLength)
                            {
                                postRaw = requestEncoding.GetString(receiveBuffer, processedRequestBytes, contentsLength);
                                processedRequestBytes += contentsLength;

                                for (int i = processedRequestBytes; i < bytesReceived; ++i)
                                {
                                    if ((receiveBuffer[i] == '\r') || (receiveBuffer[i] == '\n'))
                                    {
                                        processedRequestBytes++;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                requestRaw = null;
                                postRaw    = null;
                            }
                        }

                        if (requestRaw != null)
                        {
                            requestRaw = Regex.Replace(requestRaw, "([A-Z]+)\\s+([a-zA-Z]+://.*?/)(.*?)\\s+(HTTP/\\d.\\d)", "$1 /$3 $4", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                            requestRaw = Regex.Replace(requestRaw, "^Accept-Encoding:\\s+(.*)?[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                            requestRaw = Regex.Replace(requestRaw, "^Content-Length:\\s+(.*)?[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                            requestRaw = Regex.Replace(requestRaw, "^Proxy-Connection:\\s+(.*)?[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                            requestRaw = requestRaw.TrimEnd(" \t\r\n".ToCharArray());

                            Match hostMatch = Regex.Match(requestRaw, "^Host:\\s+(\\S*)?", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                            if (hostMatch.Success)
                            {
                                string host = hostMatch.Groups[1].Value;
                                string port = ssl_ ? "443" : "80";

                                Match portMatch = Regex.Match(host, "(:)(\\d{1,5})");
                                if (portMatch.Success)
                                {
                                    port = host.Substring(portMatch.Groups[2].Index, portMatch.Groups[2].Length);
                                    host = host.Substring(0, portMatch.Groups[1].Index);
                                }

                                ProxyRequest request = new ProxyRequest();
                                request.inbound_ = this;
                                request.ssl_     = ssl_;
                                request.header_  = requestRaw;
                                request.data_    = postRaw;

                                Outbound sendOutbound = null;
                                currentOutboundsMutex_.WaitOne();
                                foreach (Outbound o in currentOutbounds_.Keys)
                                {
                                    if ((o.host_ == host) &&
                                        (o.port_ == Convert.ToUInt16(port)) &&
                                        (currentOutbounds_[o] == null))
                                    {
                                        sendOutbound         = o;
                                        currentOutbounds_[o] = request;
                                        break;
                                    }
                                }
                                currentOutboundsMutex_.ReleaseMutex();

                                if (sendOutbound == null)
                                {
                                    sendOutbound = new Outbound(wwwProxy_, this, ssl_, host, Convert.ToUInt16(port));

                                    currentOutboundsMutex_.WaitOne();
                                    currentOutbounds_.Add(sendOutbound, request);
                                    currentOutboundsMutex_.ReleaseMutex();
                                }

                                if (!internalRequest)
                                {
                                    wwwProxy_.OnRequest(request);
                                }
                                else
                                {
                                    wwwProxy_.Pass(request);
                                }
                                StartKeepAliveTimer();
                            }
                        }
                        else
                        {
                            processedRequestBytes = 0;
                        }
                    }
                }
                else
                {
                    string connectHost = httpMatch.Groups[2].Value;

                    string host = connectHost;
                    string port = "443";

                    Match portMatch = Regex.Match(host, "(:)(\\d{1,5})");
                    if (portMatch.Success)
                    {
                        port = host.Substring(portMatch.Groups[2].Index, portMatch.Groups[2].Length);
                        host = host.Substring(0, portMatch.Groups[1].Index);
                    }

                    Outbound outbound = new Outbound(wwwProxy_, this, true, host, Convert.ToUInt16(port));

                    currentOutboundsMutex_.WaitOne();
                    currentOutbounds_.Add(outbound, null);
                    currentOutboundsMutex_.ReleaseMutex();

                    Match connectEndMatch = Regex.Match(proxyRequest, "\r\n\r\n", RegexOptions.Multiline);
                    if (connectEndMatch.Success)
                    {
                        processedRequestBytes = connectEndMatch.Index + 4;
                    }

                    byte[] sslResponseBytes = wwwProxy_.defaultEncoding_.GetBytes("HTTP/1.0 200 OK\r\n\r\n");
                    Send(sslResponseBytes, 0, sslResponseBytes.Length);

                    ssl_ = true;
                    sslNetworkStream_ = new NetworkStream(inboundSocket_);
                    sslStream_        = new SslStream(sslNetworkStream_, false, new RemoteCertificateValidationCallback(OnRemoteCertificateValidation));

                    X509Certificate serverCertificate = new X509Certificate((wwwProxy_.certificate_ != null) ? wwwProxy_.certificate_ : "WwwProxy.cer");
                    sslStream_.AuthenticateAsServer(serverCertificate);
                }
            }
            else
            {
                int lineEnd = proxyRequest.IndexOf("\r\n");
                throw new Exception("Unhandled Request \"" + proxyRequest.Substring(0, (lineEnd > 0) ? lineEnd : proxyRequest.Length) + "\"");
            }

            return(processedRequestBytes);
        }
Example #2
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal void Complete(ProxyRequest request)
        {
            Outbound sendOutbound = null;

            try
            {
                currentOutboundsMutex_.WaitOne();
                foreach (Outbound o in currentOutbounds_.Keys)
                {
                    if (currentOutbounds_[o] == request)
                    {
                        sendOutbound = o;
                        break;
                    }
                }
                currentOutboundsMutex_.ReleaseMutex();
            }
            catch (ObjectDisposedException)
            {
            }

            request.completedHeader_ = request.header_;
            if (request.data_ != null)
            {
                request.completedHeader_ += "\r\nContent-Length: " + Convert.ToString(request.data_.Length) + "\r\n\r\n" + request.data_;
            }
            else
            {
                request.completedHeader_ += "\r\n\r\n";
            }

            if (sendOutbound != null)
            {
                if (sendOutbound.useRemoteProxy_)
                {
                    Match noUrlMatch = Regex.Match(request.completedHeader_, "([A-Z]+)\\s+/(.*?)\\s+(HTTP/\\d.\\d)", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                    if (noUrlMatch.Success)
                    {
                        Match hostMatch = Regex.Match(request.completedHeader_, "^Host:\\s+(\\S*)?", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        if (hostMatch.Success)
                        {
                            string host = hostMatch.Groups[1].Value;

                            string insert = (sendOutbound.ssl_ ? "https://" : "http://") + host + "/";
                            request.completedHeader_ = Regex.Replace(request.completedHeader_,
                                                                     "([A-Z]+)\\s+/(.*)\\s+(HTTP/\\d.\\d)",
                                                                     "$1 " + insert + "$2 $3", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        }
                    }
                }

                if (wwwProxy_.ntlmEnabled_)
                {
                    MatchCollection basicCredentials = Regex.Matches(request.completedHeader_,
                                                                     "^(Proxy-)*Authorization:\\s+Basic\\s+([a-zA-Z0-9=]*)[ \t]*[\r\n]*",
                                                                     RegexOptions.IgnoreCase | RegexOptions.Multiline);
                    if (basicCredentials.Count > 0)
                    {
                        Match urlMatch = Regex.Match(request.completedHeader_, "([A-Z]+)\\s+(.*?)\\s+HTTP/\\d.\\d\r$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        if (urlMatch.Success)
                        {
                            string ntlmSite = sendOutbound.host_ + ":" + sendOutbound.port_;
                            string ntlmPath = urlMatch.Groups[2].Value;

                            INtlm wwwProxyNtlm = null;

                            try
                            {
                                wwwProxy_.ntlmListMutex_.WaitOne();

                                foreach (INtlm w in wwwProxy_.ntlmList_)
                                {
                                    if ((w.Site == ntlmSite) && (w.Path == ntlmPath))
                                    {
                                        foreach (Match basicCredentialsMatch in basicCredentials)
                                        {
                                            if ((w.Type == basicCredentialsMatch.Groups[1].Value) ||
                                                ((w.Type == "WWW") && (basicCredentialsMatch.Groups[1].Value == "")))
                                            {
                                                w.Basic      = basicCredentialsMatch.Groups[2].Value;
                                                wwwProxyNtlm = w;
                                                break;
                                            }
                                        }

                                        if (wwwProxyNtlm != null)
                                        {
                                            break;
                                        }
                                    }
                                }

                                if (wwwProxyNtlm == null)
                                {
                                    foreach (INtlm w in wwwProxy_.ntlmList_)
                                    {
                                        if ((w.Site == ntlmSite) && (w.Basic != null))
                                        {
                                            foreach (Match basicCredentialsMatch in basicCredentials)
                                            {
                                                if ((w.Basic == basicCredentialsMatch.Groups[2].Value) &&
                                                    ((w.Type == basicCredentialsMatch.Groups[1].Value) ||
                                                     ((w.Type == "WWW") && (basicCredentialsMatch.Groups[1].Value == ""))))
                                                {
                                                    INtlm cloneWwwProxyNtlm = wwwProxy_.ntlmFactory_.CreateInstance();
                                                    if (cloneWwwProxyNtlm != null)
                                                    {
                                                        cloneWwwProxyNtlm.Site  = ntlmSite;
                                                        cloneWwwProxyNtlm.Path  = ntlmPath;
                                                        cloneWwwProxyNtlm.Type  = w.Type;
                                                        cloneWwwProxyNtlm.Basic = w.Basic;
                                                        wwwProxy_.ntlmList_.Add(cloneWwwProxyNtlm);
                                                        wwwProxyNtlm = cloneWwwProxyNtlm;
                                                    }
                                                    break;
                                                }
                                            }
                                            if (wwwProxyNtlm != null)
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (wwwProxyNtlm != null)
                                {
                                    string[] credentials = wwwProxy_.defaultEncoding_.GetString(Convert.FromBase64String(wwwProxyNtlm.Basic)).Split(':');

                                    string ntlmNegotiate = null;
                                    string domain        = sendOutbound.host_;
                                    string username      = credentials[0];
                                    string password      = credentials[1];

                                    if (username.Contains("\\"))
                                    {
                                        int domainUsernameSeparator = username.IndexOf('\\');
                                        if ((domainUsernameSeparator > 0) && (domainUsernameSeparator < (username.Length - 1)))
                                        {
                                            domain   = username.Substring(0, domainUsernameSeparator);
                                            username = username.Substring(username.IndexOf('\\') + 1);
                                        }
                                    }

                                    wwwProxyNtlm.Initialise(domain, username, password);
                                    ntlmNegotiate = wwwProxyNtlm.Continue(null);
                                    if (ntlmNegotiate == null)
                                    {
                                        ntlmNegotiate = "???";
                                    }
                                    string authReplace = "^(" + (wwwProxyNtlm.Type == "Proxy" ? "Proxy-" : "") +
                                                         "Authorization:\\s+)Basic\\s+[a-zA-Z0-9=]+[ \t]*([\r\n]*)";
                                    request.completedHeader_ = Regex.Replace(request.completedHeader_,
                                                                             authReplace,
                                                                             "${1}NTLM " + ntlmNegotiate + "${2}",
                                                                             RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                }
                            }
                            finally
                            {
                                wwwProxy_.ntlmListMutex_.ReleaseMutex();
                            }
                        }
                    }
                }

                wwwProxy_.log_.Write("Inbound.Complete()", request.completedHeader_);

                sendOutbound.Connect();

                try
                {
                    sendOutbound.Send(request);
                }
                catch (IOException)
                {
                }
                catch (SocketException)
                {
                }
            }
        }