예제 #1
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public INtlm CreateInstance()
        {
            INtlm ntlm = null;

            if (loadedAssembly_ != null)
            {
                foreach (Type t in loadedAssembly_.GetTypes())
                {
                    if (t.IsClass)
                    {
                        foreach (Type i in t.GetInterfaces())
                        {
                            if (i.FullName == "WwwProxy.INtlm")
                            {
                                try
                                {
                                    ntlm = (INtlm)System.Activator.CreateInstance(t);
                                }
                                catch (Exception e)
                                {
                                    ntlm = null;
                                    WwwProxy.Instance.OnError(null, null, e, e.Message);
                                }
                                break;
                            }
                        }
                    }

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

            return(ntlm);
        }
예제 #2
0
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private int OnResponse(byte[] receiveBuffer, int bytesReceived, bool bConnectionClosed)
        {
            string proxyResponse          = wwwProxy_.defaultEncoding_.GetString(receiveBuffer, 0, bytesReceived);
            int    processedResponseBytes = 0;

            wwwProxy_.log_.Write("Outbound.OnResponse()", proxyResponse);

            string header   = null;
            string contents = null;

            byte[] contentsBytes = null;

            string defaultCharset = "iso-8859-1";
            string charset        = defaultCharset;

            Match httpResponseMatch = Regex.Match(proxyResponse, "^HTTP/\\d\\.\\d\\s+(\\d+)\\s+", RegexOptions.IgnoreCase);

            if (httpResponseMatch.Success)
            {
                ushort httpResponseCode = Convert.ToUInt16(httpResponseMatch.Groups[1].Value);
                if ((httpResponseCode >= 100) && (httpResponseCode <= 199))
                {
                    inbound_.StopKeepAliveTimer();
                    inbound_.Send(receiveBuffer, 0, bytesReceived);
                    processedResponseBytes = bytesReceived;
                }
                else
                {
                    int contentsIndex = 0;

                    for (int i = 0; i < (proxyResponse.Length - 3); ++i)
                    {
                        if ((receiveBuffer[i] == '\r') &&
                            (receiveBuffer[i + 1] == '\n') &&
                            (receiveBuffer[i + 2] == '\r') &&
                            (receiveBuffer[i + 3] == '\n'))
                        {
                            contentsIndex = i + 4;
                            header        = wwwProxy_.defaultEncoding_.GetString(receiveBuffer, 0, i);
                            contentsBytes = new byte[bytesReceived - (contentsIndex)];
                            Array.Copy(receiveBuffer, contentsIndex, contentsBytes, 0, bytesReceived - (contentsIndex));
                            break;
                        }
                    }

                    if (header != null)
                    {
                        Match connectionCloseMatch     = Regex.Match(header, "^(Proxy-)*(Connection)+:\\s+close", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        Match contentEncodingTypeMatch = Regex.Match(header, "^Content-Type:\\s+\\S+?\\s*;\\s*charset=(\\S+)?", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        Match contentLengthMatch       = Regex.Match(header, "^Content-Length:\\s+(\\d+)[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        Match contentTextTypeMatch     = Regex.Match(header, "^Content-Type:\\s+text|application/x-javascript", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                        Match transferEncodingMatch    = Regex.Match(header, "^Transfer-Encoding:\\s+chunked\\s*[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);

                        if (contentEncodingTypeMatch.Success)
                        {
                            charset = contentEncodingTypeMatch.Groups[1].Value.ToLower();
                        }

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

                        if (connectionCloseMatch.Success)
                        {
                            responseCloseInbound_ = true;
                        }

                        completableResponse_ = contentTextTypeMatch.Success || (httpResponseCode >= 300);
                        if (!completableResponse_)
                        {
                            inbound_.StopKeepAliveTimer();
                            inbound_.Send(receiveBuffer, 0, bytesReceived);
                            processedResponseBytes = bytesReceived;
                        }
                        else
                        {
                            if (contentLengthMatch.Success)
                            {
                                int contentsLength = Convert.ToInt32(contentLengthMatch.Groups[1].Value);
                                if (contentsBytes.Length >= contentsLength)
                                {
                                    header = Regex.Replace(header, "^Content-Length:\\s+(\\d+)[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                    header = header.TrimEnd(" \t\r\n".ToCharArray());

                                    contents = responseEncoding.GetString(contentsBytes, 0, contentsBytes.Length);
                                    processedResponseBytes = contentsIndex + contentsLength;
                                }
                                else
                                {
                                    bytesRequired_ = contentsLength - contentsBytes.Length;
                                }
                            }
                            else if (transferEncodingMatch.Success)
                            {
                                int    deChunkingIndex = 0;
                                byte[] chunkedContents = new byte[contentsBytes.Length];
                                Array.Copy(contentsBytes, chunkedContents, contentsBytes.Length);

                                string deChunkedContents = "";

                                while (true)
                                {
                                    int chunkLengthEnd = -1;
                                    for (int i = deChunkingIndex; i < chunkedContents.Length; ++i)
                                    {
                                        if ((chunkedContents[i] == '\r') && (chunkedContents[i + 1] == '\n'))
                                        {
                                            chunkLengthEnd = i;
                                            break;
                                        }
                                    }
                                    if (chunkLengthEnd != -1)
                                    {
                                        int chunkLength = Convert.ToInt32(responseEncoding.GetString(chunkedContents,
                                                                                                     deChunkingIndex,
                                                                                                     chunkLengthEnd - deChunkingIndex).Trim(), 16);
                                        deChunkingIndex = chunkLengthEnd + 2;

                                        if (chunkLength != 0)
                                        {
                                            if (chunkedContents.Length >= (deChunkingIndex + chunkLength))
                                            {
                                                deChunkedContents += responseEncoding.GetString(chunkedContents, deChunkingIndex, chunkLength);
                                            }
                                            else
                                            {
                                                bytesRequired_    = (deChunkingIndex + chunkLength) - chunkedContents.Length;
                                                deChunkedContents = null;
                                            }
                                        }

                                        deChunkingIndex += chunkLength;
                                        while ((deChunkingIndex < chunkedContents.Length) &&
                                               ((chunkedContents[deChunkingIndex] == '\r') ||
                                                (chunkedContents[deChunkingIndex] == '\n')))
                                        {
                                            deChunkingIndex++;
                                        }

                                        if (chunkLength == 0)
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        deChunkedContents = null;
                                        break;
                                    }
                                }

                                if (deChunkedContents != null)
                                {
                                    header   = Regex.Replace(header, "^Transfer-Encoding:\\s+chunked(.*?)[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                    header   = header.TrimEnd(" \t\r\n".ToCharArray());
                                    contents = deChunkedContents;

                                    processedResponseBytes = contentsIndex + deChunkingIndex;
                                }
                            }
                            else
                            {
                                if (((connectionCloseMatch.Success) && (bConnectionClosed)) || (bConnectionClosed) ||
                                    (httpResponseCode == 204) || (httpResponseCode == 304)) // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
                                {
                                    contents = responseEncoding.GetString(contentsBytes, 0, contentsBytes.Length);
                                    processedResponseBytes = bytesReceived;
                                }
                            }
                        }

                        if (processedResponseBytes != 0)
                        {
                            if (completableResponse_)
                            {
                                header = Regex.Replace(header, "^Proxy-Connection:\\s+(.*)?[ \t]*[\r\n]*", "", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                header = header.TrimEnd(" \t\r\n".ToCharArray());
                            }

                            if ((httpResponseCode == 401) || (httpResponseCode == 407))
                            {
                                if (wwwProxy_.ntlmEnabled_)
                                {
                                    Match urlMatch = Regex.Match(request_.completedHeader_, "([A-Z]+)\\s+(.*?)\\s+HTTP/\\d.\\d\r$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                    if (urlMatch.Success)
                                    {
                                        try
                                        {
                                            wwwProxy_.ntlmListMutex_.WaitOne();

                                            string ntlmSite = host_ + ":" + port_;
                                            string ntlmPath = urlMatch.Groups[2].Value;

                                            Match wwwAuthenticateBasicMatch = Regex.Match(header, "^(WWW|Proxy)-Authenticate:\\s+Basic(.*)?[ \t]*[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                            if (wwwAuthenticateBasicMatch.Success)
                                            {
                                                List <INtlm> toRemove = new List <INtlm>();
                                                foreach (INtlm w in wwwProxy_.ntlmList_)
                                                {
                                                    if (w.Site == ntlmSite)
                                                    {
                                                        toRemove.Add(w);
                                                    }
                                                }

                                                foreach (INtlm w in toRemove)
                                                {
                                                    wwwProxy_.ntlmList_.Remove(w);
                                                }
                                            }

                                            INtlm wwwProxyNtlm = null;
                                            foreach (INtlm w in wwwProxy_.ntlmList_)
                                            {
                                                if ((w.Site == ntlmSite) && (w.Path == ntlmPath))
                                                {
                                                    wwwProxyNtlm = w;
                                                    break;
                                                }
                                            }

                                            Match wwwAuthenticateNegotiateMatch    = Regex.Match(header, "^(WWW|Proxy)-Authenticate:\\s+Negotiate[ \t]*[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                            Match wwwAuthenticateNTLMMatch         = Regex.Match(header, "^(WWW|Proxy)-Authenticate:\\s+NTLM[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                            Match wwwAuthenticateNTLMResponseMatch = Regex.Match(header, "^(WWW|Proxy)-Authenticate:\\s+NTLM\\s+([A-Za-z0-9+/=]*)[ \t]*[\r\n]*", RegexOptions.IgnoreCase | RegexOptions.Multiline);

                                            if (wwwAuthenticateNegotiateMatch.Success && wwwAuthenticateNTLMMatch.Success)
                                            {
                                                string authType = wwwAuthenticateNegotiateMatch.Groups[1].Value;

                                                header = Regex.Replace(header,
                                                                       "^(WWW|Proxy)-Authenticate:\\s+Negotiate[ \t]*[\r\n]*",
                                                                       "",
                                                                       RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                                header = Regex.Replace(header,
                                                                       "(^(WWW|Proxy)-Authenticate:\\s+)NTLM[ \t]*([\r\n]*)",
                                                                       "${1}Basic Realm=\"WwwProxy NTLM (" + authType + ")\"${3}",
                                                                       RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                                header = header.TrimEnd(" \t\r\n".ToCharArray());

                                                if (wwwProxyNtlm == null)
                                                {
                                                    wwwProxyNtlm = wwwProxy_.ntlmFactory_.CreateInstance();
                                                    if (wwwProxyNtlm != null)
                                                    {
                                                        wwwProxyNtlm.Site = ntlmSite;
                                                        wwwProxyNtlm.Path = ntlmPath;
                                                        wwwProxyNtlm.Type = authType;
                                                        wwwProxy_.ntlmList_.Add(wwwProxyNtlm);
                                                    }
                                                }
                                                else
                                                {
                                                    wwwProxyNtlm.Reset();
                                                }
                                            }
                                            else if (wwwAuthenticateNTLMResponseMatch.Success)
                                            {
                                                string replacementAuth = "${1}" + wwwProxyNtlm.Continue(wwwAuthenticateNTLMResponseMatch.Groups[2].Value) + "${3}";
                                                request_.completedHeader_ = Regex.Replace(request_.completedHeader_,
                                                                                          "^((Proxy-)*Authorization:\\s+NTLM\\s+)[a-zA-Z0-9=]+[ \t]*([\r\n]*)",
                                                                                          replacementAuth,
                                                                                          RegexOptions.IgnoreCase | RegexOptions.Multiline);
                                                Send(request_);
                                                header = null;
                                            }
                                        }
                                        finally
                                        {
                                            wwwProxy_.ntlmListMutex_.ReleaseMutex();
                                        }
                                    }
                                }
                            }

                            if (header != null)
                            {
                                response_              = new ProxyResponse();
                                response_.encoding_    = responseEncoding;
                                response_.outbound_    = this;
                                response_.request_     = request_;
                                response_.completable_ = completableResponse_;
                                response_.ssl_         = ssl_;
                                response_.header_      = header;
                                response_.contents_    = contents;
                                wwwProxy_.OnResponse(response_);
                            }
                        }
                    }
                }
            }
            else
            {
                inbound_.StopKeepAliveTimer();
                inbound_.Send(receiveBuffer, 0, bytesReceived);
                processedResponseBytes = bytesReceived;

                bytesRequired_   = 0;
                processResponse_ = false;
            }

            return(processedResponseBytes);
        }
예제 #3
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)
                {
                }
            }
        }