Inheritance: AaltoTLS.AsyncGenericResult
Beispiel #1
0
        public IAsyncResult BeginClientHandshake(string targetHost,
                                                 AsyncCallback asyncCallback,
                                                 Object asyncState)
        {
            lock (_handshakeLock) {
                if (_isHandshaking)
                {
                    throw new InvalidOperationException("Handshake already in progress");
                }

                if (_isAuthenticated)
                {
                    throw new InvalidOperationException("Renegotiation not supported");
                }

                _recordHandler    = new RecordHandler(_securityParameters.MinimumVersion, true);
                _handshakeSession = new ClientHandshakeSession(_securityParameters);
                _isHandshaking    = true;
            }

            AsyncHandshakeResult asyncHandshakeResult = new AsyncHandshakeResult(asyncCallback, asyncState);

            ProcessSendHandshakePacket(asyncHandshakeResult);
            return(asyncHandshakeResult);
        }
Beispiel #2
0
        public IAsyncResult BeginServerHandshake(X509Certificate serverCertificate,
                                                 AsyncCallback asyncCallback,
                                                 Object asyncState)
        {
            lock (_handshakeLock) {
                if (_isHandshaking)
                {
                    throw new InvalidOperationException("Handshake already in progress");
                }

                if (_isAuthenticated)
                {
                    throw new InvalidOperationException("Renegotiation not supported");
                }

                _recordHandler    = new RecordHandler(_securityParameters.MinimumVersion, false);
                _handshakeSession = new ServerHandshakeSession(_securityParameters);
                _isHandshaking    = true;
            }

            AsyncHandshakeResult asyncHandshakeResult = new AsyncHandshakeResult(asyncCallback, asyncState);

            _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult);
            return(asyncHandshakeResult);
        }
Beispiel #3
0
        private void SendHandshakeCallback(IAsyncResult asyncResult)
        {
            AsyncHandshakeResult asyncHandshakeResult = (AsyncHandshakeResult)asyncResult.AsyncState;

            try {
                _recordStream.EndSend(asyncResult);
                lock (_handshakeLock) {
                    if (_isAuthenticated && !_isHandshaking)
                    {
                        // Mark send result as complete
                        asyncHandshakeResult.SetComplete();
                        return;
                    }
                }

                // Handshake not finished yet, continue performing
                ProcessSendHandshakePacket(asyncHandshakeResult);
            } catch (AlertException ae) {
                ProcessSendFatalAlert(new Alert(ae.AlertDescription, _handshakeSession.NegotiatedVersion));
                asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local alert", ae));
            } catch (IOException) {
                asyncHandshakeResult.SetComplete(new EndOfStreamException("Connection closed unexpectedly"));
            } catch (Exception e) {
                ProcessSendFatalAlert(new Alert(AlertDescription.InternalError, _handshakeSession.NegotiatedVersion));
                asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local error", e));
            }
        }
Beispiel #4
0
 private void ProcessSendHandshakePacket(AsyncHandshakeResult asyncHandshakeResult)
 {
     HandshakeMessage[] messages = _handshakeSession.GetOutputMessages();
     Record[]           records  = _handshakePacketizer.ProcessHandshakeMessages(_handshakeSession.NegotiatedVersion, messages, _recordStream.MaximumFragmentLength);
     if (records.Length > 0)
     {
         // Encrypt the handshake records
         for (int i = 0; i < records.Length; i++)
         {
             _recordHandler.ProcessOutputRecord(records[i]);
         }
         _recordStream.BeginSend(records, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult);
     }
     else
     {
         if (_handshakeSession.State == HandshakeState.Finished)
         {
             // Handshake finished, mark result as complete
             asyncHandshakeResult.SetComplete();
         }
         else if (_handshakeSession.State == HandshakeState.SendChangeCipherSpec)
         {
             ProcessSendChangeCipherSpec(asyncHandshakeResult);
         }
         else
         {
             // Handshake not finished, receive the next handshake packet
             _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult);
         }
     }
 }
Beispiel #5
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);
        }
Beispiel #6
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);
        }
Beispiel #7
0
        private void EndHandshake(IAsyncResult asyncResult)
        {
            AsyncHandshakeResult asyncHandshakeResult = (AsyncHandshakeResult)asyncResult;

            if (!asyncHandshakeResult.IsCompleted)
            {
                asyncHandshakeResult.AsyncWaitHandle.WaitOne();
            }

            lock (_handshakeLock) {
                _isHandshaking = false;

                if (asyncHandshakeResult.CompletedWithException)
                {
                    throw asyncHandshakeResult.AsyncException;
                }
                _isAuthenticated = true;
            }
        }
Beispiel #8
0
        private void ProcessSendChangeCipherSpec(AsyncHandshakeResult asyncHandshakeResult)
        {
            // Create the change cipher spec protocol packet
            // NOTE: this has to be before recordHandler.ChangeLocalState since it uses the old state
            Record record = new Record(RecordType.ChangeCipherSpec,
                                       _handshakeSession.NegotiatedVersion,
                                       new byte[] { 0x01 });

            _recordHandler.ProcessOutputRecord(record);

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

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

            // Send the change cipher spec protocol packet
            _recordStream.BeginSend(new Record[] { record }, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult);
        }
Beispiel #9
0
        public IAsyncResult BeginClientHandshake(string targetHost,
		                                         AsyncCallback asyncCallback,
		                                         Object asyncState)
        {
            lock (_handshakeLock) {
                if (_isHandshaking) {
                    throw new InvalidOperationException("Handshake already in progress");
                }

                if (_isAuthenticated) {
                    throw new InvalidOperationException("Renegotiation not supported");
                }

                _recordHandler = new RecordHandler(_securityParameters.MinimumVersion, true);
                _handshakeSession = new ClientHandshakeSession(_securityParameters);
                _isHandshaking = true;
            }

            AsyncHandshakeResult asyncHandshakeResult = new AsyncHandshakeResult(asyncCallback, asyncState);
            ProcessSendHandshakePacket(asyncHandshakeResult);
            return asyncHandshakeResult;
        }
