예제 #1
0
        private void ProcessChangeCipherSpecRecord(Record record, AsyncHandshakeResult asyncHandshakeResult)
        {
            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();

            // Read the finished message after changing cipher spec
            _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult);
        }
예제 #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");
        }