OLD | NEW |
(Empty) | |
| 1 diff --git a/third_party/tlslite/patches/alpn.patch b/third_party/tlslite/patche
s/alpn.patch |
| 2 new file mode 100644 |
| 3 index 0000000..e69de29 |
| 4 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlsl
ite/constants.py |
| 5 index 715def9..e9743e4 100644 |
| 6 --- a/third_party/tlslite/tlslite/constants.py |
| 7 +++ b/third_party/tlslite/tlslite/constants.py |
| 8 @@ -54,6 +54,7 @@ class ExtensionType: # RFC 6066 / 4366 |
| 9 status_request = 5 # RFC 6066 / 4366 |
| 10 srp = 12 # RFC 5054 |
| 11 cert_type = 9 # RFC 6091 |
| 12 + alpn = 16 # RFC 7301 |
| 13 signed_cert_timestamps = 18 # RFC 6962 |
| 14 extended_master_secret = 23 # RFC 7627 |
| 15 token_binding = 24 # draft-ietf-tokbind-negotiation |
| 16 diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlsl
ite/tlslite/handshakesettings.py |
| 17 index d7be5b3..284c474 100644 |
| 18 --- a/third_party/tlslite/tlslite/handshakesettings.py |
| 19 +++ b/third_party/tlslite/tlslite/handshakesettings.py |
| 20 @@ -128,6 +128,18 @@ class HandshakeSettings(object): |
| 21 |
| 22 Note that TACK support is not standardized by IETF and uses a temporary |
| 23 TLS Extension number, so should NOT be used in production software. |
| 24 + |
| 25 + @type alpnProtos: list of strings. |
| 26 + @param alpnProtos: A list of supported upper layer protocols to use in the |
| 27 + Application-Layer Protocol Negotiation Extension (RFC 7301). For the |
| 28 + client, the order does not matter. For the server, the list is in |
| 29 + decreasing order of preference. |
| 30 + |
| 31 + @type nextProtos: list of strings. |
| 32 + @param nextProtos: A list of supported upper layer protocols to use in the |
| 33 + Next-Protocol Negotiation Extension. For the server, the order does not |
| 34 + matter. For the client, the list is in decreasing order of preference, wit
h |
| 35 + the first entry used for fallback. |
| 36 """ |
| 37 def __init__(self): |
| 38 self.minKeySize = 1023 |
| 39 @@ -146,6 +158,8 @@ class HandshakeSettings(object): |
| 40 self.enableChannelID = True |
| 41 self.enableExtendedMasterSecret = True |
| 42 self.supportedTokenBindingParams = [] |
| 43 + self.alpnProtos = None |
| 44 + self.nextProtos = None |
| 45 |
| 46 # Validates the min/max fields, and certificateTypes |
| 47 # Filters out unsupported cipherNames and cipherImplementations |
| 48 @@ -166,6 +180,8 @@ class HandshakeSettings(object): |
| 49 other.enableChannelID = self.enableChannelID |
| 50 other.enableExtendedMasterSecret = self.enableExtendedMasterSecret |
| 51 other.supportedTokenBindingParams = self.supportedTokenBindingParams |
| 52 + other.alpnProtos = self.alpnProtos; |
| 53 + other.nextProtos = self.nextProtos; |
| 54 |
| 55 if not cipherfactory.tripleDESPresent: |
| 56 other.cipherNames = [e for e in self.cipherNames if e != "3des"] |
| 57 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlsli
te/messages.py |
| 58 index 5762ac6..651492b 100644 |
| 59 --- a/third_party/tlslite/tlslite/messages.py |
| 60 +++ b/third_party/tlslite/tlslite/messages.py |
| 61 @@ -99,6 +99,27 @@ class HandshakeMsg(object): |
| 62 headerWriter.add(len(w.bytes), 3) |
| 63 return headerWriter.bytes + w.bytes |
| 64 |
| 65 + def parse_next_protos(self, b): |
| 66 + protos = [] |
| 67 + while True: |
| 68 + if len(b) == 0: |
| 69 + break |
| 70 + l = b[0] |
| 71 + b = b[1:] |
| 72 + if len(b) < l: |
| 73 + raise BadNextProtos(len(b)) |
| 74 + protos.append(b[:l]) |
| 75 + b = b[l:] |
| 76 + return protos |
| 77 + |
| 78 + def next_protos_encoded(self, protocol_list): |
| 79 + b = bytearray() |
| 80 + for e in protocol_list: |
| 81 + if len(e) > 255 or len(e) == 0: |
| 82 + raise BadNextProtos(len(e)) |
| 83 + b += bytearray( [len(e)] ) + bytearray(e) |
| 84 + return b |
| 85 + |
| 86 class ClientHello(HandshakeMsg): |
| 87 def __init__(self, ssl2=False): |
| 88 HandshakeMsg.__init__(self, HandshakeType.client_hello) |
| 89 @@ -111,6 +132,7 @@ class ClientHello(HandshakeMsg): |
| 90 self.compression_methods = [] # a list of 8-bit values |
| 91 self.srp_username = None # a string |
| 92 self.tack = False |
| 93 + self.alpn_protos_advertised = None |
| 94 self.supports_npn = False |
| 95 self.server_name = bytearray(0) |
| 96 self.channel_id = False |
| 97 @@ -120,8 +142,8 @@ class ClientHello(HandshakeMsg): |
| 98 self.status_request = False |
| 99 |
| 100 def create(self, version, random, session_id, cipher_suites, |
| 101 - certificate_types=None, srpUsername=None, |
| 102 - tack=False, supports_npn=False, serverName=None): |
| 103 + certificate_types=None, srpUsername=None, tack=False, |
| 104 + alpn_protos_advertised=None, supports_npn=False, serverName=None
): |
| 105 self.client_version = version |
| 106 self.random = random |
| 107 self.session_id = session_id |
| 108 @@ -131,6 +153,7 @@ class ClientHello(HandshakeMsg): |
| 109 if srpUsername: |
| 110 self.srp_username = bytearray(srpUsername, "utf-8") |
| 111 self.tack = tack |
| 112 + self.alpn_protos_advertised = alpn_protos_advertised |
| 113 self.supports_npn = supports_npn |
| 114 if serverName: |
| 115 self.server_name = bytearray(serverName, "utf-8") |
| 116 @@ -171,6 +194,11 @@ class ClientHello(HandshakeMsg): |
| 117 self.certificate_types = p.getVarList(1, 1) |
| 118 elif extType == ExtensionType.tack: |
| 119 self.tack = True |
| 120 + elif extType == ExtensionType.alpn: |
| 121 + structLength = p.get(2) |
| 122 + if (structLength + 2 != extLength): |
| 123 + raise SyntaxError() |
| 124 + self.alpn_protos_advertised = self.parse_next_protos(p.
getFixBytes(structLength)) |
| 125 elif extType == ExtensionType.supports_npn: |
| 126 self.supports_npn = True |
| 127 elif extType == ExtensionType.server_name: |
| 128 @@ -243,6 +271,12 @@ class ClientHello(HandshakeMsg): |
| 129 w2.add(ExtensionType.srp, 2) |
| 130 w2.add(len(self.srp_username)+1, 2) |
| 131 w2.addVarSeq(self.srp_username, 1, 1) |
| 132 + if self.alpn_protos_advertised is not None: |
| 133 + encoded_alpn_protos_advertised = self.next_protos_encoded(self.alpn
_protos_advertised) |
| 134 + w2.add(ExtensionType.alpn, 2) |
| 135 + w2.add(len(encoded_alpn_protos_advertised) + 2, 2) |
| 136 + w2.add(len(encoded_alpn_protos_advertised), 2) |
| 137 + w2.addFixSeq(encoded_alpn_protos_advertised, 1) |
| 138 if self.supports_npn: |
| 139 w2.add(ExtensionType.supports_npn, 2) |
| 140 w2.add(0, 2) |
| 141 @@ -267,6 +301,13 @@ class BadNextProtos(Exception): |
| 142 def __str__(self): |
| 143 return 'Cannot encode a list of next protocols because it contains an e
lement with invalid length %d. Element lengths must be 0 < x < 256' % self.lengt
h |
| 144 |
| 145 +class InvalidAlpnResponse(Exception): |
| 146 + def __init__(self, l): |
| 147 + self.length = l |
| 148 + |
| 149 + def __str__(self): |
| 150 + return 'ALPN server response protocol list has invalid length %d. It m
ust be of length one.' % self.length |
| 151 + |
| 152 class ServerHello(HandshakeMsg): |
| 153 def __init__(self): |
| 154 HandshakeMsg.__init__(self, HandshakeType.server_hello) |
| 155 @@ -277,6 +318,7 @@ class ServerHello(HandshakeMsg): |
| 156 self.certificate_type = CertificateType.x509 |
| 157 self.compression_method = 0 |
| 158 self.tackExt = None |
| 159 + self.alpn_proto_selected = None |
| 160 self.next_protos_advertised = None |
| 161 self.next_protos = None |
| 162 self.channel_id = False |
| 163 @@ -286,7 +328,8 @@ class ServerHello(HandshakeMsg): |
| 164 self.status_request = False |
| 165 |
| 166 def create(self, version, random, session_id, cipher_suite, |
| 167 - certificate_type, tackExt, next_protos_advertised): |
| 168 + certificate_type, tackExt, alpn_proto_selected, |
| 169 + next_protos_advertised): |
| 170 self.server_version = version |
| 171 self.random = random |
| 172 self.session_id = session_id |
| 173 @@ -294,6 +337,7 @@ class ServerHello(HandshakeMsg): |
| 174 self.certificate_type = certificate_type |
| 175 self.compression_method = 0 |
| 176 self.tackExt = tackExt |
| 177 + self.alpn_proto_selected = alpn_proto_selected |
| 178 self.next_protos_advertised = next_protos_advertised |
| 179 return self |
| 180 |
| 181 @@ -316,35 +360,22 @@ class ServerHello(HandshakeMsg): |
| 182 self.certificate_type = p.get(1) |
| 183 elif extType == ExtensionType.tack and tackpyLoaded: |
| 184 self.tackExt = TackExtension(p.getFixBytes(extLength)) |
| 185 + elif extType == ExtensionType.alpn: |
| 186 + structLength = p.get(2) |
| 187 + if structLength + 2 != extLength: |
| 188 + raise SyntaxError() |
| 189 + alpn_protos = self.parse_next_protos(p.getFixBytes(structLe
ngth)) |
| 190 + if alpn_protos.len() != 1: |
| 191 + raise InvalidAlpnResponse(alpn_protos.len()); |
| 192 + self.alpn_proto_selected = alpn_protos[0] |
| 193 elif extType == ExtensionType.supports_npn: |
| 194 - self.next_protos = self.__parse_next_protos(p.getFixBytes(e
xtLength)) |
| 195 + self.next_protos = self.parse_next_protos(p.getFixBytes(ext
Length)) |
| 196 else: |
| 197 p.getFixBytes(extLength) |
| 198 soFar += 4 + extLength |
| 199 p.stopLengthCheck() |
| 200 return self |
| 201 |
| 202 - def __parse_next_protos(self, b): |
| 203 - protos = [] |
| 204 - while True: |
| 205 - if len(b) == 0: |
| 206 - break |
| 207 - l = b[0] |
| 208 - b = b[1:] |
| 209 - if len(b) < l: |
| 210 - raise BadNextProtos(len(b)) |
| 211 - protos.append(b[:l]) |
| 212 - b = b[l:] |
| 213 - return protos |
| 214 - |
| 215 - def __next_protos_encoded(self): |
| 216 - b = bytearray() |
| 217 - for e in self.next_protos_advertised: |
| 218 - if len(e) > 255 or len(e) == 0: |
| 219 - raise BadNextProtos(len(e)) |
| 220 - b += bytearray( [len(e)] ) + bytearray(e) |
| 221 - return b |
| 222 - |
| 223 def write(self): |
| 224 w = Writer() |
| 225 w.add(self.server_version[0], 1) |
| 226 @@ -365,8 +396,15 @@ class ServerHello(HandshakeMsg): |
| 227 w2.add(ExtensionType.tack, 2) |
| 228 w2.add(len(b), 2) |
| 229 w2.bytes += b |
| 230 + if self.alpn_proto_selected is not None: |
| 231 + alpn_protos_single_element_list = [self.alpn_proto_selected] |
| 232 + encoded_alpn_protos_advertised = self.next_protos_encoded(alpn_prot
os_single_element_list) |
| 233 + w2.add(ExtensionType.alpn, 2) |
| 234 + w2.add(len(encoded_alpn_protos_advertised) + 2, 2) |
| 235 + w2.add(len(encoded_alpn_protos_advertised), 2) |
| 236 + w2.addFixSeq(encoded_alpn_protos_advertised, 1) |
| 237 if self.next_protos_advertised is not None: |
| 238 - encoded_next_protos_advertised = self.__next_protos_encoded() |
| 239 + encoded_next_protos_advertised = self.next_protos_encoded(self.next
_protos_advertised) |
| 240 w2.add(ExtensionType.supports_npn, 2) |
| 241 w2.add(len(encoded_next_protos_advertised), 2) |
| 242 w2.addFixSeq(encoded_next_protos_advertised, 1) |
| 243 diff --git a/third_party/tlslite/tlslite/session.py b/third_party/tlslite/tlslit
e/session.py |
| 244 index 6aadf58..7758b7c 100644 |
| 245 --- a/third_party/tlslite/tlslite/session.py |
| 246 +++ b/third_party/tlslite/tlslite/session.py |
| 247 @@ -54,11 +54,13 @@ class Session(object): |
| 248 self.tackExt = None |
| 249 self.tackInHelloExt = False |
| 250 self.serverName = "" |
| 251 + self.alpn_proto_selected = None |
| 252 self.resumable = False |
| 253 |
| 254 def create(self, masterSecret, sessionID, cipherSuite, |
| 255 srpUsername, clientCertChain, serverCertChain, |
| 256 - tackExt, tackInHelloExt, serverName, resumable=True): |
| 257 + tackExt, tackInHelloExt, alpn_proto_selected, serverName, |
| 258 + resumable=True): |
| 259 self.masterSecret = masterSecret |
| 260 self.sessionID = sessionID |
| 261 self.cipherSuite = cipherSuite |
| 262 @@ -68,6 +70,7 @@ class Session(object): |
| 263 self.tackExt = tackExt |
| 264 self.tackInHelloExt = tackInHelloExt |
| 265 self.serverName = serverName |
| 266 + self.alpn_proto_selected = alpn_proto_selected |
| 267 self.resumable = resumable |
| 268 |
| 269 def _clone(self): |
| 270 @@ -81,6 +84,7 @@ class Session(object): |
| 271 other.tackExt = self.tackExt |
| 272 other.tackInHelloExt = self.tackInHelloExt |
| 273 other.serverName = self.serverName |
| 274 + other.alpn_proto_selected = self.alpn_proto_selected |
| 275 other.resumable = self.resumable |
| 276 return other |
| 277 |
| 278 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/
tlslite/tlsconnection.py |
| 279 index 41aab85..e062940 100644 |
| 280 --- a/third_party/tlslite/tlslite/tlsconnection.py |
| 281 +++ b/third_party/tlslite/tlslite/tlsconnection.py |
| 282 @@ -337,8 +337,7 @@ class TLSConnection(TLSRecordLayer): |
| 283 |
| 284 def handshakeClientCert(self, certChain=None, privateKey=None, |
| 285 session=None, settings=None, checker=None, |
| 286 - nextProtos=None, reqTack=True, serverName="", |
| 287 - async=False): |
| 288 + reqTack=True, serverName="", async=False): |
| 289 """Perform a certificate-based handshake in the role of client. |
| 290 |
| 291 This function performs an SSL or TLS handshake. The server |
| 292 @@ -383,11 +382,7 @@ class TLSConnection(TLSRecordLayer): |
| 293 @param checker: A Checker instance. This instance will be |
| 294 invoked to examine the other party's authentication |
| 295 credentials, if the handshake completes succesfully. |
| 296 - |
| 297 - @type nextProtos: list of strings. |
| 298 - @param nextProtos: A list of upper layer protocols ordered by |
| 299 - preference, to use in the Next-Protocol Negotiation Extension. |
| 300 - |
| 301 + |
| 302 @type reqTack: bool |
| 303 @param reqTack: Whether or not to send a "tack" TLS Extension, |
| 304 requesting the server return a TackExtension if it has one. |
| 305 @@ -417,7 +412,7 @@ class TLSConnection(TLSRecordLayer): |
| 306 handshaker = self._handshakeClientAsync(certParams=(certChain, |
| 307 privateKey), session=session, settings=settings, |
| 308 checker=checker, serverName=serverName, |
| 309 - nextProtos=nextProtos, reqTack=reqTack) |
| 310 + reqTack=reqTack) |
| 311 # The handshaker is a Python Generator which executes the handshake. |
| 312 # It allows the handshake to be run in a "piecewise", asynchronous |
| 313 # fashion, returning 1 when it is waiting to able to write, 0 when |
| 314 @@ -433,7 +428,7 @@ class TLSConnection(TLSRecordLayer): |
| 315 |
| 316 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), |
| 317 session=None, settings=None, checker=None, |
| 318 - nextProtos=None, serverName="", reqTack=True): |
| 319 + serverName="", reqTack=True): |
| 320 |
| 321 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, |
| 322 certParams=certParams, |
| 323 @@ -441,14 +436,13 @@ class TLSConnection(TLSRecordLayer): |
| 324 session=session, |
| 325 settings=settings, |
| 326 serverName=serverName, |
| 327 - nextProtos=nextProtos, |
| 328 reqTack=reqTack) |
| 329 for result in self._handshakeWrapperAsync(handshaker, checker): |
| 330 yield result |
| 331 |
| 332 |
| 333 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, |
| 334 - session, settings, serverName, nextProtos, reqTa
ck): |
| 335 + session, settings, serverName, reqTack): |
| 336 |
| 337 self._handshakeStart(client=True) |
| 338 |
| 339 @@ -485,16 +479,19 @@ class TLSConnection(TLSRecordLayer): |
| 340 reqTack = False |
| 341 if not settings or not settings.useExperimentalTackExtension: |
| 342 reqTack = False |
| 343 - if nextProtos is not None: |
| 344 - if len(nextProtos) == 0: |
| 345 - raise ValueError("Caller passed no nextProtos") |
| 346 - |
| 347 # Validates the settings and filters out any unsupported ciphers |
| 348 # or crypto libraries that were requested |
| 349 if not settings: |
| 350 settings = HandshakeSettings() |
| 351 settings = settings._filter() |
| 352 |
| 353 + if settings.alpnProtos is not None: |
| 354 + if len(settings.alpnProtos) == 0: |
| 355 + raise ValueError("Caller passed no alpnProtos") |
| 356 + if settings.nextProtos is not None: |
| 357 + if len(settings.nextProtos) == 0: |
| 358 + raise ValueError("Caller passed no nextProtos") |
| 359 + |
| 360 if clientCertChain: |
| 361 if not isinstance(clientCertChain, X509CertChain): |
| 362 raise ValueError("Unrecognized certificate type") |
| 363 @@ -530,8 +527,7 @@ class TLSConnection(TLSRecordLayer): |
| 364 # Send the ClientHello. |
| 365 for result in self._clientSendClientHello(settings, session, |
| 366 srpUsername, srpParams, certParams, |
| 367 - anonParams, serverName, nextProtos, |
| 368 - reqTack): |
| 369 + anonParams, serverName, reqTack): |
| 370 if result in (0,1): yield result |
| 371 else: break |
| 372 clientHello = result |
| 373 @@ -543,8 +539,6 @@ class TLSConnection(TLSRecordLayer): |
| 374 serverHello = result |
| 375 cipherSuite = serverHello.cipher_suite |
| 376 |
| 377 - # Choose a matching Next Protocol from server list against ours |
| 378 - # (string or None) |
| 379 nextProto = self._clientSelectNextProto(nextProtos, serverHello) |
| 380 |
| 381 #If the server elected to resume the session, it is handled here. |
| 382 @@ -615,13 +609,12 @@ class TLSConnection(TLSRecordLayer): |
| 383 self.session = Session() |
| 384 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| 385 srpUsername, clientCertChain, serverCertChain, |
| 386 - tackExt, serverHello.tackExt!=None, serverName) |
| 387 + tackExt, serverHello.tackExt!=None, None, serverName) |
| 388 self._handshakeDone(resumed=False) |
| 389 |
| 390 |
| 391 - def _clientSendClientHello(self, settings, session, srpUsername, |
| 392 - srpParams, certParams, anonParams, |
| 393 - serverName, nextProtos, reqTack): |
| 394 + def _clientSendClientHello(self, settings, session, srpUsername, srpParams, |
| 395 + certParams, anonParams, serverName, reqTack): |
| 396 #Initialize acceptable ciphersuites |
| 397 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
| 398 if srpParams: |
| 399 @@ -649,9 +642,10 @@ class TLSConnection(TLSRecordLayer): |
| 400 clientHello = ClientHello() |
| 401 clientHello.create(settings.maxVersion, getRandomBytes(32), |
| 402 session.sessionID, cipherSuites, |
| 403 - certificateTypes, |
| 404 + certificateTypes, |
| 405 session.srpUsername, |
| 406 - reqTack, nextProtos is not None, |
| 407 + reqTack, settings.alpnProtos, |
| 408 + settings.nextProtos is not None, |
| 409 session.serverName) |
| 410 |
| 411 #Or send ClientHello (without) |
| 412 @@ -659,10 +653,10 @@ class TLSConnection(TLSRecordLayer): |
| 413 clientHello = ClientHello() |
| 414 clientHello.create(settings.maxVersion, getRandomBytes(32), |
| 415 bytearray(0), cipherSuites, |
| 416 - certificateTypes, |
| 417 + certificateTypes, |
| 418 srpUsername, |
| 419 - reqTack, nextProtos is not None, |
| 420 - serverName) |
| 421 + reqTack, settings.alpnProtos, |
| 422 + settings.nextProtos is not None, serverName) |
| 423 for result in self._sendMsg(clientHello): |
| 424 yield result |
| 425 yield clientHello |
| 426 @@ -714,6 +708,16 @@ class TLSConnection(TLSRecordLayer): |
| 427 AlertDescription.illegal_parameter, |
| 428 "Server responded with unrequested Tack Extension"): |
| 429 yield result |
| 430 + if serverHello.alpn_proto_selected and not clientHello.alpn_protos_adve
rtised: |
| 431 + for result in self._sendError(\ |
| 432 + AlertDescription.illegal_parameter, |
| 433 + "Server responded with unrequested ALPN Extension"): |
| 434 + yield result |
| 435 + if serverHello.alpn_proto_selected and serverHello.next_protos: |
| 436 + for result in self._sendError(\ |
| 437 + AlertDescription.illegal_parameter, |
| 438 + "Server responded with both ALPN and NPN extension"): |
| 439 + yield result |
| 440 if serverHello.next_protos and not clientHello.supports_npn: |
| 441 for result in self._sendError(\ |
| 442 AlertDescription.illegal_parameter, |
| 443 @@ -1101,8 +1105,7 @@ class TLSConnection(TLSRecordLayer): |
| 444 certChain=None, privateKey=None, reqCert=False, |
| 445 sessionCache=None, settings=None, checker=None, |
| 446 reqCAs = None, reqCertTypes = None, |
| 447 - tacks=None, activationFlags=0, |
| 448 - nextProtos=None, anon=False, |
| 449 + tacks=None, activationFlags=0, anon=False, |
| 450 signedCertTimestamps=None, |
| 451 fallbackSCSV=False, ocspResponse=None): |
| 452 """Perform a handshake in the role of server. |
| 453 @@ -1172,11 +1175,6 @@ class TLSConnection(TLSRecordLayer): |
| 454 @param reqCertTypes: A list of certificate_type values to be sent |
| 455 along with a certificate request. This does not affect verification. |
| 456 |
| 457 - @type nextProtos: list of strings. |
| 458 - @param nextProtos: A list of upper layer protocols to expose to the |
| 459 - clients through the Next-Protocol Negotiation Extension, |
| 460 - if they support it. |
| 461 - |
| 462 @type signedCertTimestamps: str |
| 463 @param signedCertTimestamps: A SignedCertificateTimestampList (as a |
| 464 binary 8-bit string) that will be sent as a TLS extension whenever |
| 465 @@ -1206,9 +1204,8 @@ class TLSConnection(TLSRecordLayer): |
| 466 """ |
| 467 for result in self.handshakeServerAsync(verifierDB, |
| 468 certChain, privateKey, reqCert, sessionCache, settings, |
| 469 - checker, reqCAs, reqCertTypes, |
| 470 - tacks=tacks, activationFlags=activationFlags, |
| 471 - nextProtos=nextProtos, anon=anon, |
| 472 + checker, reqCAs, reqCertTypes, tacks=tacks, |
| 473 + activationFlags=activationFlags, anon=anon, |
| 474 signedCertTimestamps=signedCertTimestamps, |
| 475 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
| 476 pass |
| 477 @@ -1218,8 +1215,7 @@ class TLSConnection(TLSRecordLayer): |
| 478 certChain=None, privateKey=None, reqCert=False, |
| 479 sessionCache=None, settings=None, checker=None, |
| 480 reqCAs=None, reqCertTypes=None, |
| 481 - tacks=None, activationFlags=0, |
| 482 - nextProtos=None, anon=False, |
| 483 + tacks=None, activationFlags=0, anon=False, |
| 484 signedCertTimestamps=None, |
| 485 fallbackSCSV=False, |
| 486 ocspResponse=None |
| 487 @@ -1238,10 +1234,9 @@ class TLSConnection(TLSRecordLayer): |
| 488 handshaker = self._handshakeServerAsyncHelper(\ |
| 489 verifierDB=verifierDB, certChain=certChain, |
| 490 privateKey=privateKey, reqCert=reqCert, |
| 491 - sessionCache=sessionCache, settings=settings, |
| 492 + sessionCache=sessionCache, settings=settings, |
| 493 reqCAs=reqCAs, reqCertTypes=reqCertTypes, |
| 494 - tacks=tacks, activationFlags=activationFlags, |
| 495 - nextProtos=nextProtos, anon=anon, |
| 496 + tacks=tacks, activationFlags=activationFlags, anon=anon, |
| 497 signedCertTimestamps=signedCertTimestamps, |
| 498 fallbackSCSV=fallbackSCSV, |
| 499 ocspResponse=ocspResponse) |
| 500 @@ -1256,8 +1251,7 @@ class TLSConnection(TLSRecordLayer): |
| 501 def _handshakeServerAsyncHelper(self, verifierDB, |
| 502 certChain, privateKey, reqCert, sessionCache, |
| 503 settings, reqCAs, reqCertTypes, |
| 504 - tacks, activationFlags, |
| 505 - nextProtos, anon, |
| 506 + tacks, activationFlags, anon, |
| 507 signedCertTimestamps, fallbackSCSV, |
| 508 ocspResponse): |
| 509 |
| 510 @@ -1314,9 +1308,18 @@ class TLSConnection(TLSRecordLayer): |
| 511 sessionID = getRandomBytes(32) |
| 512 else: |
| 513 sessionID = bytearray(0) |
| 514 - |
| 515 + |
| 516 + alpn_proto_selected = None |
| 517 + if clientHello.alpn_protos_advertised is not None: |
| 518 + if settings.alpnProtos is not None: |
| 519 + for proto in settings.alpnProtos: |
| 520 + if proto in clientHello.alpn_protos_advertised: |
| 521 + alpn_proto_selected = proto |
| 522 + settings.nextProtos = None |
| 523 + break; |
| 524 + |
| 525 if not clientHello.supports_npn: |
| 526 - nextProtos = None |
| 527 + settings.nextProtos = None |
| 528 |
| 529 # If not doing a certificate-based suite, discard the TACK |
| 530 if not cipherSuite in CipherSuite.certAllSuites: |
| 531 @@ -1330,7 +1333,7 @@ class TLSConnection(TLSRecordLayer): |
| 532 serverHello = ServerHello() |
| 533 serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
| 534 cipherSuite, CertificateType.x509, tackExt, |
| 535 - nextProtos) |
| 536 + alpn_proto_selected, settings.nextProtos) |
| 537 serverHello.channel_id = \ |
| 538 clientHello.channel_id and settings.enableChannelID |
| 539 serverHello.extended_master_secret = \ |
| 540 @@ -1397,7 +1400,7 @@ class TLSConnection(TLSRecordLayer): |
| 541 for result in self._serverFinished(premasterSecret, |
| 542 clientHello.random, serverHello.random, |
| 543 cipherSuite, settings.cipherImplementations, |
| 544 - nextProtos, serverHello.channel_id, |
| 545 + settings.nextProtos, serverHello.channel_id, |
| 546 serverHello.extended_master_secret): |
| 547 if result in (0,1): yield result |
| 548 else: break |
| 549 @@ -1420,7 +1423,7 @@ class TLSConnection(TLSRecordLayer): |
| 550 serverName = clientHello.server_name.decode("utf-8") |
| 551 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
| 552 srpUsername, clientCertChain, serverCertChain, |
| 553 - tackExt, serverHello.tackExt!=None, serverName) |
| 554 + tackExt, serverHello.tackExt!=None, alpn_proto_selected, serverName
) |
| 555 |
| 556 #Add the session object to the session cache |
| 557 if sessionCache and sessionID: |
| 558 @@ -1540,7 +1543,8 @@ class TLSConnection(TLSRecordLayer): |
| 559 serverHello = ServerHello() |
| 560 serverHello.create(self.version, getRandomBytes(32), |
| 561 session.sessionID, session.cipherSuite, |
| 562 - CertificateType.x509, None, None) |
| 563 + CertificateType.x509, None, |
| 564 + session.alpn_proto_selected, None) |
| 565 serverHello.extended_master_secret = \ |
| 566 clientHello.extended_master_secret and \ |
| 567 settings.enableExtendedMasterSecret |
OLD | NEW |