예제 #1
0
        private async Task <bool> CanBeHttpMethod(CustomBufferedStream clientStream)
        {
            int legthToCheck = 10;

            for (int i = 0; i < legthToCheck; i++)
            {
                int b = await clientStream.PeekByteAsync(i);

                if (b == -1)
                {
                    return(false);
                }

                if (b == ' ' && i > 2)
                {
                    // at least 3 letters and a space
                    return(true);
                }

                if (!char.IsLetter((char)b))
                {
                    // non letter or too short
                    return(false);
                }
            }

            // only letters
            return(true);
        }
예제 #2
0
        /// <summary>
        /// Determines whether is connect method.
        /// </summary>
        /// <param name="clientStream">The client stream.</param>
        /// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
        private async Task <int> IsConnectMethod(CustomBufferedStream clientStream)
        {
            bool isConnect    = true;
            int  legthToCheck = 10;

            for (int i = 0; i < legthToCheck; i++)
            {
                int b = await clientStream.PeekByteAsync(i);

                if (b == -1)
                {
                    return(-1);
                }

                if (b == ' ' && i > 2)
                {
                    // at least 3 letters and a space
                    return(isConnect ? 1 : 0);
                }

                char ch = (char)b;
                if (!char.IsLetter(ch))
                {
                    // non letter or too short
                    return(-1);
                }

                if (i > 6 || ch != "CONNECT"[i])
                {
                    isConnect = false;
                }
            }

            // only letters
            return(isConnect ? 1 : 0);
        }
예제 #3
0
        public static async Task <ServerHelloInfo> PeekServerHello(CustomBufferedStream serverStream)
        {
            //detects the HTTPS ClientHello message as it is described in the following url:
            //https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format

            int recordType = await serverStream.PeekByteAsync(0);

            if (recordType == -1)
            {
                return(null);
            }

            if ((recordType & 0x80) == 0x80)
            {
                //SSL 2
                // not tested. SSL2 is deprecated
                var peekStream = new CustomBufferedPeekStream(serverStream, 1);

                // length value + minimum length
                if (!await peekStream.EnsureBufferLength(39))
                {
                    return(null);
                }

                int length = ((recordType & 0x7f) << 8) + peekStream.ReadByte();
                if (length < 38)
                {
                    // Message body too short.
                    return(null);
                }

                if (peekStream.ReadByte() != 0x04)
                {
                    // should be ServerHello
                    return(null);
                }

                int majorVersion = peekStream.ReadByte();
                int minorVersion = peekStream.ReadByte();

                // 32 bytes random + 1 byte sessionId + 2 bytes cipherSuite
                if (!await peekStream.EnsureBufferLength(35))
                {
                    return(null);
                }

                byte[] random      = peekStream.ReadBytes(32);
                byte[] sessionId   = peekStream.ReadBytes(1);
                int    cipherSuite = peekStream.ReadInt16();

                var serverHelloInfo = new ServerHelloInfo
                {
                    HandshakeVersion  = 2,
                    MajorVersion      = majorVersion,
                    MinorVersion      = minorVersion,
                    Random            = random,
                    SessionId         = sessionId,
                    CipherSuite       = cipherSuite,
                    ServerHelloLength = peekStream.Position,
                };

                return(serverHelloInfo);
            }
            else if (recordType == 0x16)
            {
                var peekStream = new CustomBufferedPeekStream(serverStream, 1);

                //should contain at least 43 bytes
                // 2 version + 2 length + 1 type + 3 length(?) + 2 version +  32 random + 1 sessionid length
                if (!await peekStream.EnsureBufferLength(43))
                {
                    return(null);
                }

                //SSL 3.0 or TLS 1.0, 1.1 and 1.2
                int majorVersion = peekStream.ReadByte();
                int minorVersion = peekStream.ReadByte();

                int length = peekStream.ReadInt16();

                if (peekStream.ReadByte() != 0x02)
                {
                    // should be ServerHello
                    return(null);
                }

                length = peekStream.ReadInt24();

                majorVersion = peekStream.ReadByte();
                minorVersion = peekStream.ReadByte();

                byte[] random = peekStream.ReadBytes(32);
                length = peekStream.ReadByte();

                // sessionid + cipherSuite + compressionMethod
                if (!await peekStream.EnsureBufferLength(length + 2 + 1))
                {
                    return(null);
                }

                byte[] sessionId = peekStream.ReadBytes(length);

                int  cipherSuite       = peekStream.ReadInt16();
                byte compressionMethod = peekStream.ReadByte();

                int extenstionsStartPosition = peekStream.Position;

                var extensions = await ReadExtensions(majorVersion, minorVersion, peekStream);

                //var rawBytes = new CustomBufferedPeekStream(serverStream).ReadBytes(peekStream.Position);

                var serverHelloInfo = new ServerHelloInfo
                {
                    HandshakeVersion        = 3,
                    MajorVersion            = majorVersion,
                    MinorVersion            = minorVersion,
                    Random                  = random,
                    SessionId               = sessionId,
                    CipherSuite             = cipherSuite,
                    CompressionMethod       = compressionMethod,
                    ServerHelloLength       = peekStream.Position,
                    EntensionsStartPosition = extenstionsStartPosition,
                    Extensions              = extensions,
                };

                return(serverHelloInfo);
            }

            return(null);
        }
