Example #1
0
        public HandshakeMessage[] ProcessHandshakeRecord(ProtocolVersion version,
                                                         Record record)
        {
            List <HandshakeMessage> ret = new List <HandshakeMessage>();

            // Write record to input stream and attempt to parse a handshake message
            _inputStream.Write(record.Fragment, 0, record.Fragment.Length);
            while (_inputStream.Length - _inputtedBytes >= 4)
            {
                byte[] inputBuffer = _inputStream.GetBuffer();

                int dataLength = (inputBuffer[_inputtedBytes + 1] << 16) |
                                 (inputBuffer[_inputtedBytes + 2] << 8) |
                                 inputBuffer[_inputtedBytes + 3];

                // Check that if we have enough data to read message now
                if (4 + dataLength > _inputStream.Length - _inputtedBytes)
                {
                    break;
                }

                byte[] msgData       = new byte[4 + dataLength];
                long   writePosition = _inputStream.Position;

                // Read message data from inputStream
                _inputStream.Position = _inputtedBytes;
                _inputStream.Read(msgData, 0, msgData.Length);
                _inputStream.Position = writePosition;
                _inputtedBytes       += msgData.Length;

                // Add resulting handshake message to the results
                ret.Add(HandshakeMessage.GetInstance(version, msgData));
            }

            if (_inputtedBytes == _inputStream.Length)
            {
                // Reset stream to save memory
                _inputStream.Position = 0;
                _inputStream.SetLength(0);
                _inputtedBytes = 0;
            }

            return(ret.ToArray());
        }
        public bool ReadPacket(Stream stream)
        {
            byte[] header    = new byte[5];
            int    readBytes = 0;

            while (readBytes < header.Length)
            {
                readBytes += stream.Read(header, readBytes, header.Length - readBytes);
            }

            Record record = new Record(header);

            readBytes = 0;
            while (readBytes < record.Fragment.Length)
            {
                readBytes += stream.Read(record.Fragment, readBytes, record.Fragment.Length - readBytes);
            }

            _recordHandler.ProcessInputRecord(record);

            if (record.Type == 22)
            {
                HandshakeMessage hs = HandshakeMessage.GetInstance(VERSION, record.Fragment);
                if (hs == null)
                {
                    Console.WriteLine("Skipped handling packet");
                    return(true);
                }

                Console.WriteLine("adding bytes to hash " + record.Fragment.Length);
                _handshakeStream.Write(record.Fragment, 0, record.Fragment.Length);

                if (hs.Type == HandshakeMessageType.ServerHello)
                {
                    HandshakeServerHello sh = (HandshakeServerHello)hs;
                    _serverRandom = sh.Random.GetBytes();
                    if (sh.ServerVersion != VERSION)
                    {
                        throw new Exception("Version doesn't match");
                    }
                }
                else if (hs.Type == HandshakeMessageType.Certificate)
                {
                    Console.WriteLine("Found certificate");
                    HandshakeCertificate cert = (HandshakeCertificate)hs;

                    _rsaPublicKey = null;
                    foreach (X509Certificate c in cert.CertificateList)
                    {
                        Console.WriteLine(c.ToString(true));

                        if (_rsaPublicKey == null)
                        {
                            X509Certificate c2 = new X509Certificate(c);
                            _rsaPublicKey = new CertificatePublicKey(c2);
                        }
                    }
                }
                else if (hs.Type == HandshakeMessageType.ServerHelloDone)
                {
                    SendClientKey(stream);

                    byte[] seed = new byte[64];
                    Array.Copy(_clientRandom, 0, seed, 0, 32);
                    Array.Copy(_serverRandom, 0, seed, 32, 32);
                    PrintBytes("hash seed", seed);

                    _masterSecret = _cipherSuite.KeyExchangeAlgorithm.GetMasterSecret(_cipherSuite.PseudoRandomFunction, seed);
                    PrintBytes("master secret", _masterSecret);

                    seed = new byte[64];
                    Array.Copy(_serverRandom, 0, seed, 0, 32);
                    Array.Copy(_clientRandom, 0, seed, 32, 32);

                    ConnectionState connectionState = new ConnectionState(_clientRandom, _serverRandom, _masterSecret);
                    _recordHandler.SetCipherSuite(_cipherSuite, connectionState);

                    SendFinished(stream);
                }
                else if (hs.Type == HandshakeMessageType.Finished)
                {
                    Console.WriteLine("Got Finished message!!!");
                    SendHttpGet(stream);
                }
            }
            else if (record.Type == 20)
            {
                Console.WriteLine("Got change cipher spec from server");
                _recordHandler.ChangeRemoteState();
            }
            else if (record.Type == 21)
            {
                // This is an alert
                if (record.Fragment.Length >= 2 && record.Fragment[1] == 0)
                {
                    // Close notify
                    Console.WriteLine("Close notify received");
                    return(false);
                }
            }
            else if (record.Type == 23)
            {
                Console.WriteLine("Got data: " + Encoding.UTF8.GetString(record.Fragment));
            }

            return(true);
        }