Esempio n. 1
0
        private void ExtractHeaderField(string headerField)
        {
            if (headerField.StartsWith("Host: "))  //look for the host
            {
                this.requestedHost = headerField.Substring(6).Trim();
                if (!this.ParentFrame.QuickParse)
                {
                    base.Attributes.Add("Requested Host", headerField.Substring(6).Trim());
                }
            }
            else if (headerField.StartsWith("User-Agent: ", StringComparison.OrdinalIgnoreCase))
            {
                this.userAgentBanner = headerField.Substring(12).Trim();
                if (!this.ParentFrame.QuickParse)
                {
                    base.Attributes.Add("User-Agent", this.userAgentBanner = headerField.Substring(12).Trim());
                }
            }
            else if (headerField.StartsWith("Server: ", StringComparison.OrdinalIgnoreCase))
            {
                this.serverBanner = headerField.Substring(8).Trim();
                if (!this.ParentFrame.QuickParse)
                {
                    this.Attributes.Add("Server banner", this.serverBanner = headerField.Substring(8).Trim());
                }
            }
            else if (headerField.StartsWith("Cookie: ", StringComparison.OrdinalIgnoreCase))
            {
                //http://www.w3.org/Protocols/rfc2109/rfc2109
                this.cookie = headerField.Substring(8).Trim();
                if (!this.ParentFrame.QuickParse)
                {
                    this.Attributes.Add("Cookie", this.cookie);
                }
            }
            else if (headerField.StartsWith("Set-Cookie: ", StringComparison.OrdinalIgnoreCase))
            {
                if (String.IsNullOrEmpty(this.cookie))
                {
                    this.cookie = headerField.Substring(12).Trim();
                }
                else
                {
                    this.cookie += "; " + headerField.Substring(12).Trim();
                }
                if (!this.ParentFrame.QuickParse)
                {
                    this.Attributes.Add("Cookie", this.cookie);
                }
            }
            else if (headerField.StartsWith("Content-Type: ", StringComparison.OrdinalIgnoreCase))
            {
                this.contentType = headerField.Substring(14).Trim();
            }
            else if (headerField.StartsWith("Content-Length: ", StringComparison.OrdinalIgnoreCase))
            {
                this.contentLength = Convert.ToInt32(headerField.Substring(16).Trim());
            }
            else if (headerField.StartsWith("Content-Encoding: ", StringComparison.OrdinalIgnoreCase))
            {
                this.contentEncoding = headerField.Substring(18).Trim();
            }
            else if (headerField.StartsWith("Transfer-Encoding: ", StringComparison.OrdinalIgnoreCase))
            {
                this.transferEncoding = headerField.Substring(19).Trim();
            }
            else if (headerField.StartsWith("WWW-Authenticate: ", StringComparison.OrdinalIgnoreCase) && headerField.Contains("realm=\""))
            {
                int realmStart = headerField.IndexOf("realm=\"") + 7;
                int realmEnd   = headerField.IndexOf('\"', realmStart);
                if (realmStart >= 0 && realmEnd > 0)
                {
                    this.wwwAuthenticateRealm = headerField.Substring(realmStart, realmEnd - realmStart).Trim();
                }
            }

            /*
             * else if(headerField.StartsWith("WWW-Authenticate: Basic realm=", StringComparison.OrdinalIgnoreCase))
             *  this.wwwAuth0enticateBasicRealm=headerField.Substring(31, headerField.Length-32);
             * */
            else if (headerField.StartsWith("Proxy-Authenticate: Basic realm=", StringComparison.OrdinalIgnoreCase))
            {
                this.wwwAuthenticateRealm = headerField.Substring(33, headerField.Length - 34).Trim();
            }
            else if (headerField.StartsWith("Authorization: Basic ", StringComparison.OrdinalIgnoreCase))
            {
                try {
                    string        base64string = headerField.Substring(21).Trim();
                    Byte[]        bArray       = Convert.FromBase64String(base64string);
                    StringBuilder sb           = new StringBuilder(bArray.Length);
                    foreach (byte b in bArray)
                    {
                        sb.Append((char)b);
                    }
                    //string s=System.Text.Encoding.Unicode.GetString(bArray);
                    string s = sb.ToString();
                    if (s.Contains(":"))
                    {
                        this.authorizationCredentialsUsername = s.Substring(0, s.IndexOf(':'));
                        if (s.IndexOf(':') + 1 < s.Length)
                        {
                            this.authorizationCredentailsPassword = s.Substring(s.IndexOf(':') + 1);
                        }
                        else
                        {
                            this.authorizationCredentailsPassword = "";
                        }
                    }
                }
                catch (Exception e) {
                    if (!this.ParentFrame.QuickParse)
                    {
                        this.ParentFrame.Errors.Add(new Frame.Error(this.ParentFrame, PacketStartIndex, this.PacketEndIndex, "Cannot parse credentials in HTTP Authorization (" + e.Message + ")"));
                    }
                }
            }
            else if (headerField.StartsWith("Authorization: Digest ", StringComparison.OrdinalIgnoreCase))
            {
                try {
                    string authorizationString = headerField.Substring(22).Trim();
                    foreach (string keyValueString in authorizationString.Split(new char[] { ',' }))
                    {
                        //username="******"
                        string[] parts = keyValueString.Split(new char[] { '=' });
                        if (parts.Length == 2)
                        {
                            /**
                             *         private string wwwAuthenticateRealm;//Used to be wwwAuthenticateBasicRealm
                             *         private string authorizationCredentialsUsername;
                             *         private string authorizationCredentailsPassword;
                             **/
                            string name  = parts[0].Trim();
                            string value = parts[1].Trim(new char[] { ' ', '\"', '\'' });
                            if (name.Equals("username", StringComparison.InvariantCultureIgnoreCase))
                            {
                                this.authorizationCredentialsUsername = value;
                                if (this.authorizationCredentailsPassword == null)
                                {
                                    this.authorizationCredentailsPassword = "******";
                                }
                            }
                            else if (name.Equals("realm", StringComparison.InvariantCultureIgnoreCase))
                            {
                                this.wwwAuthenticateRealm = value;
                            }
                        }
                    }
                }
                catch (Exception e) {
                    if (!this.ParentFrame.QuickParse)
                    {
                        this.ParentFrame.Errors.Add(new Frame.Error(this.ParentFrame, PacketStartIndex, this.PacketEndIndex, "Cannot parse credentials in HTTP Authorization (" + e.Message + ")"));
                    }
                }
            }
            else if (headerField.StartsWith("Content-Disposition:", StringComparison.OrdinalIgnoreCase))
            {
                this.contentDisposition = headerField.Substring(20).Trim();
                if (headerField.Contains("filename="))
                {
                    string filename = headerField.Substring(headerField.IndexOf("filename=") + 9);
                    filename = filename.Trim();
                    if (filename.StartsWith("\"") && filename.IndexOf('\"', 1) > 0)//get the string inside the quotations
                    {
                        filename = filename.Substring(1, filename.IndexOf('\"', 1) - 1);
                    }
                    if (filename.Length > 0)
                    {
                        this.contentDispositionFilename = filename;
                    }
                }
                else if (headerField.Contains("filename*="))
                {
                    //Example: Content-Disposition: inline; filename*=UTF-8''944.png
                    //rfc6266 specifies that filename-parm can be "filename*" "=" ext-value
                    //rfc5987 sprcifies that ext-value = charset  "'" [ language ] "'" value-chars
                    int charsetIndex = headerField.IndexOf("filename*=") + 10;
                    int quoteIndex   = headerField.IndexOf('\'', charsetIndex);
                    if (charsetIndex > 0 && quoteIndex > 0)
                    {
                        string charset = headerField.Substring(charsetIndex, quoteIndex - charsetIndex);
                        try {
                            Encoding encoding      = System.Text.Encoding.GetEncoding(charset);
                            int      extValueIndex = headerField.IndexOf('\'', quoteIndex + 1) + 1;
                            byte[]   extValueBytes = System.Text.Encoding.Default.GetBytes(headerField.Substring(extValueIndex));
                            string   filename      = encoding.GetString(extValueBytes);
                            filename = filename.Trim();
                            if (filename.StartsWith("\"") && filename.IndexOf('\"', 1) > 0)//get the string inside the quotations
                            {
                                filename = filename.Substring(1, filename.IndexOf('\"', 1) - 1);
                            }
                            if (filename.Length > 0)
                            {
                                this.contentDispositionFilename = filename;
                            }
                        }
                        catch { }
                    }
                }
            }
            else if (headerField.StartsWith("Content-Range: ", StringComparison.OrdinalIgnoreCase))
            {
                //Content-Range: bytes 8621-23239/42941008
                //Content-Range: bytes 21010-47021/47022
                System.Text.RegularExpressions.Regex rangeRegEx = new System.Text.RegularExpressions.Regex(@"bytes (?<start>[0-9]+)-(?<end>[0-9]+)/(?<total>[0-9]+)$");
                System.Text.RegularExpressions.Match rangeMatch = rangeRegEx.Match(headerField);
                if (rangeMatch.Success)
                {
                    long start, end, total;
                    if (Int64.TryParse(rangeMatch.Groups["start"].Value, out start) && Int64.TryParse(rangeMatch.Groups["end"].Value, out end) && Int64.TryParse(rangeMatch.Groups["total"].Value, out total))
                    {
                        this.contentRange = new FileTransfer.ContentRange()
                        {
                            Start = start, End = end, Total = total
                        };
                    }
                }
            }
        }