Beispiel #10
0
 private void ProcessSendHandshakePacket(AsyncHandshakeResult asyncHandshakeResult)
 {
     HandshakeMessage[] messages = _handshakeSession.GetOutputMessages();
     Record[] records = _handshakePacketizer.ProcessHandshakeMessages(_handshakeSession.NegotiatedVersion, messages, _recordStream.MaximumFragmentLength);
     if (records.Length > 0) {
         // Encrypt the handshake records
         for (int i=0; i<records.Length; i++) {
             _recordHandler.ProcessOutputRecord(records[i]);
         }
         _recordStream.BeginSend(records, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult);
     } else {
         if (_handshakeSession.State == HandshakeState.Finished) {
             // Handshake finished, mark result as complete
             asyncHandshakeResult.SetComplete();
         } else if (_handshakeSession.State == HandshakeState.SendChangeCipherSpec) {
             ProcessSendChangeCipherSpec(asyncHandshakeResult);
         } else {
             // Handshake not finished, receive the next handshake packet
             _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult);
         }
     }
 }
Beispiel #11
0
        private void ProcessSendChangeCipherSpec(AsyncHandshakeResult asyncHandshakeResult)
        {
            // Create the change cipher spec protocol packet
            // NOTE: this has to be before recordHandler.ChangeLocalState since it uses the old state
            Record record = new Record(RecordType.ChangeCipherSpec,
                                       _handshakeSession.NegotiatedVersion,
                                       new byte[] { 0x01 });
            _recordHandler.ProcessOutputRecord(record);

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

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

            // Send the change cipher spec protocol packet
            _recordStream.BeginSend(new Record[] { record }, new AsyncCallback(SendHandshakeCallback), asyncHandshakeResult);
        }
Beispiel #12
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);
        }
Beispiel #13
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);
        }
Beispiel #14
0
        public IAsyncResult BeginServerHandshake(X509Certificate serverCertificate,
		                                         AsyncCallback asyncCallback,
		                                         Object asyncState)
        {
            lock (_handshakeLock) {
                if (_isHandshaking) {
                    throw new InvalidOperationException("Handshake already in progress");
                }

                if (_isAuthenticated) {
                    throw new InvalidOperationException("Renegotiation not supported");
                }

                _recordHandler = new RecordHandler(_securityParameters.MinimumVersion, false);
                _handshakeSession = new ServerHandshakeSession(_securityParameters);
                _isHandshaking = true;
            }

            AsyncHandshakeResult asyncHandshakeResult = new AsyncHandshakeResult(asyncCallback, asyncState);
            _recordStream.BeginReceive(new AsyncCallback(ReceiveHandshakeCallback), asyncHandshakeResult);
            return asyncHandshakeResult;
        }
Beispiel #15
0
        private void ReceiveHandshakeCallback(IAsyncResult asyncResult)
        {
            AsyncHandshakeResult asyncHandshakeResult = (AsyncHandshakeResult)asyncResult.AsyncState;

            try {
                Record[] records = _recordStream.EndReceive(asyncResult);
                for (int i = 0; i < records.Length; i++)
                {
                    Record record = records[i];
                    if (!_recordHandler.ProcessInputRecord(record))
                    {
                        // Ignore records from invalid epoch
                        continue;
                    }

                    lock (_handshakeLock) {
                        if (!_isAuthenticated && record.Type == RecordType.Data)
                        {
                            // Refuse data packets before authentication
                            throw new AlertException(AlertDescription.UnexpectedMessage,
                                                     "Data packet received before handshake");
                        }
                        if (!_isHandshaking && (record.Type == RecordType.ChangeCipherSpec || record.Type == RecordType.Handshake))
                        {
                            // Refuse ChangeCipherSpec and Handshake packets if not handshaking
                            // TODO: Should handle HelloRequest if renegotiation is supported
                            throw new AlertException(AlertDescription.UnexpectedMessage,
                                                     "Handshake packet received outside handshake");
                        }
                        if (_isHandshaking && record.Type == RecordType.Data)
                        {
                            // Queue data packets during new handshake to avoid sync problems
                            // TODO: Should handle the data correctly if renegotiation is supported
                            throw new AlertException(AlertDescription.UnexpectedMessage,
                                                     "Received a data packet during handshake");
                        }
                    }

                    switch (record.Type)
                    {
                    case RecordType.ChangeCipherSpec:
                        ProcessChangeCipherSpecRecord(record, asyncHandshakeResult);
                        break;

                    case RecordType.Alert:
                        ProcessAlertRecord(record, asyncHandshakeResult);
                        break;

                    case RecordType.Handshake:
                        ProcessHandshakeRecord(record, asyncHandshakeResult);
                        break;

                    case RecordType.Data:
                        // TODO: Implement this properly if renegotiation is supported
                        break;

                    default:
                        ProcessUnknownRecord(record, asyncHandshakeResult);
                        break;
                    }
                }
            } catch (AlertException ae) {
                ProcessSendFatalAlert(new Alert(ae.AlertDescription, _handshakeSession.NegotiatedVersion));
                asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local alert", ae));
            } catch (IOException) {
                asyncHandshakeResult.SetComplete(new EndOfStreamException("Connection closed unexpectedly"));
            } catch (Exception e) {
                ProcessSendFatalAlert(new Alert(AlertDescription.InternalError, _handshakeSession.NegotiatedVersion));
                asyncHandshakeResult.SetComplete(new Exception("Connection closed because of local error", e));
            }
        }