Chromium Code Reviews| Index: third_party/tlslite/tlslite/tlsconnection.py |
| diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py |
| index 41aab85a71b3726d8cafb6060c94c44000e999a8..e06294064ea563824afb66915bdce3a1b03a9aed 100644 |
| --- a/third_party/tlslite/tlslite/tlsconnection.py |
| +++ b/third_party/tlslite/tlslite/tlsconnection.py |
| @@ -337,8 +337,7 @@ class TLSConnection(TLSRecordLayer): |
| def handshakeClientCert(self, certChain=None, privateKey=None, |
| session=None, settings=None, checker=None, |
| - nextProtos=None, reqTack=True, serverName="", |
| - async=False): |
| + reqTack=True, serverName="", async=False): |
| """Perform a certificate-based handshake in the role of client. |
| This function performs an SSL or TLS handshake. The server |
| @@ -383,11 +382,7 @@ class TLSConnection(TLSRecordLayer): |
| @param checker: A Checker instance. This instance will be |
| invoked to examine the other party's authentication |
| credentials, if the handshake completes succesfully. |
| - |
| - @type nextProtos: list of strings. |
| - @param nextProtos: A list of upper layer protocols ordered by |
| - preference, to use in the Next-Protocol Negotiation Extension. |
| - |
| + |
| @type reqTack: bool |
| @param reqTack: Whether or not to send a "tack" TLS Extension, |
| requesting the server return a TackExtension if it has one. |
| @@ -417,7 +412,7 @@ class TLSConnection(TLSRecordLayer): |
| handshaker = self._handshakeClientAsync(certParams=(certChain, |
| privateKey), session=session, settings=settings, |
| checker=checker, serverName=serverName, |
| - nextProtos=nextProtos, reqTack=reqTack) |
| + reqTack=reqTack) |
| # The handshaker is a Python Generator which executes the handshake. |
| # It allows the handshake to be run in a "piecewise", asynchronous |
| # fashion, returning 1 when it is waiting to able to write, 0 when |
| @@ -433,7 +428,7 @@ class TLSConnection(TLSRecordLayer): |
| def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), |
| session=None, settings=None, checker=None, |
| - nextProtos=None, serverName="", reqTack=True): |
| + serverName="", reqTack=True): |
| handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, |
| certParams=certParams, |
| @@ -441,14 +436,13 @@ class TLSConnection(TLSRecordLayer): |
| session=session, |
| settings=settings, |
| serverName=serverName, |
| - nextProtos=nextProtos, |
| reqTack=reqTack) |
| for result in self._handshakeWrapperAsync(handshaker, checker): |
| yield result |
| def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, |
| - session, settings, serverName, nextProtos, reqTack): |
| + session, settings, serverName, reqTack): |
| self._handshakeStart(client=True) |
| @@ -485,16 +479,19 @@ class TLSConnection(TLSRecordLayer): |
| reqTack = False |
| if not settings or not settings.useExperimentalTackExtension: |
| reqTack = False |
| - if nextProtos is not None: |
| - if len(nextProtos) == 0: |
| - raise ValueError("Caller passed no nextProtos") |
| - |
| # Validates the settings and filters out any unsupported ciphers |
| # or crypto libraries that were requested |
| if not settings: |
| settings = HandshakeSettings() |
| settings = settings._filter() |
| + if settings.alpnProtos is not None: |
| + if len(settings.alpnProtos) == 0: |
| + raise ValueError("Caller passed no alpnProtos") |
| + if settings.nextProtos is not None: |
| + if len(settings.nextProtos) == 0: |
| + raise ValueError("Caller passed no nextProtos") |
| + |
| if clientCertChain: |
| if not isinstance(clientCertChain, X509CertChain): |
| raise ValueError("Unrecognized certificate type") |
| @@ -530,8 +527,7 @@ class TLSConnection(TLSRecordLayer): |
| # Send the ClientHello. |
| for result in self._clientSendClientHello(settings, session, |
| srpUsername, srpParams, certParams, |
| - anonParams, serverName, nextProtos, |
| - reqTack): |
| + anonParams, serverName, reqTack): |
| if result in (0,1): yield result |
| else: break |
| clientHello = result |
| @@ -543,8 +539,6 @@ class TLSConnection(TLSRecordLayer): |
| serverHello = result |
| cipherSuite = serverHello.cipher_suite |
| - # Choose a matching Next Protocol from server list against ours |
| - # (string or None) |
|
davidben
2016/08/04 22:29:26
Unintentional lost comment?
Bence
2016/08/05 14:27:55
Oops. Done.
|
| nextProto = self._clientSelectNextProto(nextProtos, serverHello) |
|
davidben
2016/08/04 22:29:26
This variable isn't even defined anymore. I suspec
Bence
2016/08/05 14:27:55
(1) Done.
(2) I have to admit that I have not run
|
| #If the server elected to resume the session, it is handled here. |
| @@ -615,13 +609,12 @@ class TLSConnection(TLSRecordLayer): |
| self.session = Session() |
| self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| srpUsername, clientCertChain, serverCertChain, |
| - tackExt, serverHello.tackExt!=None, serverName) |
| + tackExt, serverHello.tackExt!=None, None, serverName) |
| self._handshakeDone(resumed=False) |
| - def _clientSendClientHello(self, settings, session, srpUsername, |
| - srpParams, certParams, anonParams, |
| - serverName, nextProtos, reqTack): |
| + def _clientSendClientHello(self, settings, session, srpUsername, srpParams, |
| + certParams, anonParams, serverName, reqTack): |
| #Initialize acceptable ciphersuites |
| cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
| if srpParams: |
| @@ -649,9 +642,10 @@ class TLSConnection(TLSRecordLayer): |
| clientHello = ClientHello() |
| clientHello.create(settings.maxVersion, getRandomBytes(32), |
| session.sessionID, cipherSuites, |
| - certificateTypes, |
| + certificateTypes, |
| session.srpUsername, |
| - reqTack, nextProtos is not None, |
| + reqTack, settings.alpnProtos, |
| + settings.nextProtos is not None, |
| session.serverName) |
| #Or send ClientHello (without) |
| @@ -659,10 +653,10 @@ class TLSConnection(TLSRecordLayer): |
| clientHello = ClientHello() |
| clientHello.create(settings.maxVersion, getRandomBytes(32), |
| bytearray(0), cipherSuites, |
| - certificateTypes, |
| + certificateTypes, |
| srpUsername, |
| - reqTack, nextProtos is not None, |
| - serverName) |
| + reqTack, settings.alpnProtos, |
| + settings.nextProtos is not None, serverName) |
| for result in self._sendMsg(clientHello): |
| yield result |
| yield clientHello |
| @@ -714,6 +708,16 @@ class TLSConnection(TLSRecordLayer): |
| AlertDescription.illegal_parameter, |
| "Server responded with unrequested Tack Extension"): |
| yield result |
| + if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised: |
| + for result in self._sendError(\ |
| + AlertDescription.illegal_parameter, |
| + "Server responded with unrequested ALPN Extension"): |
| + yield result |
| + if serverHello.alpn_proto_selected and serverHello.next_protos: |
| + for result in self._sendError(\ |
| + AlertDescription.illegal_parameter, |
| + "Server responded with both ALPN and NPN extension"): |
| + yield result |
| if serverHello.next_protos and not clientHello.supports_npn: |
| for result in self._sendError(\ |
| AlertDescription.illegal_parameter, |
| @@ -1101,8 +1105,7 @@ class TLSConnection(TLSRecordLayer): |
| certChain=None, privateKey=None, reqCert=False, |
| sessionCache=None, settings=None, checker=None, |
| reqCAs = None, reqCertTypes = None, |
| - tacks=None, activationFlags=0, |
| - nextProtos=None, anon=False, |
| + tacks=None, activationFlags=0, anon=False, |
| signedCertTimestamps=None, |
| fallbackSCSV=False, ocspResponse=None): |
| """Perform a handshake in the role of server. |
| @@ -1172,11 +1175,6 @@ class TLSConnection(TLSRecordLayer): |
| @param reqCertTypes: A list of certificate_type values to be sent |
| along with a certificate request. This does not affect verification. |
| - @type nextProtos: list of strings. |
| - @param nextProtos: A list of upper layer protocols to expose to the |
| - clients through the Next-Protocol Negotiation Extension, |
| - if they support it. |
| - |
| @type signedCertTimestamps: str |
| @param signedCertTimestamps: A SignedCertificateTimestampList (as a |
| binary 8-bit string) that will be sent as a TLS extension whenever |
| @@ -1206,9 +1204,8 @@ class TLSConnection(TLSRecordLayer): |
| """ |
| for result in self.handshakeServerAsync(verifierDB, |
| certChain, privateKey, reqCert, sessionCache, settings, |
| - checker, reqCAs, reqCertTypes, |
| - tacks=tacks, activationFlags=activationFlags, |
| - nextProtos=nextProtos, anon=anon, |
| + checker, reqCAs, reqCertTypes, tacks=tacks, |
| + activationFlags=activationFlags, anon=anon, |
| signedCertTimestamps=signedCertTimestamps, |
| fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
| pass |
| @@ -1218,8 +1215,7 @@ class TLSConnection(TLSRecordLayer): |
| certChain=None, privateKey=None, reqCert=False, |
| sessionCache=None, settings=None, checker=None, |
| reqCAs=None, reqCertTypes=None, |
| - tacks=None, activationFlags=0, |
| - nextProtos=None, anon=False, |
| + tacks=None, activationFlags=0, anon=False, |
| signedCertTimestamps=None, |
| fallbackSCSV=False, |
| ocspResponse=None |
| @@ -1238,10 +1234,9 @@ class TLSConnection(TLSRecordLayer): |
| handshaker = self._handshakeServerAsyncHelper(\ |
| verifierDB=verifierDB, certChain=certChain, |
| privateKey=privateKey, reqCert=reqCert, |
| - sessionCache=sessionCache, settings=settings, |
| + sessionCache=sessionCache, settings=settings, |
| reqCAs=reqCAs, reqCertTypes=reqCertTypes, |
| - tacks=tacks, activationFlags=activationFlags, |
| - nextProtos=nextProtos, anon=anon, |
| + tacks=tacks, activationFlags=activationFlags, anon=anon, |
| signedCertTimestamps=signedCertTimestamps, |
| fallbackSCSV=fallbackSCSV, |
| ocspResponse=ocspResponse) |
| @@ -1256,8 +1251,7 @@ class TLSConnection(TLSRecordLayer): |
| def _handshakeServerAsyncHelper(self, verifierDB, |
| certChain, privateKey, reqCert, sessionCache, |
| settings, reqCAs, reqCertTypes, |
| - tacks, activationFlags, |
| - nextProtos, anon, |
| + tacks, activationFlags, anon, |
| signedCertTimestamps, fallbackSCSV, |
| ocspResponse): |
| @@ -1314,9 +1308,18 @@ class TLSConnection(TLSRecordLayer): |
| sessionID = getRandomBytes(32) |
| else: |
| sessionID = bytearray(0) |
| - |
| + |
| + alpn_proto_selected = None |
| + if clientHello.alpn_protos_advertised is not None: |
| + if settings.alpnProtos is not None: |
| + for proto in settings.alpnProtos: |
| + if proto in clientHello.alpn_protos_advertised: |
| + alpn_proto_selected = proto |
| + settings.nextProtos = None |
| + break; |
| + |
| if not clientHello.supports_npn: |
| - nextProtos = None |
| + settings.nextProtos = None |
|
davidben
2016/08/04 22:29:26
This function probably should not mutate the setti
Bence
2016/08/05 14:27:55
Done.
|
| # If not doing a certificate-based suite, discard the TACK |
| if not cipherSuite in CipherSuite.certAllSuites: |
| @@ -1330,7 +1333,7 @@ class TLSConnection(TLSRecordLayer): |
| serverHello = ServerHello() |
| serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
| cipherSuite, CertificateType.x509, tackExt, |
| - nextProtos) |
| + alpn_proto_selected, settings.nextProtos) |
| serverHello.channel_id = \ |
| clientHello.channel_id and settings.enableChannelID |
| serverHello.extended_master_secret = \ |
| @@ -1397,7 +1400,7 @@ class TLSConnection(TLSRecordLayer): |
| for result in self._serverFinished(premasterSecret, |
| clientHello.random, serverHello.random, |
| cipherSuite, settings.cipherImplementations, |
| - nextProtos, serverHello.channel_id, |
| + settings.nextProtos, serverHello.channel_id, |
| serverHello.extended_master_secret): |
| if result in (0,1): yield result |
| else: break |
| @@ -1420,7 +1423,7 @@ class TLSConnection(TLSRecordLayer): |
| serverName = clientHello.server_name.decode("utf-8") |
| self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| srpUsername, clientCertChain, serverCertChain, |
| - tackExt, serverHello.tackExt!=None, serverName) |
| + tackExt, serverHello.tackExt!=None, alpn_proto_selected, serverName) |
| #Add the session object to the session cache |
| if sessionCache and sessionID: |
| @@ -1540,7 +1543,8 @@ class TLSConnection(TLSRecordLayer): |
| serverHello = ServerHello() |
| serverHello.create(self.version, getRandomBytes(32), |
| session.sessionID, session.cipherSuite, |
| - CertificateType.x509, None, None) |
| + CertificateType.x509, None, |
| + session.alpn_proto_selected, None) |
| serverHello.extended_master_secret = \ |
| clientHello.extended_master_secret and \ |
| settings.enableExtendedMasterSecret |