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 |