Esempio n. 2
0
        private HttpPacket(Frame parentFrame, int packetStartIndex, int packetEndIndex)
            : base(parentFrame, packetStartIndex, packetEndIndex, "HTTP")
        {
            /*
             *
             *         generic-message = start-line
             *             *(message-header CRLF)
             *             CRLF
             *             [ message-body ]
             *
             *         start-line      = Request-Line | Status-Line
             *
             * */
            this.headerFields                     = new List <string>();
            this.requestedHost                    = null;
            this.requestedFileName                = null;
            this.userAgentBanner                  = null;
            this.statusCode                       = null;
            this.statusMessage                    = null;
            this.serverBanner                     = null;
            this.contentType                      = null;
            this.contentLength                    = -1;//instead of null
            this.contentEncoding                  = null;
            this.cookie                           = null;
            this.transferEncoding                 = null;
            this.wwwAuthenticateRealm             = null;
            this.authorizationCredentialsUsername = null;
            this.authorizationCredentailsPassword = null;
            this.packetHeaderIsComplete           = false;
            this.contentDispositionFilename       = null;
            this.contentRange                     = null;

            int dataIndex = packetStartIndex;

            //a start-line
            string startLine = Utils.ByteConverter.ReadLine(parentFrame.Data, ref dataIndex);

            if (startLine == null)
            {
                throw new Exception("HTTP packet does not contain a valid start line. Probably a false HTTP positive");
            }
            if (startLine.Length > 2048)
            {
                throw new Exception("HTTP start line is longer than 255 bytes. Probably a false HTTP positive");
            }

            if (dataIndex > packetEndIndex)
            {
                throw new Exception("HTTP start line ends after packet end...");
            }

            if (startLine.StartsWith("GET"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.GET;
            }
            else if (startLine.StartsWith("HEAD"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.HEAD;
            }
            else if (startLine.StartsWith("POST"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.POST;
            }
            else if (startLine.StartsWith("PUT"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.PUT;
            }
            else if (startLine.StartsWith("DELETE"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.DELETE;
            }
            else if (startLine.StartsWith("TRACE"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.TRACE;
            }
            else if (startLine.StartsWith("OPTIONS"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.OPTIONS;
            }
            else if (startLine.StartsWith("CONNECT"))
            {
                this.messageTypeIsRequest = true;
                this.requestMethod        = RequestMethods.CONNECT;
            }
            else if (startLine.StartsWith("HTTP"))
            {
                this.messageTypeIsRequest = false;
                this.requestMethod        = RequestMethods.none;
            }
            else
            {
                throw new Exception("Incorrect HTTP Message Type or Request Method");
            }

            //zero or more header fields (also known as "headers")
            while (true)
            {
                string headerLine = Utils.ByteConverter.ReadLine(parentFrame.Data, ref dataIndex);
                if (headerLine == null)
                {
                    break;//this.packetHeaderIsComplete will NOT be true!
                }
                else if (headerLine.Length > 0)
                {
                    this.headerFields.Add(headerLine);
                    ExtractHeaderField(headerLine);
                }
                else  //headerLine.Length==0
                {
                    this.packetHeaderIsComplete = true;//the header is complete and that's enough
                    break;//the for loop should stop now...
                }
            }

            //see if there is a message-body
            if (this.packetHeaderIsComplete && this.messageTypeIsRequest && (requestMethod == RequestMethods.HEAD || requestMethod == RequestMethods.GET))
            {
                //this part is important in case there are chained (queued) requests as in HTTP 1.1
                this.messageBody    = null;
                this.PacketEndIndex = dataIndex - 1;
            }
            else if (this.packetHeaderIsComplete && dataIndex <= packetEndIndex)//we have a body!
            {
                if (this.contentLength > 0 && this.contentLength < packetEndIndex - dataIndex + 1)
                {
                    this.messageBody    = new byte[this.contentLength];
                    this.PacketEndIndex = dataIndex + this.contentLength - 1;
                }
                else
                {
                    this.messageBody = new byte[packetEndIndex - dataIndex + 1];
                }
                Array.Copy(parentFrame.Data, dataIndex, this.messageBody, 0, this.messageBody.Length);

                /*
                 * for(int i=0; i<this.messageBody.Length; i++)
                 *  this.messageBody[i]=parentFrame.Data[dataIndex+i];
                 * */
            }
            else
            {
                this.messageBody = null;
            }


            //now extract some interresting information from the packet
            if (this.messageTypeIsRequest) //REQUEST
            {
                if (this.requestMethod == RequestMethods.GET || this.requestMethod == RequestMethods.POST || this.requestMethod == RequestMethods.HEAD || this.requestMethod == RequestMethods.OPTIONS)
                {
                    int    requestUriOffset = this.requestMethod.ToString().Length + 1;
                    string fileURI          = startLine.Substring(requestUriOffset, startLine.Length - requestUriOffset);
                    if (fileURI.Contains(" HTTP"))
                    {
                        fileURI = fileURI.Substring(0, fileURI.IndexOf(" HTTP"));
                    }
                    if (fileURI.Length > 0)//If it is the index-file the URI will be just "/"
                    {
                        this.requestedFileName = fileURI;
                    }
                    else
                    {
                        this.requestedFileName = null;
                    }
                } /*
                   * else if(this.requestMethod==RequestMethods.POST) {
                   * string fileURI=startLine.Substring(5, startLine.Length-5);
                   * if(fileURI.Contains(" HTTP")) {
                   *     fileURI=fileURI.Substring(0, fileURI.IndexOf(" HTTP"));
                   * }
                   * if(fileURI.Length>0) {//If it is the index-file the URI will be just "/"
                   *     this.requestedFileName=fileURI;
                   * }
                   * }*/
            }
            else  //REPLY
            {
                if (startLine.StartsWith("HTTP/1."))
                {
                    this.statusCode = startLine.Substring(9, 3);
                    if (startLine.Length > 12)
                    {
                        this.statusMessage = startLine.Substring(12).Trim();
                    }
                }
            }
        }