예제 #4
0
        public static async Task <ClientHelloInfo> PeekClientHello(CustomBufferedStream clientStream)
        {
            //detects the HTTPS ClientHello message as it is described in the following url:
            //https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format

            int recordType = await clientStream.PeekByteAsync(0);

            if (recordType == -1)
            {
                return(null);
            }

            if ((recordType & 0x80) == 0x80)
            {
                //SSL 2
                var peekStream = new CustomBufferedPeekStream(clientStream, 1);

                // length value + minimum length
                if (!await peekStream.EnsureBufferLength(10))
                {
                    return(null);
                }

                int length = ((recordType & 0x7f) << 8) + peekStream.ReadByte();
                if (length < 9)
                {
                    // Message body too short.
                    return(null);
                }

                if (peekStream.ReadByte() != 0x01)
                {
                    // should be ClientHello
                    return(null);
                }

                int majorVersion = peekStream.ReadByte();
                int minorVersion = peekStream.ReadByte();

                int ciphersCount    = peekStream.ReadInt16() / 3;
                int sessionIdLength = peekStream.ReadInt16();
                int randomLength    = peekStream.ReadInt16();

                if (!await peekStream.EnsureBufferLength(ciphersCount * 3 + sessionIdLength + randomLength))
                {
                    return(null);
                }

                int[] ciphers = new int[ciphersCount];
                for (int i = 0; i < ciphers.Length; i++)
                {
                    ciphers[i] = (peekStream.ReadByte() << 16) + (peekStream.ReadByte() << 8) + peekStream.ReadByte();
                }

                byte[] sessionId = peekStream.ReadBytes(sessionIdLength);
                byte[] random    = peekStream.ReadBytes(randomLength);

                var clientHelloInfo = new ClientHelloInfo
                {
                    HandshakeVersion  = 2,
                    MajorVersion      = majorVersion,
                    MinorVersion      = minorVersion,
                    Random            = random,
                    SessionId         = sessionId,
                    Ciphers           = ciphers,
                    ClientHelloLength = peekStream.Position,
                };

                return(clientHelloInfo);
            }
            else if (recordType == 0x16)
            {
                var peekStream = new CustomBufferedPeekStream(clientStream, 1);

                //should contain at least 43 bytes
                // 2 version + 2 length + 1 type + 3 length(?) + 2 version +  32 random + 1 sessionid length
                if (!await peekStream.EnsureBufferLength(43))
                {
                    return(null);
                }

                //SSL 3.0 or TLS 1.0, 1.1 and 1.2
                int majorVersion = peekStream.ReadByte();
                int minorVersion = peekStream.ReadByte();

                int length = peekStream.ReadInt16();

                if (peekStream.ReadByte() != 0x01)
                {
                    // should be ClientHello
                    return(null);
                }

                length = peekStream.ReadInt24();

                majorVersion = peekStream.ReadByte();
                minorVersion = peekStream.ReadByte();

                byte[] random = peekStream.ReadBytes(32);
                length = peekStream.ReadByte();

                // sessionid + 2 ciphersData length
                if (!await peekStream.EnsureBufferLength(length + 2))
                {
                    return(null);
                }

                byte[] sessionId = peekStream.ReadBytes(length);

                length = peekStream.ReadInt16();

                // ciphersData + compressionData length
                if (!await peekStream.EnsureBufferLength(length + 1))
                {
                    return(null);
                }

                byte[] ciphersData = peekStream.ReadBytes(length);
                int[]  ciphers     = new int[ciphersData.Length / 2];
                for (int i = 0; i < ciphers.Length; i++)
                {
                    ciphers[i] = (ciphersData[2 * i] << 8) + ciphersData[2 * i + 1];
                }

                length = peekStream.ReadByte();
                if (length < 1)
                {
                    return(null);
                }

                // compressionData
                if (!await peekStream.EnsureBufferLength(length))
                {
                    return(null);
                }

                byte[] compressionData = peekStream.ReadBytes(length);

                int extenstionsStartPosition = peekStream.Position;

                var extensions = await ReadExtensions(majorVersion, minorVersion, peekStream);

                var clientHelloInfo = new ClientHelloInfo
                {
                    HandshakeVersion        = 3,
                    MajorVersion            = majorVersion,
                    MinorVersion            = minorVersion,
                    Random                  = random,
                    SessionId               = sessionId,
                    Ciphers                 = ciphers,
                    CompressionData         = compressionData,
                    ClientHelloLength       = peekStream.Position,
                    EntensionsStartPosition = extenstionsStartPosition,
                    Extensions              = extensions,
                };

                return(clientHelloInfo);
            }

            return(null);
        }