summaryrefslogtreecommitdiffstats
path: root/src/lib/tlslite/TLSConnection.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tlslite/TLSConnection.py')
-rwxr-xr-xsrc/lib/tlslite/TLSConnection.py1600
1 files changed, 0 insertions, 1600 deletions
diff --git a/src/lib/tlslite/TLSConnection.py b/src/lib/tlslite/TLSConnection.py
deleted file mode 100755
index d125f8f0a..000000000
--- a/src/lib/tlslite/TLSConnection.py
+++ /dev/null
@@ -1,1600 +0,0 @@
-"""
-MAIN CLASS FOR TLS LITE (START HERE!).
-"""
-from __future__ import generators
-
-import socket
-from utils.compat import formatExceptionTrace
-from TLSRecordLayer import TLSRecordLayer
-from Session import Session
-from constants import *
-from utils.cryptomath import getRandomBytes
-from errors import *
-from messages import *
-from mathtls import *
-from HandshakeSettings import HandshakeSettings
-
-
-class TLSConnection(TLSRecordLayer):
- """
- This class wraps a socket and provides TLS handshaking and data
- transfer.
-
- To use this class, create a new instance, passing a connected
- socket into the constructor. Then call some handshake function.
- If the handshake completes without raising an exception, then a TLS
- connection has been negotiated. You can transfer data over this
- connection as if it were a socket.
-
- This class provides both synchronous and asynchronous versions of
- its key functions. The synchronous versions should be used when
- writing single-or multi-threaded code using blocking sockets. The
- asynchronous versions should be used when performing asynchronous,
- event-based I/O with non-blocking sockets.
-
- Asynchronous I/O is a complicated subject; typically, you should
- not use the asynchronous functions directly, but should use some
- framework like asyncore or Twisted which TLS Lite integrates with
- (see
- L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or
- L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}).
- """
-
-
- def __init__(self, sock):
- """Create a new TLSConnection instance.
-
- @param sock: The socket data will be transmitted on. The
- socket should already be connected. It may be in blocking or
- non-blocking mode.
-
- @type sock: L{socket.socket}
- """
- TLSRecordLayer.__init__(self, sock)
-
- def handshakeClientSRP(self, username, password, session=None,
- settings=None, checker=None, async=False):
- """Perform an SRP handshake in the role of client.
-
- This function performs a TLS/SRP handshake. SRP mutually
- authenticates both parties to each other using only a
- username and password. This function may also perform a
- combined SRP and server-certificate handshake, if the server
- chooses to authenticate itself with a certificate chain in
- addition to doing SRP.
-
- TLS/SRP is non-standard. Most TLS implementations don't
- support it. See
- U{http://www.ietf.org/html.charters/tls-charter.html} or
- U{http://trevp.net/tlssrp/} for the latest information on
- TLS/SRP.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type username: str
- @param username: The SRP username.
-
- @type password: str
- @param password: The SRP password.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. This
- session must be an SRP session performed with the same username
- and password as were passed in. If the resumption does not
- succeed, a full SRP handshake will be performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(srpParams=(username, password),
- session=session, settings=settings, checker=checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
- def handshakeClientCert(self, certChain=None, privateKey=None,
- session=None, settings=None, checker=None,
- async=False):
- """Perform a certificate-based handshake in the role of client.
-
- This function performs an SSL or TLS handshake. The server
- will authenticate itself using an X.509 or cryptoID certificate
- chain. If the handshake succeeds, the server's certificate
- chain will be stored in the session's serverCertChain attribute.
- Unless a checker object is passed in, this function does no
- validation or checking of the server's certificate chain.
-
- If the server requests client authentication, the
- client will send the passed-in certificate chain, and use the
- passed-in private key to authenticate itself. If no
- certificate chain and private key were passed in, the client
- will attempt to proceed without client authentication. The
- server may or may not allow this.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type certChain: L{tlslite.X509CertChain.X509CertChain} or
- L{cryptoIDlib.CertChain.CertChain}
- @param certChain: The certificate chain to be used if the
- server requests client authentication.
-
- @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
- @param privateKey: The private key to be used if the server
- requests client authentication.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. If the
- resumption does not succeed, a full handshake will be
- performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(certParams=(certChain,
- privateKey), session=session, settings=settings,
- checker=checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
- def handshakeClientUnknown(self, srpCallback=None, certCallback=None,
- session=None, settings=None, checker=None,
- async=False):
- """Perform a to-be-determined type of handshake in the role of client.
-
- This function performs an SSL or TLS handshake. If the server
- requests client certificate authentication, the
- certCallback will be invoked and should return a (certChain,
- privateKey) pair. If the callback returns None, the library
- will attempt to proceed without client authentication. The
- server may or may not allow this.
-
- If the server requests SRP authentication, the srpCallback
- will be invoked and should return a (username, password) pair.
- If the callback returns None, the local implementation will
- signal a user_canceled error alert.
-
- After the handshake completes, the client can inspect the
- connection's session attribute to determine what type of
- authentication was performed.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type srpCallback: callable
- @param srpCallback: The callback to be used if the server
- requests SRP authentication. If None, the client will not
- offer support for SRP ciphersuites.
-
- @type certCallback: callable
- @param certCallback: The callback to be used if the server
- requests client certificate authentication.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. If the
- resumption does not succeed, a full handshake will be
- performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(unknownParams=(srpCallback,
- certCallback), session=session, settings=settings,
- checker=checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
- def handshakeClientSharedKey(self, username, sharedKey, settings=None,
- checker=None, async=False):
- """Perform a shared-key handshake in the role of client.
-
- This function performs a shared-key handshake. Using shared
- symmetric keys of high entropy (128 bits or greater) mutually
- authenticates both parties to each other.
-
- TLS with shared-keys is non-standard. Most TLS
- implementations don't support it. See
- U{http://www.ietf.org/html.charters/tls-charter.html} for the
- latest information on TLS with shared-keys. If the shared-keys
- Internet-Draft changes or is superceded, TLS Lite will track
- those changes, so the shared-key support in later versions of
- TLS Lite may become incompatible with this version.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type username: str
- @param username: The shared-key username.
-
- @type sharedKey: str
- @param sharedKey: The shared key.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(sharedKeyParams=(username,
- sharedKey), settings=settings, checker=checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
- def _handshakeClientAsync(self, srpParams=(), certParams=(),
- unknownParams=(), sharedKeyParams=(),
- session=None, settings=None, checker=None,
- recursive=False):
-
- handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
- certParams=certParams, unknownParams=unknownParams,
- sharedKeyParams=sharedKeyParams, session=session,
- settings=settings, recursive=recursive)
- for result in self._handshakeWrapperAsync(handshaker, checker):
- yield result
-
-
- def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams,
- sharedKeyParams, session, settings, recursive):
- if not recursive:
- self._handshakeStart(client=True)
-
- #Unpack parameters
- srpUsername = None # srpParams
- password = None # srpParams
- clientCertChain = None # certParams
- privateKey = None # certParams
- srpCallback = None # unknownParams
- certCallback = None # unknownParams
- #session # sharedKeyParams (or session)
- #settings # settings
-
- if srpParams:
- srpUsername, password = srpParams
- elif certParams:
- clientCertChain, privateKey = certParams
- elif unknownParams:
- srpCallback, certCallback = unknownParams
- elif sharedKeyParams:
- session = Session()._createSharedKey(*sharedKeyParams)
-
- if not settings:
- settings = HandshakeSettings()
- settings = settings._filter()
-
- #Validate parameters
- if srpUsername and not password:
- raise ValueError("Caller passed a username but no password")
- if password and not srpUsername:
- raise ValueError("Caller passed a password but no username")
-
- if clientCertChain and not privateKey:
- raise ValueError("Caller passed a certChain but no privateKey")
- if privateKey and not clientCertChain:
- raise ValueError("Caller passed a privateKey but no certChain")
-
- if clientCertChain:
- foundType = False
- try:
- import cryptoIDlib.CertChain
- if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain):
- if "cryptoID" not in settings.certificateTypes:
- raise ValueError("Client certificate doesn't "\
- "match Handshake Settings")
- settings.certificateTypes = ["cryptoID"]
- foundType = True
- except ImportError:
- pass
- if not foundType and isinstance(clientCertChain,
- X509CertChain):
- if "x509" not in settings.certificateTypes:
- raise ValueError("Client certificate doesn't match "\
- "Handshake Settings")
- settings.certificateTypes = ["x509"]
- foundType = True
- if not foundType:
- raise ValueError("Unrecognized certificate type")
-
-
- if session:
- if not session.valid():
- session = None #ignore non-resumable sessions...
- elif session.resumable and \
- (session.srpUsername != srpUsername):
- raise ValueError("Session username doesn't match")
-
- #Add Faults to parameters
- if srpUsername and self.fault == Fault.badUsername:
- srpUsername += "GARBAGE"
- if password and self.fault == Fault.badPassword:
- password += "GARBAGE"
- if sharedKeyParams:
- identifier = sharedKeyParams[0]
- sharedKey = sharedKeyParams[1]
- if self.fault == Fault.badIdentifier:
- identifier += "GARBAGE"
- session = Session()._createSharedKey(identifier, sharedKey)
- elif self.fault == Fault.badSharedKey:
- sharedKey += "GARBAGE"
- session = Session()._createSharedKey(identifier, sharedKey)
-
-
- #Initialize locals
- serverCertChain = None
- cipherSuite = 0
- certificateType = CertificateType.x509
- premasterSecret = None
-
- #Get client nonce
- clientRandom = getRandomBytes(32)
-
- #Initialize acceptable ciphersuites
- cipherSuites = []
- if srpParams:
- cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
- cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
- elif certParams:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- elif unknownParams:
- if srpCallback:
- cipherSuites += \
- CipherSuite.getSrpRsaSuites(settings.cipherNames)
- cipherSuites += \
- CipherSuite.getSrpSuites(settings.cipherNames)
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- elif sharedKeyParams:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- else:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
-
- #Initialize acceptable certificate types
- certificateTypes = settings._getCertificateTypes()
-
- #Tentatively set the version to the client's minimum version.
- #We'll use this for the ClientHello, and if an error occurs
- #parsing the Server Hello, we'll use this version for the response
- self.version = settings.maxVersion
-
- #Either send ClientHello (with a resumable session)...
- if session:
- #If it's a resumable (i.e. not a shared-key session), then its
- #ciphersuite must be one of the acceptable ciphersuites
- if (not sharedKeyParams) and \
- session.cipherSuite not in cipherSuites:
- raise ValueError("Session's cipher suite not consistent "\
- "with parameters")
- else:
- clientHello = ClientHello()
- clientHello.create(settings.maxVersion, clientRandom,
- session.sessionID, cipherSuites,
- certificateTypes, session.srpUsername)
-
- #Or send ClientHello (without)
- else:
- clientHello = ClientHello()
- clientHello.create(settings.maxVersion, clientRandom,
- createByteArraySequence([]), cipherSuites,
- certificateTypes, srpUsername)
- for result in self._sendMsg(clientHello):
- yield result
-
- #Get ServerHello (or missing_srp_username)
- for result in self._getMsg((ContentType.handshake,
- ContentType.alert),
- HandshakeType.server_hello):
- if result in (0,1):
- yield result
- else:
- break
- msg = result
-
- if isinstance(msg, ServerHello):
- serverHello = msg
- elif isinstance(msg, Alert):
- alert = msg
-
- #If it's not a missing_srp_username, re-raise
- if alert.description != AlertDescription.missing_srp_username:
- self._shutdown(False)
- raise TLSRemoteAlert(alert)
-
- #If we're not in SRP callback mode, we won't have offered SRP
- #without a username, so we shouldn't get this alert
- if not srpCallback:
- for result in self._sendError(\
- AlertDescription.unexpected_message):
- yield result
- srpParams = srpCallback()
- #If the callback returns None, cancel the handshake
- if srpParams == None:
- for result in self._sendError(AlertDescription.user_canceled):
- yield result
-
- #Recursively perform handshake
- for result in self._handshakeClientAsyncHelper(srpParams,
- None, None, None, None, settings, True):
- yield result
- return
-
- #Get the server version. Do this before anything else, so any
- #error alerts will use the server's version
- self.version = serverHello.server_version
-
- #Future responses from server must use this version
- self._versionCheck = True
-
- #Check ServerHello
- if serverHello.server_version < settings.minVersion:
- for result in self._sendError(\
- AlertDescription.protocol_version,
- "Too old version: %s" % str(serverHello.server_version)):
- yield result
- if serverHello.server_version > settings.maxVersion:
- for result in self._sendError(\
- AlertDescription.protocol_version,
- "Too new version: %s" % str(serverHello.server_version)):
- yield result
- if serverHello.cipher_suite not in cipherSuites:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Server responded with incorrect ciphersuite"):
- yield result
- if serverHello.certificate_type not in certificateTypes:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Server responded with incorrect certificate type"):
- yield result
- if serverHello.compression_method != 0:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Server responded with incorrect compression method"):
- yield result
-
- #Get the server nonce
- serverRandom = serverHello.random
-
- #If the server agrees to resume
- if session and session.sessionID and \
- serverHello.session_id == session.sessionID:
-
- #If a shared-key, we're flexible about suites; otherwise the
- #server-chosen suite has to match the session's suite
- if sharedKeyParams:
- session.cipherSuite = serverHello.cipher_suite
- elif serverHello.cipher_suite != session.cipherSuite:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,\
- "Server's ciphersuite doesn't match session"):
- yield result
-
- #Set the session for this connection
- self.session = session
-
- #Calculate pending connection states
- self._calcPendingStates(clientRandom, serverRandom,
- settings.cipherImplementations)
-
- #Exchange ChangeCipherSpec and Finished messages
- for result in self._getFinished():
- yield result
- for result in self._sendFinished():
- yield result
-
- #Mark the connection as open
- self._handshakeDone(resumed=True)
-
- #If server DOES NOT agree to resume
- else:
-
- if sharedKeyParams:
- for result in self._sendError(\
- AlertDescription.user_canceled,
- "Was expecting a shared-key resumption"):
- yield result
-
- #We've already validated these
- cipherSuite = serverHello.cipher_suite
- certificateType = serverHello.certificate_type
-
- #If the server chose an SRP suite...
- if cipherSuite in CipherSuite.srpSuites:
- #Get ServerKeyExchange, ServerHelloDone
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.server_key_exchange, cipherSuite):
- if result in (0,1):
- yield result
- else:
- break
- serverKeyExchange = result
-
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.server_hello_done):
- if result in (0,1):
- yield result
- else:
- break
- serverHelloDone = result
-
- #If the server chose an SRP+RSA suite...
- elif cipherSuite in CipherSuite.srpRsaSuites:
- #Get Certificate, ServerKeyExchange, ServerHelloDone
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.certificate, certificateType):
- if result in (0,1):
- yield result
- else:
- break
- serverCertificate = result
-
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.server_key_exchange, cipherSuite):
- if result in (0,1):
- yield result
- else:
- break
- serverKeyExchange = result
-
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.server_hello_done):
- if result in (0,1):
- yield result
- else:
- break
- serverHelloDone = result
-
- #If the server chose an RSA suite...
- elif cipherSuite in CipherSuite.rsaSuites:
- #Get Certificate[, CertificateRequest], ServerHelloDone
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.certificate, certificateType):
- if result in (0,1):
- yield result
- else:
- break
- serverCertificate = result
-
- for result in self._getMsg(ContentType.handshake,
- (HandshakeType.server_hello_done,
- HandshakeType.certificate_request)):
- if result in (0,1):
- yield result
- else:
- break
- msg = result
-
- certificateRequest = None
- if isinstance(msg, CertificateRequest):
- certificateRequest = msg
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.server_hello_done):
- if result in (0,1):
- yield result
- else:
- break
- serverHelloDone = result
- elif isinstance(msg, ServerHelloDone):
- serverHelloDone = msg
- else:
- raise AssertionError()
-
-
- #Calculate SRP premaster secret, if server chose an SRP or
- #SRP+RSA suite
- if cipherSuite in CipherSuite.srpSuites + \
- CipherSuite.srpRsaSuites:
- #Get and check the server's group parameters and B value
- N = serverKeyExchange.srp_N
- g = serverKeyExchange.srp_g
- s = serverKeyExchange.srp_s
- B = serverKeyExchange.srp_B
-
- if (g,N) not in goodGroupParameters:
- for result in self._sendError(\
- AlertDescription.untrusted_srp_parameters,
- "Unknown group parameters"):
- yield result
- if numBits(N) < settings.minKeySize:
- for result in self._sendError(\
- AlertDescription.untrusted_srp_parameters,
- "N value is too small: %d" % numBits(N)):
- yield result
- if numBits(N) > settings.maxKeySize:
- for result in self._sendError(\
- AlertDescription.untrusted_srp_parameters,
- "N value is too large: %d" % numBits(N)):
- yield result
- if B % N == 0:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Suspicious B value"):
- yield result
-
- #Check the server's signature, if server chose an
- #SRP+RSA suite
- if cipherSuite in CipherSuite.srpRsaSuites:
- #Hash ServerKeyExchange/ServerSRPParams
- hashBytes = serverKeyExchange.hash(clientRandom,
- serverRandom)
-
- #Extract signature bytes from ServerKeyExchange
- sigBytes = serverKeyExchange.signature
- if len(sigBytes) == 0:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Server sent an SRP ServerKeyExchange "\
- "message without a signature"):
- yield result
-
- #Get server's public key from the Certificate message
- for result in self._getKeyFromChain(serverCertificate,
- settings):
- if result in (0,1):
- yield result
- else:
- break
- publicKey, serverCertChain = result
-
- #Verify signature
- if not publicKey.verify(sigBytes, hashBytes):
- for result in self._sendError(\
- AlertDescription.decrypt_error,
- "Signature failed to verify"):
- yield result
-
-
- #Calculate client's ephemeral DH values (a, A)
- a = bytesToNumber(getRandomBytes(32))
- A = powMod(g, a, N)
-
- #Calculate client's static DH values (x, v)
- x = makeX(bytesToString(s), srpUsername, password)
- v = powMod(g, x, N)
-
- #Calculate u
- u = makeU(N, A, B)
-
- #Calculate premaster secret
- k = makeK(N, g)
- S = powMod((B - (k*v)) % N, a+(u*x), N)
-
- if self.fault == Fault.badA:
- A = N
- S = 0
- premasterSecret = numberToBytes(S)
-
- #Send ClientKeyExchange
- for result in self._sendMsg(\
- ClientKeyExchange(cipherSuite).createSRP(A)):
- yield result
-
-
- #Calculate RSA premaster secret, if server chose an RSA suite
- elif cipherSuite in CipherSuite.rsaSuites:
-
- #Handle the presence of a CertificateRequest
- if certificateRequest:
- if unknownParams and certCallback:
- certParamsNew = certCallback()
- if certParamsNew:
- clientCertChain, privateKey = certParamsNew
-
- #Get server's public key from the Certificate message
- for result in self._getKeyFromChain(serverCertificate,
- settings):
- if result in (0,1):
- yield result
- else:
- break
- publicKey, serverCertChain = result
-
-
- #Calculate premaster secret
- premasterSecret = getRandomBytes(48)
- premasterSecret[0] = settings.maxVersion[0]
- premasterSecret[1] = settings.maxVersion[1]
-
- if self.fault == Fault.badPremasterPadding:
- premasterSecret[0] = 5
- if self.fault == Fault.shortPremasterSecret:
- premasterSecret = premasterSecret[:-1]
-
- #Encrypt premaster secret to server's public key
- encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
-
- #If client authentication was requested, send Certificate
- #message, either with certificates or empty
- if certificateRequest:
- clientCertificate = Certificate(certificateType)
-
- if clientCertChain:
- #Check to make sure we have the same type of
- #certificates the server requested
- wrongType = False
- if certificateType == CertificateType.x509:
- if not isinstance(clientCertChain, X509CertChain):
- wrongType = True
- elif certificateType == CertificateType.cryptoID:
- if not isinstance(clientCertChain,
- cryptoIDlib.CertChain.CertChain):
- wrongType = True
- if wrongType:
- for result in self._sendError(\
- AlertDescription.handshake_failure,
- "Client certificate is of wrong type"):
- yield result
-
- clientCertificate.create(clientCertChain)
-
- for result in self._sendMsg(clientCertificate):
- yield result
- else:
- #The server didn't request client auth, so we
- #zeroize these so the clientCertChain won't be
- #stored in the session.
- privateKey = None
- clientCertChain = None
-
- #Send ClientKeyExchange
- clientKeyExchange = ClientKeyExchange(cipherSuite,
- self.version)
- clientKeyExchange.createRSA(encryptedPreMasterSecret)
- for result in self._sendMsg(clientKeyExchange):
- yield result
-
- #If client authentication was requested and we have a
- #private key, send CertificateVerify
- if certificateRequest and privateKey:
- if self.version == (3,0):
- #Create a temporary session object, just for the
- #purpose of creating the CertificateVerify
- session = Session()
- session._calcMasterSecret(self.version,
- premasterSecret,
- clientRandom,
- serverRandom)
- verifyBytes = self._calcSSLHandshakeHash(\
- session.masterSecret, "")
- elif self.version in ((3,1), (3,2)):
- verifyBytes = stringToBytes(\
- self._handshake_md5.digest() + \
- self._handshake_sha.digest())
- if self.fault == Fault.badVerifyMessage:
- verifyBytes[0] = ((verifyBytes[0]+1) % 256)
- signedBytes = privateKey.sign(verifyBytes)
- certificateVerify = CertificateVerify()
- certificateVerify.create(signedBytes)
- for result in self._sendMsg(certificateVerify):
- yield result
-
-
- #Create the session object
- self.session = Session()
- self.session._calcMasterSecret(self.version, premasterSecret,
- clientRandom, serverRandom)
- self.session.sessionID = serverHello.session_id
- self.session.cipherSuite = cipherSuite
- self.session.srpUsername = srpUsername
- self.session.clientCertChain = clientCertChain
- self.session.serverCertChain = serverCertChain
-
- #Calculate pending connection states
- self._calcPendingStates(clientRandom, serverRandom,
- settings.cipherImplementations)
-
- #Exchange ChangeCipherSpec and Finished messages
- for result in self._sendFinished():
- yield result
- for result in self._getFinished():
- yield result
-
- #Mark the connection as open
- self.session._setResumable(True)
- self._handshakeDone(resumed=False)
-
-
-
- def handshakeServer(self, sharedKeyDB=None, verifierDB=None,
- certChain=None, privateKey=None, reqCert=False,
- sessionCache=None, settings=None, checker=None):
- """Perform a handshake in the role of server.
-
- This function performs an SSL or TLS handshake. Depending on
- the arguments and the behavior of the client, this function can
- perform a shared-key, SRP, or certificate-based handshake. It
- can also perform a combined SRP and server-certificate
- handshake.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
- This function does not send a Hello Request message before
- performing the handshake, so if re-handshaking is required,
- the server must signal the client to begin the re-handshake
- through some other means.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
- @param sharedKeyDB: A database of shared symmetric keys
- associated with usernames. If the client performs a
- shared-key handshake, the session's sharedKeyUsername
- attribute will be set.
-
- @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
- @param verifierDB: A database of SRP password verifiers
- associated with usernames. If the client performs an SRP
- handshake, the session's srpUsername attribute will be set.
-
- @type certChain: L{tlslite.X509CertChain.X509CertChain} or
- L{cryptoIDlib.CertChain.CertChain}
- @param certChain: The certificate chain to be used if the
- client requests server certificate authentication.
-
- @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
- @param privateKey: The private key to be used if the client
- requests server certificate authentication.
-
- @type reqCert: bool
- @param reqCert: Whether to request client certificate
- authentication. This only applies if the client chooses server
- certificate authentication; if the client chooses SRP or
- shared-key authentication, this will be ignored. If the client
- performs a client certificate authentication, the sessions's
- clientCertChain attribute will be set.
-
- @type sessionCache: L{tlslite.SessionCache.SessionCache}
- @param sessionCache: An in-memory cache of resumable sessions.
- The client can resume sessions from this cache. Alternatively,
- if the client performs a full handshake, a new session will be
- added to the cache.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites and SSL/TLS version chosen by the server.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
- certChain, privateKey, reqCert, sessionCache, settings,
- checker):
- pass
-
-
- def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None,
- certChain=None, privateKey=None, reqCert=False,
- sessionCache=None, settings=None, checker=None):
- """Start a server handshake operation on the TLS connection.
-
- This function returns a generator which behaves similarly to
- handshakeServer(). Successive invocations of the generator
- will return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or it will raise StopIteration
- if the handshake operation is complete.
-
- @rtype: iterable
- @return: A generator; see above for details.
- """
- handshaker = self._handshakeServerAsyncHelper(\
- sharedKeyDB=sharedKeyDB,
- verifierDB=verifierDB, certChain=certChain,
- privateKey=privateKey, reqCert=reqCert,
- sessionCache=sessionCache, settings=settings)
- for result in self._handshakeWrapperAsync(handshaker, checker):
- yield result
-
-
- def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB,
- certChain, privateKey, reqCert, sessionCache,
- settings):
-
- self._handshakeStart(client=False)
-
- if (not sharedKeyDB) and (not verifierDB) and (not certChain):
- raise ValueError("Caller passed no authentication credentials")
- if certChain and not privateKey:
- raise ValueError("Caller passed a certChain but no privateKey")
- if privateKey and not certChain:
- raise ValueError("Caller passed a privateKey but no certChain")
-
- if not settings:
- settings = HandshakeSettings()
- settings = settings._filter()
-
- #Initialize acceptable cipher suites
- cipherSuites = []
- if verifierDB:
- if certChain:
- cipherSuites += \
- CipherSuite.getSrpRsaSuites(settings.cipherNames)
- cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
- if sharedKeyDB or certChain:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
-
- #Initialize acceptable certificate type
- certificateType = None
- if certChain:
- try:
- import cryptoIDlib.CertChain
- if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
- certificateType = CertificateType.cryptoID
- except ImportError:
- pass
- if isinstance(certChain, X509CertChain):
- certificateType = CertificateType.x509
- if certificateType == None:
- raise ValueError("Unrecognized certificate type")
-
- #Initialize locals
- clientCertChain = None
- serverCertChain = None #We may set certChain to this later
- postFinishedError = None
-
- #Tentatively set version to most-desirable version, so if an error
- #occurs parsing the ClientHello, this is what we'll use for the
- #error alert
- self.version = settings.maxVersion
-
- #Get ClientHello
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.client_hello):
- if result in (0,1):
- yield result
- else:
- break
- clientHello = result
-
- #If client's version is too low, reject it
- if clientHello.client_version < settings.minVersion:
- self.version = settings.minVersion
- for result in self._sendError(\
- AlertDescription.protocol_version,
- "Too old version: %s" % str(clientHello.client_version)):
- yield result
-
- #If client's version is too high, propose my highest version
- elif clientHello.client_version > settings.maxVersion:
- self.version = settings.maxVersion
-
- else:
- #Set the version to the client's version
- self.version = clientHello.client_version
-
- #Get the client nonce; create server nonce
- clientRandom = clientHello.random
- serverRandom = getRandomBytes(32)
-
- #Calculate the first cipher suite intersection.
- #This is the 'privileged' ciphersuite. We'll use it if we're
- #doing a shared-key resumption or a new negotiation. In fact,
- #the only time we won't use it is if we're resuming a non-sharedkey
- #session, in which case we use the ciphersuite from the session.
- #
- #Given the current ciphersuite ordering, this means we prefer SRP
- #over non-SRP.
- for cipherSuite in cipherSuites:
- if cipherSuite in clientHello.cipher_suites:
- break
- else:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
-
- #If resumption was requested...
- if clientHello.session_id and (sharedKeyDB or sessionCache):
- session = None
-
- #Check in the sharedKeys container
- if sharedKeyDB and len(clientHello.session_id)==16:
- try:
- #Trim off zero padding, if any
- for x in range(16):
- if clientHello.session_id[x]==0:
- break
- self.allegedSharedKeyUsername = bytesToString(\
- clientHello.session_id[:x])
- session = sharedKeyDB[self.allegedSharedKeyUsername]
- if not session.sharedKey:
- raise AssertionError()
- #use privileged ciphersuite
- session.cipherSuite = cipherSuite
- except KeyError:
- pass
-
- #Then check in the session cache
- if sessionCache and not session:
- try:
- session = sessionCache[bytesToString(\
- clientHello.session_id)]
- if session.sharedKey:
- raise AssertionError()
- if not session.resumable:
- raise AssertionError()
- #Check for consistency with ClientHello
- if session.cipherSuite not in cipherSuites:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
- if session.cipherSuite not in clientHello.cipher_suites:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
- if clientHello.srp_username:
- if clientHello.srp_username != session.srpUsername:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
- except KeyError:
- pass
-
- #If a session is found..
- if session:
- #Set the session
- self.session = session
-
- #Send ServerHello
- serverHello = ServerHello()
- serverHello.create(self.version, serverRandom,
- session.sessionID, session.cipherSuite,
- certificateType)
- for result in self._sendMsg(serverHello):
- yield result
-
- #From here on, the client's messages must have the right version
- self._versionCheck = True
-
- #Calculate pending connection states
- self._calcPendingStates(clientRandom, serverRandom,
- settings.cipherImplementations)
-
- #Exchange ChangeCipherSpec and Finished messages
- for result in self._sendFinished():
- yield result
- for result in self._getFinished():
- yield result
-
- #Mark the connection as open
- self._handshakeDone(resumed=True)
- return
-
-
- #If not a resumption...
-
- #TRICKY: we might have chosen an RSA suite that was only deemed
- #acceptable because of the shared-key resumption. If the shared-
- #key resumption failed, because the identifier wasn't recognized,
- #we might fall through to here, where we have an RSA suite
- #chosen, but no certificate.
- if cipherSuite in CipherSuite.rsaSuites and not certChain:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
-
- #If an RSA suite is chosen, check for certificate type intersection
- #(We do this check down here because if the mismatch occurs but the
- # client is using a shared-key session, it's okay)
- if cipherSuite in CipherSuite.rsaSuites + \
- CipherSuite.srpRsaSuites:
- if certificateType not in clientHello.certificate_types:
- for result in self._sendError(\
- AlertDescription.handshake_failure,
- "the client doesn't support my certificate type"):
- yield result
-
- #Move certChain -> serverCertChain, now that we're using it
- serverCertChain = certChain
-
-
- #Create sessionID
- if sessionCache:
- sessionID = getRandomBytes(32)
- else:
- sessionID = createByteArraySequence([])
-
- #If we've selected an SRP suite, exchange keys and calculate
- #premaster secret:
- if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
-
- #If there's no SRP username...
- if not clientHello.srp_username:
-
- #Ask the client to re-send ClientHello with one
- for result in self._sendMsg(Alert().create(\
- AlertDescription.missing_srp_username,
- AlertLevel.warning)):
- yield result
-
- #Get ClientHello
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.client_hello):
- if result in (0,1):
- yield result
- else:
- break
- clientHello = result
-
- #Check ClientHello
- #If client's version is too low, reject it (COPIED CODE; BAD!)
- if clientHello.client_version < settings.minVersion:
- self.version = settings.minVersion
- for result in self._sendError(\
- AlertDescription.protocol_version,
- "Too old version: %s" % str(clientHello.client_version)):
- yield result
-
- #If client's version is too high, propose my highest version
- elif clientHello.client_version > settings.maxVersion:
- self.version = settings.maxVersion
-
- else:
- #Set the version to the client's version
- self.version = clientHello.client_version
-
- #Recalculate the privileged cipher suite, making sure to
- #pick an SRP suite
- cipherSuites = [c for c in cipherSuites if c in \
- CipherSuite.srpSuites + \
- CipherSuite.srpRsaSuites]
- for cipherSuite in cipherSuites:
- if cipherSuite in clientHello.cipher_suites:
- break
- else:
- for result in self._sendError(\
- AlertDescription.handshake_failure):
- yield result
-
- #Get the client nonce; create server nonce
- clientRandom = clientHello.random
- serverRandom = getRandomBytes(32)
-
- #The username better be there, this time
- if not clientHello.srp_username:
- for result in self._sendError(\
- AlertDescription.illegal_parameter,
- "Client resent a hello, but without the SRP"\
- " username"):
- yield result
-
-
- #Get username
- self.allegedSrpUsername = clientHello.srp_username
-
- #Get parameters from username
- try:
- entry = verifierDB[self.allegedSrpUsername]
- except KeyError:
- for result in self._sendError(\
- AlertDescription.unknown_srp_username):
- yield result
- (N, g, s, v) = entry
-
- #Calculate server's ephemeral DH values (b, B)
- b = bytesToNumber(getRandomBytes(32))
- k = makeK(N, g)
- B = (powMod(g, b, N) + (k*v)) % N
-
- #Create ServerKeyExchange, signing it if necessary
- serverKeyExchange = ServerKeyExchange(cipherSuite)
- serverKeyExchange.createSRP(N, g, stringToBytes(s), B)
- if cipherSuite in CipherSuite.srpRsaSuites:
- hashBytes = serverKeyExchange.hash(clientRandom,
- serverRandom)
- serverKeyExchange.signature = privateKey.sign(hashBytes)
-
- #Send ServerHello[, Certificate], ServerKeyExchange,
- #ServerHelloDone
- msgs = []
- serverHello = ServerHello()
- serverHello.create(self.version, serverRandom, sessionID,
- cipherSuite, certificateType)
- msgs.append(serverHello)
- if cipherSuite in CipherSuite.srpRsaSuites:
- certificateMsg = Certificate(certificateType)
- certificateMsg.create(serverCertChain)
- msgs.append(certificateMsg)
- msgs.append(serverKeyExchange)
- msgs.append(ServerHelloDone())
- for result in self._sendMsgs(msgs):
- yield result
-
- #From here on, the client's messages must have the right version
- self._versionCheck = True
-
- #Get and check ClientKeyExchange
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.client_key_exchange,
- cipherSuite):
- if result in (0,1):
- yield result
- else:
- break
- clientKeyExchange = result
- A = clientKeyExchange.srp_A
- if A % N == 0:
- postFinishedError = (AlertDescription.illegal_parameter,
- "Suspicious A value")
- #Calculate u
- u = makeU(N, A, B)
-
- #Calculate premaster secret
- S = powMod((A * powMod(v,u,N)) % N, b, N)
- premasterSecret = numberToBytes(S)
-
-
- #If we've selected an RSA suite, exchange keys and calculate
- #premaster secret:
- elif cipherSuite in CipherSuite.rsaSuites:
-
- #Send ServerHello, Certificate[, CertificateRequest],
- #ServerHelloDone
- msgs = []
- msgs.append(ServerHello().create(self.version, serverRandom,
- sessionID, cipherSuite, certificateType))
- msgs.append(Certificate(certificateType).create(serverCertChain))
- if reqCert:
- msgs.append(CertificateRequest())
- msgs.append(ServerHelloDone())
- for result in self._sendMsgs(msgs):
- yield result
-
- #From here on, the client's messages must have the right version
- self._versionCheck = True
-
- #Get [Certificate,] (if was requested)
- if reqCert:
- if self.version == (3,0):
- for result in self._getMsg((ContentType.handshake,
- ContentType.alert),
- HandshakeType.certificate,
- certificateType):
- if result in (0,1):
- yield result
- else:
- break
- msg = result
-
- if isinstance(msg, Alert):
- #If it's not a no_certificate alert, re-raise
- alert = msg
- if alert.description != \
- AlertDescription.no_certificate:
- self._shutdown(False)
- raise TLSRemoteAlert(alert)
- elif isinstance(msg, Certificate):
- clientCertificate = msg
- if clientCertificate.certChain and \
- clientCertificate.certChain.getNumCerts()!=0:
- clientCertChain = clientCertificate.certChain
- else:
- raise AssertionError()
- elif self.version in ((3,1), (3,2)):
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.certificate,
- certificateType):
- if result in (0,1):
- yield result
- else:
- break
- clientCertificate = result
- if clientCertificate.certChain and \
- clientCertificate.certChain.getNumCerts()!=0:
- clientCertChain = clientCertificate.certChain
- else:
- raise AssertionError()
-
- #Get ClientKeyExchange
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.client_key_exchange,
- cipherSuite):
- if result in (0,1):
- yield result
- else:
- break
- clientKeyExchange = result
-
- #Decrypt ClientKeyExchange
- premasterSecret = privateKey.decrypt(\
- clientKeyExchange.encryptedPreMasterSecret)
-
- randomPreMasterSecret = getRandomBytes(48)
- versionCheck = (premasterSecret[0], premasterSecret[1])
- if not premasterSecret:
- premasterSecret = randomPreMasterSecret
- elif len(premasterSecret)!=48:
- premasterSecret = randomPreMasterSecret
- elif versionCheck != clientHello.client_version:
- if versionCheck != self.version: #Tolerate buggy IE clients
- premasterSecret = randomPreMasterSecret
-
- #Get and check CertificateVerify, if relevant
- if clientCertChain:
- if self.version == (3,0):
- #Create a temporary session object, just for the purpose
- #of checking the CertificateVerify
- session = Session()
- session._calcMasterSecret(self.version, premasterSecret,
- clientRandom, serverRandom)
- verifyBytes = self._calcSSLHandshakeHash(\
- session.masterSecret, "")
- elif self.version in ((3,1), (3,2)):
- verifyBytes = stringToBytes(self._handshake_md5.digest() +\
- self._handshake_sha.digest())
- for result in self._getMsg(ContentType.handshake,
- HandshakeType.certificate_verify):
- if result in (0,1):
- yield result
- else:
- break
- certificateVerify = result
- publicKey = clientCertChain.getEndEntityPublicKey()
- if len(publicKey) < settings.minKeySize:
- postFinishedError = (AlertDescription.handshake_failure,
- "Client's public key too small: %d" % len(publicKey))
- if len(publicKey) > settings.maxKeySize:
- postFinishedError = (AlertDescription.handshake_failure,
- "Client's public key too large: %d" % len(publicKey))
-
- if not publicKey.verify(certificateVerify.signature,
- verifyBytes):
- postFinishedError = (AlertDescription.decrypt_error,
- "Signature failed to verify")
-
-
- #Create the session object
- self.session = Session()
- self.session._calcMasterSecret(self.version, premasterSecret,
- clientRandom, serverRandom)
- self.session.sessionID = sessionID
- self.session.cipherSuite = cipherSuite
- self.session.srpUsername = self.allegedSrpUsername
- self.session.clientCertChain = clientCertChain
- self.session.serverCertChain = serverCertChain
-
- #Calculate pending connection states
- self._calcPendingStates(clientRandom, serverRandom,
- settings.cipherImplementations)
-
- #Exchange ChangeCipherSpec and Finished messages
- for result in self._getFinished():
- yield result
-
- #If we were holding a post-finished error until receiving the client
- #finished message, send it now. We delay the call until this point
- #because calling sendError() throws an exception, and our caller might
- #shut down the socket upon receiving the exception. If he did, and the
- #client was still sending its ChangeCipherSpec or Finished messages, it
- #would cause a socket error on the client side. This is a lot of
- #consideration to show to misbehaving clients, but this would also
- #cause problems with fault-testing.
- if postFinishedError:
- for result in self._sendError(*postFinishedError):
- yield result
-
- for result in self._sendFinished():
- yield result
-
- #Add the session object to the session cache
- if sessionCache and sessionID:
- sessionCache[bytesToString(sessionID)] = self.session
-
- #Mark the connection as open
- self.session._setResumable(True)
- self._handshakeDone(resumed=False)
-
-
- def _handshakeWrapperAsync(self, handshaker, checker):
- if not self.fault:
- try:
- for result in handshaker:
- yield result
- if checker:
- try:
- checker(self)
- except TLSAuthenticationError:
- alert = Alert().create(AlertDescription.close_notify,
- AlertLevel.fatal)
- for result in self._sendMsg(alert):
- yield result
- raise
- except:
- self._shutdown(False)
- raise
- else:
- try:
- for result in handshaker:
- yield result
- if checker:
- try:
- checker(self)
- except TLSAuthenticationError:
- alert = Alert().create(AlertDescription.close_notify,
- AlertLevel.fatal)
- for result in self._sendMsg(alert):
- yield result
- raise
- except socket.error, e:
- raise TLSFaultError("socket error!")
- except TLSAbruptCloseError, e:
- raise TLSFaultError("abrupt close error!")
- except TLSAlert, alert:
- if alert.description not in Fault.faultAlerts[self.fault]:
- raise TLSFaultError(str(alert))
- else:
- pass
- except:
- self._shutdown(False)
- raise
- else:
- raise TLSFaultError("No error!")
-
-
- def _getKeyFromChain(self, certificate, settings):
- #Get and check cert chain from the Certificate message
- certChain = certificate.certChain
- if not certChain or certChain.getNumCerts() == 0:
- for result in self._sendError(AlertDescription.illegal_parameter,
- "Other party sent a Certificate message without "\
- "certificates"):
- yield result
-
- #Get and check public key from the cert chain
- publicKey = certChain.getEndEntityPublicKey()
- if len(publicKey) < settings.minKeySize:
- for result in self._sendError(AlertDescription.handshake_failure,
- "Other party's public key too small: %d" % len(publicKey)):
- yield result
- if len(publicKey) > settings.maxKeySize:
- for result in self._sendError(AlertDescription.handshake_failure,
- "Other party's public key too large: %d" % len(publicKey)):
- yield result
-
- yield publicKey, certChain