| Index: third_party/tlslite/patches/alpn.patch
|
| diff --git a/third_party/tlslite/patches/alpn.patch b/third_party/tlslite/patches/alpn.patch
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a52bf63ad8812f5ee291d57670dde182a0c7bfa9
|
| --- /dev/null
|
| +++ b/third_party/tlslite/patches/alpn.patch
|
| @@ -0,0 +1,567 @@
|
| +diff --git a/third_party/tlslite/patches/alpn.patch b/third_party/tlslite/patches/alpn.patch
|
| +new file mode 100644
|
| +index 0000000..e69de29
|
| +diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
|
| +index 715def9..e9743e4 100644
|
| +--- a/third_party/tlslite/tlslite/constants.py
|
| ++++ b/third_party/tlslite/tlslite/constants.py
|
| +@@ -54,6 +54,7 @@ class ExtensionType: # RFC 6066 / 4366
|
| + status_request = 5 # RFC 6066 / 4366
|
| + srp = 12 # RFC 5054
|
| + cert_type = 9 # RFC 6091
|
| ++ alpn = 16 # RFC 7301
|
| + signed_cert_timestamps = 18 # RFC 6962
|
| + extended_master_secret = 23 # RFC 7627
|
| + token_binding = 24 # draft-ietf-tokbind-negotiation
|
| +diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
|
| +index d7be5b3..284c474 100644
|
| +--- a/third_party/tlslite/tlslite/handshakesettings.py
|
| ++++ b/third_party/tlslite/tlslite/handshakesettings.py
|
| +@@ -128,6 +128,18 @@ class HandshakeSettings(object):
|
| +
|
| + Note that TACK support is not standardized by IETF and uses a temporary
|
| + TLS Extension number, so should NOT be used in production software.
|
| ++
|
| ++ @type alpnProtos: list of strings.
|
| ++ @param alpnProtos: A list of supported upper layer protocols to use in the
|
| ++ Application-Layer Protocol Negotiation Extension (RFC 7301). For the
|
| ++ client, the order does not matter. For the server, the list is in
|
| ++ decreasing order of preference.
|
| ++
|
| ++ @type nextProtos: list of strings.
|
| ++ @param nextProtos: A list of supported upper layer protocols to use in the
|
| ++ Next-Protocol Negotiation Extension. For the server, the order does not
|
| ++ matter. For the client, the list is in decreasing order of preference, with
|
| ++ the first entry used for fallback.
|
| + """
|
| + def __init__(self):
|
| + self.minKeySize = 1023
|
| +@@ -146,6 +158,8 @@ class HandshakeSettings(object):
|
| + self.enableChannelID = True
|
| + self.enableExtendedMasterSecret = True
|
| + self.supportedTokenBindingParams = []
|
| ++ self.alpnProtos = None
|
| ++ self.nextProtos = None
|
| +
|
| + # Validates the min/max fields, and certificateTypes
|
| + # Filters out unsupported cipherNames and cipherImplementations
|
| +@@ -166,6 +180,8 @@ class HandshakeSettings(object):
|
| + other.enableChannelID = self.enableChannelID
|
| + other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
|
| + other.supportedTokenBindingParams = self.supportedTokenBindingParams
|
| ++ other.alpnProtos = self.alpnProtos;
|
| ++ other.nextProtos = self.nextProtos;
|
| +
|
| + if not cipherfactory.tripleDESPresent:
|
| + other.cipherNames = [e for e in self.cipherNames if e != "3des"]
|
| +diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
|
| +index 5762ac6..651492b 100644
|
| +--- a/third_party/tlslite/tlslite/messages.py
|
| ++++ b/third_party/tlslite/tlslite/messages.py
|
| +@@ -99,6 +99,27 @@ class HandshakeMsg(object):
|
| + headerWriter.add(len(w.bytes), 3)
|
| + return headerWriter.bytes + w.bytes
|
| +
|
| ++ def parse_next_protos(self, b):
|
| ++ protos = []
|
| ++ while True:
|
| ++ if len(b) == 0:
|
| ++ break
|
| ++ l = b[0]
|
| ++ b = b[1:]
|
| ++ if len(b) < l:
|
| ++ raise BadNextProtos(len(b))
|
| ++ protos.append(b[:l])
|
| ++ b = b[l:]
|
| ++ return protos
|
| ++
|
| ++ def next_protos_encoded(self, protocol_list):
|
| ++ b = bytearray()
|
| ++ for e in protocol_list:
|
| ++ if len(e) > 255 or len(e) == 0:
|
| ++ raise BadNextProtos(len(e))
|
| ++ b += bytearray( [len(e)] ) + bytearray(e)
|
| ++ return b
|
| ++
|
| + class ClientHello(HandshakeMsg):
|
| + def __init__(self, ssl2=False):
|
| + HandshakeMsg.__init__(self, HandshakeType.client_hello)
|
| +@@ -111,6 +132,7 @@ class ClientHello(HandshakeMsg):
|
| + self.compression_methods = [] # a list of 8-bit values
|
| + self.srp_username = None # a string
|
| + self.tack = False
|
| ++ self.alpn_protos_advertised = None
|
| + self.supports_npn = False
|
| + self.server_name = bytearray(0)
|
| + self.channel_id = False
|
| +@@ -120,8 +142,8 @@ class ClientHello(HandshakeMsg):
|
| + self.status_request = False
|
| +
|
| + def create(self, version, random, session_id, cipher_suites,
|
| +- certificate_types=None, srpUsername=None,
|
| +- tack=False, supports_npn=False, serverName=None):
|
| ++ certificate_types=None, srpUsername=None, tack=False,
|
| ++ alpn_protos_advertised=None, supports_npn=False, serverName=None):
|
| + self.client_version = version
|
| + self.random = random
|
| + self.session_id = session_id
|
| +@@ -131,6 +153,7 @@ class ClientHello(HandshakeMsg):
|
| + if srpUsername:
|
| + self.srp_username = bytearray(srpUsername, "utf-8")
|
| + self.tack = tack
|
| ++ self.alpn_protos_advertised = alpn_protos_advertised
|
| + self.supports_npn = supports_npn
|
| + if serverName:
|
| + self.server_name = bytearray(serverName, "utf-8")
|
| +@@ -171,6 +194,11 @@ class ClientHello(HandshakeMsg):
|
| + self.certificate_types = p.getVarList(1, 1)
|
| + elif extType == ExtensionType.tack:
|
| + self.tack = True
|
| ++ elif extType == ExtensionType.alpn:
|
| ++ structLength = p.get(2)
|
| ++ if (structLength + 2 != extLength):
|
| ++ raise SyntaxError()
|
| ++ self.alpn_protos_advertised = self.parse_next_protos(p.getFixBytes(structLength))
|
| + elif extType == ExtensionType.supports_npn:
|
| + self.supports_npn = True
|
| + elif extType == ExtensionType.server_name:
|
| +@@ -243,6 +271,12 @@ class ClientHello(HandshakeMsg):
|
| + w2.add(ExtensionType.srp, 2)
|
| + w2.add(len(self.srp_username)+1, 2)
|
| + w2.addVarSeq(self.srp_username, 1, 1)
|
| ++ if self.alpn_protos_advertised is not None:
|
| ++ encoded_alpn_protos_advertised = self.next_protos_encoded(self.alpn_protos_advertised)
|
| ++ w2.add(ExtensionType.alpn, 2)
|
| ++ w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
|
| ++ w2.add(len(encoded_alpn_protos_advertised), 2)
|
| ++ w2.addFixSeq(encoded_alpn_protos_advertised, 1)
|
| + if self.supports_npn:
|
| + w2.add(ExtensionType.supports_npn, 2)
|
| + w2.add(0, 2)
|
| +@@ -267,6 +301,13 @@ class BadNextProtos(Exception):
|
| + def __str__(self):
|
| + return 'Cannot encode a list of next protocols because it contains an element with invalid length %d. Element lengths must be 0 < x < 256' % self.length
|
| +
|
| ++class InvalidAlpnResponse(Exception):
|
| ++ def __init__(self, l):
|
| ++ self.length = l
|
| ++
|
| ++ def __str__(self):
|
| ++ return 'ALPN server response protocol list has invalid length %d. It must be of length one.' % self.length
|
| ++
|
| + class ServerHello(HandshakeMsg):
|
| + def __init__(self):
|
| + HandshakeMsg.__init__(self, HandshakeType.server_hello)
|
| +@@ -277,6 +318,7 @@ class ServerHello(HandshakeMsg):
|
| + self.certificate_type = CertificateType.x509
|
| + self.compression_method = 0
|
| + self.tackExt = None
|
| ++ self.alpn_proto_selected = None
|
| + self.next_protos_advertised = None
|
| + self.next_protos = None
|
| + self.channel_id = False
|
| +@@ -286,7 +328,8 @@ class ServerHello(HandshakeMsg):
|
| + self.status_request = False
|
| +
|
| + def create(self, version, random, session_id, cipher_suite,
|
| +- certificate_type, tackExt, next_protos_advertised):
|
| ++ certificate_type, tackExt, alpn_proto_selected,
|
| ++ next_protos_advertised):
|
| + self.server_version = version
|
| + self.random = random
|
| + self.session_id = session_id
|
| +@@ -294,6 +337,7 @@ class ServerHello(HandshakeMsg):
|
| + self.certificate_type = certificate_type
|
| + self.compression_method = 0
|
| + self.tackExt = tackExt
|
| ++ self.alpn_proto_selected = alpn_proto_selected
|
| + self.next_protos_advertised = next_protos_advertised
|
| + return self
|
| +
|
| +@@ -316,35 +360,22 @@ class ServerHello(HandshakeMsg):
|
| + self.certificate_type = p.get(1)
|
| + elif extType == ExtensionType.tack and tackpyLoaded:
|
| + self.tackExt = TackExtension(p.getFixBytes(extLength))
|
| ++ elif extType == ExtensionType.alpn:
|
| ++ structLength = p.get(2)
|
| ++ if structLength + 2 != extLength:
|
| ++ raise SyntaxError()
|
| ++ alpn_protos = self.parse_next_protos(p.getFixBytes(structLength))
|
| ++ if alpn_protos.len() != 1:
|
| ++ raise InvalidAlpnResponse(alpn_protos.len());
|
| ++ self.alpn_proto_selected = alpn_protos[0]
|
| + elif extType == ExtensionType.supports_npn:
|
| +- self.next_protos = self.__parse_next_protos(p.getFixBytes(extLength))
|
| ++ self.next_protos = self.parse_next_protos(p.getFixBytes(extLength))
|
| + else:
|
| + p.getFixBytes(extLength)
|
| + soFar += 4 + extLength
|
| + p.stopLengthCheck()
|
| + return self
|
| +
|
| +- def __parse_next_protos(self, b):
|
| +- protos = []
|
| +- while True:
|
| +- if len(b) == 0:
|
| +- break
|
| +- l = b[0]
|
| +- b = b[1:]
|
| +- if len(b) < l:
|
| +- raise BadNextProtos(len(b))
|
| +- protos.append(b[:l])
|
| +- b = b[l:]
|
| +- return protos
|
| +-
|
| +- def __next_protos_encoded(self):
|
| +- b = bytearray()
|
| +- for e in self.next_protos_advertised:
|
| +- if len(e) > 255 or len(e) == 0:
|
| +- raise BadNextProtos(len(e))
|
| +- b += bytearray( [len(e)] ) + bytearray(e)
|
| +- return b
|
| +-
|
| + def write(self):
|
| + w = Writer()
|
| + w.add(self.server_version[0], 1)
|
| +@@ -365,8 +396,15 @@ class ServerHello(HandshakeMsg):
|
| + w2.add(ExtensionType.tack, 2)
|
| + w2.add(len(b), 2)
|
| + w2.bytes += b
|
| ++ if self.alpn_proto_selected is not None:
|
| ++ alpn_protos_single_element_list = [self.alpn_proto_selected]
|
| ++ encoded_alpn_protos_advertised = self.next_protos_encoded(alpn_protos_single_element_list)
|
| ++ w2.add(ExtensionType.alpn, 2)
|
| ++ w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
|
| ++ w2.add(len(encoded_alpn_protos_advertised), 2)
|
| ++ w2.addFixSeq(encoded_alpn_protos_advertised, 1)
|
| + if self.next_protos_advertised is not None:
|
| +- encoded_next_protos_advertised = self.__next_protos_encoded()
|
| ++ encoded_next_protos_advertised = self.next_protos_encoded(self.next_protos_advertised)
|
| + w2.add(ExtensionType.supports_npn, 2)
|
| + w2.add(len(encoded_next_protos_advertised), 2)
|
| + w2.addFixSeq(encoded_next_protos_advertised, 1)
|
| +diff --git a/third_party/tlslite/tlslite/session.py b/third_party/tlslite/tlslite/session.py
|
| +index 6aadf58..7758b7c 100644
|
| +--- a/third_party/tlslite/tlslite/session.py
|
| ++++ b/third_party/tlslite/tlslite/session.py
|
| +@@ -54,11 +54,13 @@ class Session(object):
|
| + self.tackExt = None
|
| + self.tackInHelloExt = False
|
| + self.serverName = ""
|
| ++ self.alpn_proto_selected = None
|
| + self.resumable = False
|
| +
|
| + def create(self, masterSecret, sessionID, cipherSuite,
|
| + srpUsername, clientCertChain, serverCertChain,
|
| +- tackExt, tackInHelloExt, serverName, resumable=True):
|
| ++ tackExt, tackInHelloExt, alpn_proto_selected, serverName,
|
| ++ resumable=True):
|
| + self.masterSecret = masterSecret
|
| + self.sessionID = sessionID
|
| + self.cipherSuite = cipherSuite
|
| +@@ -68,6 +70,7 @@ class Session(object):
|
| + self.tackExt = tackExt
|
| + self.tackInHelloExt = tackInHelloExt
|
| + self.serverName = serverName
|
| ++ self.alpn_proto_selected = alpn_proto_selected
|
| + self.resumable = resumable
|
| +
|
| + def _clone(self):
|
| +@@ -81,6 +84,7 @@ class Session(object):
|
| + other.tackExt = self.tackExt
|
| + other.tackInHelloExt = self.tackInHelloExt
|
| + other.serverName = self.serverName
|
| ++ other.alpn_proto_selected = self.alpn_proto_selected
|
| + other.resumable = self.resumable
|
| + return other
|
| +
|
| +diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
|
| +index 41aab85..e062940 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)
|
| + nextProto = self._clientSelectNextProto(nextProtos, serverHello)
|
| +
|
| + #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
|
| +
|
| + # 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
|
|
|