Ejemplo n.º 1
0
        private void ProcessHandshakeRecord(Record record, AsyncHandshakeResult asyncHandshakeResult)
        {
            // Process each handshake message included in this record fragment separately
            HandshakeMessage[] msgs = _handshakePacketizer.ProcessHandshakeRecord(_handshakeSession.NegotiatedVersion, record);
            for (int i = 0; i < msgs.Length; i++)
            {
                _handshakeSession.ProcessMessage(msgs[i]);
            }

            // Continue processing handshake by attempting to send packets
            ProcessSendHandshakePacket(asyncHandshakeResult);
        }
Ejemplo n.º 2
0
        private async Task ReceiveChangeCipherSpecAndFinished(CancellationToken token)
        {
            var recordList = new List <Record>();
            var changeCipherSpecReceived = false;
            var finishedReceived         = false;

            while (!token.IsCancellationRequested)
            {
                var records = await _recordStream.ReceiveAsync(token);

                if (records == null || records.Count == 0)
                {
                    continue;
                }

                // Check for alerts
                foreach (var record in records)
                {
                    if (record.Type == RecordType.Alert)
                    {
                        logger?.Error($"Alert received: { (AlertDescription)record.Fragment[1]}");
                        if (record.Fragment.Length == 2)
                        {
                            var alert = (AlertDescription)record.Fragment[1];
                            throw new AlertException((AlertDescription)record.Fragment[1], $"Received TLS alert record: {alert}");
                        }
                    }
                }

                recordList.AddRange(records);
                if (recordList.Count < 2)
                {
                    continue;
                }

                foreach (var record in recordList)
                {
                    _recordHandler.ProcessInputRecord(record);

                    if (record.Type == RecordType.ChangeCipherSpec)
                    {
                        changeCipherSpecReceived = true;

                        if (record.Fragment.Length != 1 || record.Fragment[0] != 0x01)
                        {
                            throw new AlertException(AlertDescription.IllegalParameter, "Received an invalid ChangeCipherSpec record");
                        }

                        // NOTE: keep this before recordHandler.ChangeLocalState since it may generate masterSecret
                        _handshakeSession.RemoteChangeCipherSpec();

                        // Change cipher suite in record handler and handle it in handshake session
                        _recordHandler.SetCipherSuite(_handshakeSession.CipherSuite, _handshakeSession.ConnectionState);
                        _recordHandler.ChangeRemoteState();

                        continue;
                    }

                    if (record.Type == RecordType.Handshake)
                    {
                        finishedReceived = true;
                        HandshakeMessage[] handshakeMessages = _handshakePacketizer.ProcessHandshakeRecord(_handshakeSession.NegotiatedVersion, record);
                        foreach (HandshakeMessage hsm in handshakeMessages)
                        {
                            if (hsm.Type != HandshakeMessageType.Finished)
                            {
                                throw new AlertException(AlertDescription.UnexpectedMessage, "Finished handshake message was expected");
                            }

                            logger?.Debug("Received Handshake message {0}", hsm.Type);
                            _handshakeSession.ProcessMessage(hsm);
                        }
                    }

                    if (changeCipherSpecReceived && finishedReceived)
                    {
                        return;
                    }
                }
            }

            throw new TimeoutException("ReceiveAsync change cipher spec timed out");
        }