OLD | NEW |
---|---|
1 # Authors: | 1 # Authors: |
2 # Trevor Perrin | 2 # Trevor Perrin |
3 # Google - added reqCAs parameter | 3 # Google - added reqCAs parameter |
4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support | 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support |
5 # Dimitris Moraitis - Anon ciphersuites | 5 # Dimitris Moraitis - Anon ciphersuites |
6 # Martin von Loewis - python 3 port | 6 # Martin von Loewis - python 3 port |
7 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 | 7 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 |
8 # | 8 # |
9 # See the LICENSE file for legal information regarding use of this file. | 9 # See the LICENSE file for legal information regarding use of this file. |
10 | 10 |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 # | 330 # |
331 # If 'async' is True, the generator is returned to the caller, | 331 # If 'async' is True, the generator is returned to the caller, |
332 # otherwise it is executed to completion here. | 332 # otherwise it is executed to completion here. |
333 if async: | 333 if async: |
334 return handshaker | 334 return handshaker |
335 for result in handshaker: | 335 for result in handshaker: |
336 pass | 336 pass |
337 | 337 |
338 def handshakeClientCert(self, certChain=None, privateKey=None, | 338 def handshakeClientCert(self, certChain=None, privateKey=None, |
339 session=None, settings=None, checker=None, | 339 session=None, settings=None, checker=None, |
340 nextProtos=None, reqTack=True, serverName="", | 340 reqTack=True, serverName="", async=False): |
341 async=False): | |
342 """Perform a certificate-based handshake in the role of client. | 341 """Perform a certificate-based handshake in the role of client. |
343 | 342 |
344 This function performs an SSL or TLS handshake. The server | 343 This function performs an SSL or TLS handshake. The server |
345 will authenticate itself using an X.509 certificate | 344 will authenticate itself using an X.509 certificate |
346 chain. If the handshake succeeds, the server's certificate | 345 chain. If the handshake succeeds, the server's certificate |
347 chain will be stored in the session's serverCertChain attribute. | 346 chain will be stored in the session's serverCertChain attribute. |
348 Unless a checker object is passed in, this function does no | 347 Unless a checker object is passed in, this function does no |
349 validation or checking of the server's certificate chain. | 348 validation or checking of the server's certificate chain. |
350 | 349 |
351 If the server requests client authentication, the | 350 If the server requests client authentication, the |
(...skipping 24 matching lines...) Expand all Loading... | |
376 | 375 |
377 @type settings: L{tlslite.handshakesettings.HandshakeSettings} | 376 @type settings: L{tlslite.handshakesettings.HandshakeSettings} |
378 @param settings: Various settings which can be used to control | 377 @param settings: Various settings which can be used to control |
379 the ciphersuites, certificate types, and SSL/TLS versions | 378 the ciphersuites, certificate types, and SSL/TLS versions |
380 offered by the client. | 379 offered by the client. |
381 | 380 |
382 @type checker: L{tlslite.checker.Checker} | 381 @type checker: L{tlslite.checker.Checker} |
383 @param checker: A Checker instance. This instance will be | 382 @param checker: A Checker instance. This instance will be |
384 invoked to examine the other party's authentication | 383 invoked to examine the other party's authentication |
385 credentials, if the handshake completes succesfully. | 384 credentials, if the handshake completes succesfully. |
386 | 385 |
387 @type nextProtos: list of strings. | |
388 @param nextProtos: A list of upper layer protocols ordered by | |
389 preference, to use in the Next-Protocol Negotiation Extension. | |
390 | |
391 @type reqTack: bool | 386 @type reqTack: bool |
392 @param reqTack: Whether or not to send a "tack" TLS Extension, | 387 @param reqTack: Whether or not to send a "tack" TLS Extension, |
393 requesting the server return a TackExtension if it has one. | 388 requesting the server return a TackExtension if it has one. |
394 | 389 |
395 @type serverName: string | 390 @type serverName: string |
396 @param serverName: The ServerNameIndication TLS Extension. | 391 @param serverName: The ServerNameIndication TLS Extension. |
397 | 392 |
398 @type async: bool | 393 @type async: bool |
399 @param async: If False, this function will block until the | 394 @param async: If False, this function will block until the |
400 handshake is completed. If True, this function will return a | 395 handshake is completed. If True, this function will return a |
401 generator. Successive invocations of the generator will | 396 generator. Successive invocations of the generator will |
402 return 0 if it is waiting to read from the socket, 1 if it is | 397 return 0 if it is waiting to read from the socket, 1 if it is |
403 waiting to write to the socket, or will raise StopIteration if | 398 waiting to write to the socket, or will raise StopIteration if |
404 the handshake operation is completed. | 399 the handshake operation is completed. |
405 | 400 |
406 @rtype: None or an iterable | 401 @rtype: None or an iterable |
407 @return: If 'async' is True, a generator object will be | 402 @return: If 'async' is True, a generator object will be |
408 returned. | 403 returned. |
409 | 404 |
410 @raise socket.error: If a socket error occurs. | 405 @raise socket.error: If a socket error occurs. |
411 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 406 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
412 without a preceding alert. | 407 without a preceding alert. |
413 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 408 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
414 @raise tlslite.errors.TLSAuthenticationError: If the checker | 409 @raise tlslite.errors.TLSAuthenticationError: If the checker |
415 doesn't like the other party's authentication credentials. | 410 doesn't like the other party's authentication credentials. |
416 """ | 411 """ |
417 handshaker = self._handshakeClientAsync(certParams=(certChain, | 412 handshaker = self._handshakeClientAsync(certParams=(certChain, |
418 privateKey), session=session, settings=settings, | 413 privateKey), session=session, settings=settings, |
419 checker=checker, serverName=serverName, | 414 checker=checker, serverName=serverName, |
420 nextProtos=nextProtos, reqTack=reqTack) | 415 reqTack=reqTack) |
421 # The handshaker is a Python Generator which executes the handshake. | 416 # The handshaker is a Python Generator which executes the handshake. |
422 # It allows the handshake to be run in a "piecewise", asynchronous | 417 # It allows the handshake to be run in a "piecewise", asynchronous |
423 # fashion, returning 1 when it is waiting to able to write, 0 when | 418 # fashion, returning 1 when it is waiting to able to write, 0 when |
424 # it is waiting to read. | 419 # it is waiting to read. |
425 # | 420 # |
426 # If 'async' is True, the generator is returned to the caller, | 421 # If 'async' is True, the generator is returned to the caller, |
427 # otherwise it is executed to completion here. | 422 # otherwise it is executed to completion here. |
428 if async: | 423 if async: |
429 return handshaker | 424 return handshaker |
430 for result in handshaker: | 425 for result in handshaker: |
431 pass | 426 pass |
432 | 427 |
433 | 428 |
434 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), | 429 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), |
435 session=None, settings=None, checker=None, | 430 session=None, settings=None, checker=None, |
436 nextProtos=None, serverName="", reqTack=True): | 431 serverName="", reqTack=True): |
437 | 432 |
438 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, | 433 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, |
439 certParams=certParams, | 434 certParams=certParams, |
440 anonParams=anonParams, | 435 anonParams=anonParams, |
441 session=session, | 436 session=session, |
442 settings=settings, | 437 settings=settings, |
443 serverName=serverName, | 438 serverName=serverName, |
444 nextProtos=nextProtos, | |
445 reqTack=reqTack) | 439 reqTack=reqTack) |
446 for result in self._handshakeWrapperAsync(handshaker, checker): | 440 for result in self._handshakeWrapperAsync(handshaker, checker): |
447 yield result | 441 yield result |
448 | 442 |
449 | 443 |
450 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, | 444 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, |
451 session, settings, serverName, nextProtos, reqTac k): | 445 session, settings, serverName, reqTack): |
452 | 446 |
453 self._handshakeStart(client=True) | 447 self._handshakeStart(client=True) |
454 | 448 |
455 #Unpack parameters | 449 #Unpack parameters |
456 srpUsername = None # srpParams[0] | 450 srpUsername = None # srpParams[0] |
457 password = None # srpParams[1] | 451 password = None # srpParams[1] |
458 clientCertChain = None # certParams[0] | 452 clientCertChain = None # certParams[0] |
459 privateKey = None # certParams[1] | 453 privateKey = None # certParams[1] |
460 | 454 |
461 # Allow only one of (srpParams, certParams, anonParams) | 455 # Allow only one of (srpParams, certParams, anonParams) |
(...skipping 16 matching lines...) Expand all Loading... | |
478 raise ValueError("Caller passed a password but no username") | 472 raise ValueError("Caller passed a password but no username") |
479 if clientCertChain and not privateKey: | 473 if clientCertChain and not privateKey: |
480 raise ValueError("Caller passed a certChain but no privateKey") | 474 raise ValueError("Caller passed a certChain but no privateKey") |
481 if privateKey and not clientCertChain: | 475 if privateKey and not clientCertChain: |
482 raise ValueError("Caller passed a privateKey but no certChain") | 476 raise ValueError("Caller passed a privateKey but no certChain") |
483 if reqTack: | 477 if reqTack: |
484 if not tackpyLoaded: | 478 if not tackpyLoaded: |
485 reqTack = False | 479 reqTack = False |
486 if not settings or not settings.useExperimentalTackExtension: | 480 if not settings or not settings.useExperimentalTackExtension: |
487 reqTack = False | 481 reqTack = False |
488 if nextProtos is not None: | |
489 if len(nextProtos) == 0: | |
490 raise ValueError("Caller passed no nextProtos") | |
491 | |
492 # Validates the settings and filters out any unsupported ciphers | 482 # Validates the settings and filters out any unsupported ciphers |
493 # or crypto libraries that were requested | 483 # or crypto libraries that were requested |
494 if not settings: | 484 if not settings: |
495 settings = HandshakeSettings() | 485 settings = HandshakeSettings() |
496 settings = settings._filter() | 486 settings = settings._filter() |
497 | 487 |
488 if settings.alpnProtos is not None: | |
489 if len(settings.alpnProtos) == 0: | |
490 raise ValueError("Caller passed no alpnProtos") | |
491 if settings.nextProtos is not None: | |
492 if len(settings.nextProtos) == 0: | |
493 raise ValueError("Caller passed no nextProtos") | |
494 | |
498 if clientCertChain: | 495 if clientCertChain: |
499 if not isinstance(clientCertChain, X509CertChain): | 496 if not isinstance(clientCertChain, X509CertChain): |
500 raise ValueError("Unrecognized certificate type") | 497 raise ValueError("Unrecognized certificate type") |
501 if "x509" not in settings.certificateTypes: | 498 if "x509" not in settings.certificateTypes: |
502 raise ValueError("Client certificate doesn't match "\ | 499 raise ValueError("Client certificate doesn't match "\ |
503 "Handshake Settings") | 500 "Handshake Settings") |
504 | 501 |
505 if session: | 502 if session: |
506 # session.valid() ensures session is resumable and has | 503 # session.valid() ensures session is resumable and has |
507 # non-empty sessionID | 504 # non-empty sessionID |
(...skipping 15 matching lines...) Expand all Loading... | |
523 #We'll use this for the ClientHello, and if an error occurs | 520 #We'll use this for the ClientHello, and if an error occurs |
524 #parsing the Server Hello, we'll use this version for the response | 521 #parsing the Server Hello, we'll use this version for the response |
525 self.version = settings.maxVersion | 522 self.version = settings.maxVersion |
526 | 523 |
527 # OK Start sending messages! | 524 # OK Start sending messages! |
528 # ***************************** | 525 # ***************************** |
529 | 526 |
530 # Send the ClientHello. | 527 # Send the ClientHello. |
531 for result in self._clientSendClientHello(settings, session, | 528 for result in self._clientSendClientHello(settings, session, |
532 srpUsername, srpParams, certParams, | 529 srpUsername, srpParams, certParams, |
533 anonParams, serverName, nextProtos, | 530 anonParams, serverName, reqTack): |
534 reqTack): | |
535 if result in (0,1): yield result | 531 if result in (0,1): yield result |
536 else: break | 532 else: break |
537 clientHello = result | 533 clientHello = result |
538 | 534 |
539 #Get the ServerHello. | 535 #Get the ServerHello. |
540 for result in self._clientGetServerHello(settings, clientHello): | 536 for result in self._clientGetServerHello(settings, clientHello): |
541 if result in (0,1): yield result | 537 if result in (0,1): yield result |
542 else: break | 538 else: break |
543 serverHello = result | 539 serverHello = result |
544 cipherSuite = serverHello.cipher_suite | 540 cipherSuite = serverHello.cipher_suite |
545 | 541 |
546 # Choose a matching Next Protocol from server list against ours | |
547 # (string or None) | |
davidben
2016/08/04 22:29:26
Unintentional lost comment?
Bence
2016/08/05 14:27:55
Oops. Done.
| |
548 nextProto = self._clientSelectNextProto(nextProtos, serverHello) | 542 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
| |
549 | 543 |
550 #If the server elected to resume the session, it is handled here. | 544 #If the server elected to resume the session, it is handled here. |
551 for result in self._clientResume(session, serverHello, | 545 for result in self._clientResume(session, serverHello, |
552 clientHello.random, | 546 clientHello.random, |
553 settings.cipherImplementations, | 547 settings.cipherImplementations, |
554 nextProto): | 548 nextProto): |
555 if result in (0,1): yield result | 549 if result in (0,1): yield result |
556 else: break | 550 else: break |
557 if result == "resumed_and_finished": | 551 if result == "resumed_and_finished": |
558 self._handshakeDone(resumed=True) | 552 self._handshakeDone(resumed=True) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 else: break | 602 else: break |
609 masterSecret = result | 603 masterSecret = result |
610 | 604 |
611 self.clientRandom = clientHello.random | 605 self.clientRandom = clientHello.random |
612 self.serverRandom = serverHello.random | 606 self.serverRandom = serverHello.random |
613 | 607 |
614 # Create the session object which is used for resumptions | 608 # Create the session object which is used for resumptions |
615 self.session = Session() | 609 self.session = Session() |
616 self.session.create(masterSecret, serverHello.session_id, cipherSuite, | 610 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
617 srpUsername, clientCertChain, serverCertChain, | 611 srpUsername, clientCertChain, serverCertChain, |
618 tackExt, serverHello.tackExt!=None, serverName) | 612 tackExt, serverHello.tackExt!=None, None, serverName) |
619 self._handshakeDone(resumed=False) | 613 self._handshakeDone(resumed=False) |
620 | 614 |
621 | 615 |
622 def _clientSendClientHello(self, settings, session, srpUsername, | 616 def _clientSendClientHello(self, settings, session, srpUsername, srpParams, |
623 srpParams, certParams, anonParams, | 617 certParams, anonParams, serverName, reqTack): |
624 serverName, nextProtos, reqTack): | |
625 #Initialize acceptable ciphersuites | 618 #Initialize acceptable ciphersuites |
626 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] | 619 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
627 if srpParams: | 620 if srpParams: |
628 cipherSuites += CipherSuite.getSrpAllSuites(settings) | 621 cipherSuites += CipherSuite.getSrpAllSuites(settings) |
629 elif certParams: | 622 elif certParams: |
630 # TODO: Client DHE_RSA not supported. | 623 # TODO: Client DHE_RSA not supported. |
631 # cipherSuites += CipherSuite.getDheCertSuites(settings) | 624 # cipherSuites += CipherSuite.getDheCertSuites(settings) |
632 cipherSuites += CipherSuite.getCertSuites(settings) | 625 cipherSuites += CipherSuite.getCertSuites(settings) |
633 elif anonParams: | 626 elif anonParams: |
634 cipherSuites += CipherSuite.getAnonSuites(settings) | 627 cipherSuites += CipherSuite.getAnonSuites(settings) |
635 else: | 628 else: |
636 assert(False) | 629 assert(False) |
637 | 630 |
638 #Initialize acceptable certificate types | 631 #Initialize acceptable certificate types |
639 certificateTypes = settings._getCertificateTypes() | 632 certificateTypes = settings._getCertificateTypes() |
640 | 633 |
641 #Either send ClientHello (with a resumable session)... | 634 #Either send ClientHello (with a resumable session)... |
642 if session and session.sessionID: | 635 if session and session.sessionID: |
643 #If it's resumable, then its | 636 #If it's resumable, then its |
644 #ciphersuite must be one of the acceptable ciphersuites | 637 #ciphersuite must be one of the acceptable ciphersuites |
645 if session.cipherSuite not in cipherSuites: | 638 if session.cipherSuite not in cipherSuites: |
646 raise ValueError("Session's cipher suite not consistent "\ | 639 raise ValueError("Session's cipher suite not consistent "\ |
647 "with parameters") | 640 "with parameters") |
648 else: | 641 else: |
649 clientHello = ClientHello() | 642 clientHello = ClientHello() |
650 clientHello.create(settings.maxVersion, getRandomBytes(32), | 643 clientHello.create(settings.maxVersion, getRandomBytes(32), |
651 session.sessionID, cipherSuites, | 644 session.sessionID, cipherSuites, |
652 certificateTypes, | 645 certificateTypes, |
653 session.srpUsername, | 646 session.srpUsername, |
654 reqTack, nextProtos is not None, | 647 reqTack, settings.alpnProtos, |
648 settings.nextProtos is not None, | |
655 session.serverName) | 649 session.serverName) |
656 | 650 |
657 #Or send ClientHello (without) | 651 #Or send ClientHello (without) |
658 else: | 652 else: |
659 clientHello = ClientHello() | 653 clientHello = ClientHello() |
660 clientHello.create(settings.maxVersion, getRandomBytes(32), | 654 clientHello.create(settings.maxVersion, getRandomBytes(32), |
661 bytearray(0), cipherSuites, | 655 bytearray(0), cipherSuites, |
662 certificateTypes, | 656 certificateTypes, |
663 srpUsername, | 657 srpUsername, |
664 reqTack, nextProtos is not None, | 658 reqTack, settings.alpnProtos, |
665 serverName) | 659 settings.nextProtos is not None, serverName) |
666 for result in self._sendMsg(clientHello): | 660 for result in self._sendMsg(clientHello): |
667 yield result | 661 yield result |
668 yield clientHello | 662 yield clientHello |
669 | 663 |
670 | 664 |
671 def _clientGetServerHello(self, settings, clientHello): | 665 def _clientGetServerHello(self, settings, clientHello): |
672 for result in self._getMsg(ContentType.handshake, | 666 for result in self._getMsg(ContentType.handshake, |
673 HandshakeType.server_hello): | 667 HandshakeType.server_hello): |
674 if result in (0,1): yield result | 668 if result in (0,1): yield result |
675 else: break | 669 else: break |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
707 for result in self._sendError(\ | 701 for result in self._sendError(\ |
708 AlertDescription.illegal_parameter, | 702 AlertDescription.illegal_parameter, |
709 "Server responded with incorrect compression method"): | 703 "Server responded with incorrect compression method"): |
710 yield result | 704 yield result |
711 if serverHello.tackExt: | 705 if serverHello.tackExt: |
712 if not clientHello.tack: | 706 if not clientHello.tack: |
713 for result in self._sendError(\ | 707 for result in self._sendError(\ |
714 AlertDescription.illegal_parameter, | 708 AlertDescription.illegal_parameter, |
715 "Server responded with unrequested Tack Extension"): | 709 "Server responded with unrequested Tack Extension"): |
716 yield result | 710 yield result |
711 if serverHello.alpn_proto_selected and not clientHello.alpn_protos_adver tised: | |
712 for result in self._sendError(\ | |
713 AlertDescription.illegal_parameter, | |
714 "Server responded with unrequested ALPN Extension"): | |
715 yield result | |
716 if serverHello.alpn_proto_selected and serverHello.next_protos: | |
717 for result in self._sendError(\ | |
718 AlertDescription.illegal_parameter, | |
719 "Server responded with both ALPN and NPN extension"): | |
720 yield result | |
717 if serverHello.next_protos and not clientHello.supports_npn: | 721 if serverHello.next_protos and not clientHello.supports_npn: |
718 for result in self._sendError(\ | 722 for result in self._sendError(\ |
719 AlertDescription.illegal_parameter, | 723 AlertDescription.illegal_parameter, |
720 "Server responded with unrequested NPN Extension"): | 724 "Server responded with unrequested NPN Extension"): |
721 yield result | 725 yield result |
722 if not serverHello.tackExt.verifySignatures(): | 726 if not serverHello.tackExt.verifySignatures(): |
723 for result in self._sendError(\ | 727 for result in self._sendError(\ |
724 AlertDescription.decrypt_error, | 728 AlertDescription.decrypt_error, |
725 "TackExtension contains an invalid signature"): | 729 "TackExtension contains an invalid signature"): |
726 yield result | 730 yield result |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1094 | 1098 |
1095 #********************************************************* | 1099 #********************************************************* |
1096 # Server Handshake Functions | 1100 # Server Handshake Functions |
1097 #********************************************************* | 1101 #********************************************************* |
1098 | 1102 |
1099 | 1103 |
1100 def handshakeServer(self, verifierDB=None, | 1104 def handshakeServer(self, verifierDB=None, |
1101 certChain=None, privateKey=None, reqCert=False, | 1105 certChain=None, privateKey=None, reqCert=False, |
1102 sessionCache=None, settings=None, checker=None, | 1106 sessionCache=None, settings=None, checker=None, |
1103 reqCAs = None, reqCertTypes = None, | 1107 reqCAs = None, reqCertTypes = None, |
1104 tacks=None, activationFlags=0, | 1108 tacks=None, activationFlags=0, anon=False, |
1105 nextProtos=None, anon=False, | |
1106 signedCertTimestamps=None, | 1109 signedCertTimestamps=None, |
1107 fallbackSCSV=False, ocspResponse=None): | 1110 fallbackSCSV=False, ocspResponse=None): |
1108 """Perform a handshake in the role of server. | 1111 """Perform a handshake in the role of server. |
1109 | 1112 |
1110 This function performs an SSL or TLS handshake. Depending on | 1113 This function performs an SSL or TLS handshake. Depending on |
1111 the arguments and the behavior of the client, this function can | 1114 the arguments and the behavior of the client, this function can |
1112 perform an SRP, or certificate-based handshake. It | 1115 perform an SRP, or certificate-based handshake. It |
1113 can also perform a combined SRP and server-certificate | 1116 can also perform a combined SRP and server-certificate |
1114 handshake. | 1117 handshake. |
1115 | 1118 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1165 | 1168 |
1166 @type reqCAs: list of L{bytearray} of unsigned bytes | 1169 @type reqCAs: list of L{bytearray} of unsigned bytes |
1167 @param reqCAs: A collection of DER-encoded DistinguishedNames that | 1170 @param reqCAs: A collection of DER-encoded DistinguishedNames that |
1168 will be sent along with a certificate request. This does not affect | 1171 will be sent along with a certificate request. This does not affect |
1169 verification. | 1172 verification. |
1170 | 1173 |
1171 @type reqCertTypes: list of int | 1174 @type reqCertTypes: list of int |
1172 @param reqCertTypes: A list of certificate_type values to be sent | 1175 @param reqCertTypes: A list of certificate_type values to be sent |
1173 along with a certificate request. This does not affect verification. | 1176 along with a certificate request. This does not affect verification. |
1174 | 1177 |
1175 @type nextProtos: list of strings. | |
1176 @param nextProtos: A list of upper layer protocols to expose to the | |
1177 clients through the Next-Protocol Negotiation Extension, | |
1178 if they support it. | |
1179 | |
1180 @type signedCertTimestamps: str | 1178 @type signedCertTimestamps: str |
1181 @param signedCertTimestamps: A SignedCertificateTimestampList (as a | 1179 @param signedCertTimestamps: A SignedCertificateTimestampList (as a |
1182 binary 8-bit string) that will be sent as a TLS extension whenever | 1180 binary 8-bit string) that will be sent as a TLS extension whenever |
1183 the client announces support for the extension. | 1181 the client announces support for the extension. |
1184 | 1182 |
1185 @type fallbackSCSV: bool | 1183 @type fallbackSCSV: bool |
1186 @param fallbackSCSV: if true, the server will implement | 1184 @param fallbackSCSV: if true, the server will implement |
1187 TLS_FALLBACK_SCSV and thus reject connections using less than the | 1185 TLS_FALLBACK_SCSV and thus reject connections using less than the |
1188 server's maximum TLS version that include this cipher suite. | 1186 server's maximum TLS version that include this cipher suite. |
1189 | 1187 |
1190 @type ocspResponse: str | 1188 @type ocspResponse: str |
1191 @param ocspResponse: An OCSP response (as a binary 8-bit string) that | 1189 @param ocspResponse: An OCSP response (as a binary 8-bit string) that |
1192 will be sent stapled in the handshake whenever the client announces | 1190 will be sent stapled in the handshake whenever the client announces |
1193 support for the status_request extension. | 1191 support for the status_request extension. |
1194 Note that the response is sent independent of the ClientHello | 1192 Note that the response is sent independent of the ClientHello |
1195 status_request extension contents, and is thus only meant for testing | 1193 status_request extension contents, and is thus only meant for testing |
1196 environments. Real OCSP stapling is more complicated as it requires | 1194 environments. Real OCSP stapling is more complicated as it requires |
1197 choosing a suitable response based on the ClientHello status_request | 1195 choosing a suitable response based on the ClientHello status_request |
1198 extension contents. | 1196 extension contents. |
1199 | 1197 |
1200 @raise socket.error: If a socket error occurs. | 1198 @raise socket.error: If a socket error occurs. |
1201 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed | 1199 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
1202 without a preceding alert. | 1200 without a preceding alert. |
1203 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. | 1201 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. |
1204 @raise tlslite.errors.TLSAuthenticationError: If the checker | 1202 @raise tlslite.errors.TLSAuthenticationError: If the checker |
1205 doesn't like the other party's authentication credentials. | 1203 doesn't like the other party's authentication credentials. |
1206 """ | 1204 """ |
1207 for result in self.handshakeServerAsync(verifierDB, | 1205 for result in self.handshakeServerAsync(verifierDB, |
1208 certChain, privateKey, reqCert, sessionCache, settings, | 1206 certChain, privateKey, reqCert, sessionCache, settings, |
1209 checker, reqCAs, reqCertTypes, | 1207 checker, reqCAs, reqCertTypes, tacks=tacks, |
1210 tacks=tacks, activationFlags=activationFlags, | 1208 activationFlags=activationFlags, anon=anon, |
1211 nextProtos=nextProtos, anon=anon, | |
1212 signedCertTimestamps=signedCertTimestamps, | 1209 signedCertTimestamps=signedCertTimestamps, |
1213 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): | 1210 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
1214 pass | 1211 pass |
1215 | 1212 |
1216 | 1213 |
1217 def handshakeServerAsync(self, verifierDB=None, | 1214 def handshakeServerAsync(self, verifierDB=None, |
1218 certChain=None, privateKey=None, reqCert=False, | 1215 certChain=None, privateKey=None, reqCert=False, |
1219 sessionCache=None, settings=None, checker=None, | 1216 sessionCache=None, settings=None, checker=None, |
1220 reqCAs=None, reqCertTypes=None, | 1217 reqCAs=None, reqCertTypes=None, |
1221 tacks=None, activationFlags=0, | 1218 tacks=None, activationFlags=0, anon=False, |
1222 nextProtos=None, anon=False, | |
1223 signedCertTimestamps=None, | 1219 signedCertTimestamps=None, |
1224 fallbackSCSV=False, | 1220 fallbackSCSV=False, |
1225 ocspResponse=None | 1221 ocspResponse=None |
1226 ): | 1222 ): |
1227 """Start a server handshake operation on the TLS connection. | 1223 """Start a server handshake operation on the TLS connection. |
1228 | 1224 |
1229 This function returns a generator which behaves similarly to | 1225 This function returns a generator which behaves similarly to |
1230 handshakeServer(). Successive invocations of the generator | 1226 handshakeServer(). Successive invocations of the generator |
1231 will return 0 if it is waiting to read from the socket, 1 if it is | 1227 will return 0 if it is waiting to read from the socket, 1 if it is |
1232 waiting to write to the socket, or it will raise StopIteration | 1228 waiting to write to the socket, or it will raise StopIteration |
1233 if the handshake operation is complete. | 1229 if the handshake operation is complete. |
1234 | 1230 |
1235 @rtype: iterable | 1231 @rtype: iterable |
1236 @return: A generator; see above for details. | 1232 @return: A generator; see above for details. |
1237 """ | 1233 """ |
1238 handshaker = self._handshakeServerAsyncHelper(\ | 1234 handshaker = self._handshakeServerAsyncHelper(\ |
1239 verifierDB=verifierDB, certChain=certChain, | 1235 verifierDB=verifierDB, certChain=certChain, |
1240 privateKey=privateKey, reqCert=reqCert, | 1236 privateKey=privateKey, reqCert=reqCert, |
1241 sessionCache=sessionCache, settings=settings, | 1237 sessionCache=sessionCache, settings=settings, |
1242 reqCAs=reqCAs, reqCertTypes=reqCertTypes, | 1238 reqCAs=reqCAs, reqCertTypes=reqCertTypes, |
1243 tacks=tacks, activationFlags=activationFlags, | 1239 tacks=tacks, activationFlags=activationFlags, anon=anon, |
1244 nextProtos=nextProtos, anon=anon, | |
1245 signedCertTimestamps=signedCertTimestamps, | 1240 signedCertTimestamps=signedCertTimestamps, |
1246 fallbackSCSV=fallbackSCSV, | 1241 fallbackSCSV=fallbackSCSV, |
1247 ocspResponse=ocspResponse) | 1242 ocspResponse=ocspResponse) |
1248 for result in self._handshakeWrapperAsync(handshaker, checker): | 1243 for result in self._handshakeWrapperAsync(handshaker, checker): |
1249 yield result | 1244 yield result |
1250 if settings and settings.alertAfterHandshake: | 1245 if settings and settings.alertAfterHandshake: |
1251 for result in self._sendError(AlertDescription.internal_error, | 1246 for result in self._sendError(AlertDescription.internal_error, |
1252 "Spurious alert"): | 1247 "Spurious alert"): |
1253 yield result | 1248 yield result |
1254 | 1249 |
1255 | 1250 |
1256 def _handshakeServerAsyncHelper(self, verifierDB, | 1251 def _handshakeServerAsyncHelper(self, verifierDB, |
1257 certChain, privateKey, reqCert, sessionCache, | 1252 certChain, privateKey, reqCert, sessionCache, |
1258 settings, reqCAs, reqCertTypes, | 1253 settings, reqCAs, reqCertTypes, |
1259 tacks, activationFlags, | 1254 tacks, activationFlags, anon, |
1260 nextProtos, anon, | |
1261 signedCertTimestamps, fallbackSCSV, | 1255 signedCertTimestamps, fallbackSCSV, |
1262 ocspResponse): | 1256 ocspResponse): |
1263 | 1257 |
1264 self._handshakeStart(client=False) | 1258 self._handshakeStart(client=False) |
1265 | 1259 |
1266 if (not verifierDB) and (not certChain) and not anon: | 1260 if (not verifierDB) and (not certChain) and not anon: |
1267 raise ValueError("Caller passed no authentication credentials") | 1261 raise ValueError("Caller passed no authentication credentials") |
1268 if certChain and not privateKey: | 1262 if certChain and not privateKey: |
1269 raise ValueError("Caller passed a certChain but no privateKey") | 1263 raise ValueError("Caller passed a certChain but no privateKey") |
1270 if privateKey and not certChain: | 1264 if privateKey and not certChain: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1307 # Save the ClientHello for external code to query. | 1301 # Save the ClientHello for external code to query. |
1308 self.clientHello = clientHello | 1302 self.clientHello = clientHello |
1309 | 1303 |
1310 #If not a resumption... | 1304 #If not a resumption... |
1311 | 1305 |
1312 # Create the ServerHello message | 1306 # Create the ServerHello message |
1313 if sessionCache: | 1307 if sessionCache: |
1314 sessionID = getRandomBytes(32) | 1308 sessionID = getRandomBytes(32) |
1315 else: | 1309 else: |
1316 sessionID = bytearray(0) | 1310 sessionID = bytearray(0) |
1317 | 1311 |
1312 alpn_proto_selected = None | |
1313 if clientHello.alpn_protos_advertised is not None: | |
1314 if settings.alpnProtos is not None: | |
1315 for proto in settings.alpnProtos: | |
1316 if proto in clientHello.alpn_protos_advertised: | |
1317 alpn_proto_selected = proto | |
1318 settings.nextProtos = None | |
1319 break; | |
1320 | |
1318 if not clientHello.supports_npn: | 1321 if not clientHello.supports_npn: |
1319 nextProtos = None | 1322 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.
| |
1320 | 1323 |
1321 # If not doing a certificate-based suite, discard the TACK | 1324 # If not doing a certificate-based suite, discard the TACK |
1322 if not cipherSuite in CipherSuite.certAllSuites: | 1325 if not cipherSuite in CipherSuite.certAllSuites: |
1323 tacks = None | 1326 tacks = None |
1324 | 1327 |
1325 # Prepare a TACK Extension if requested | 1328 # Prepare a TACK Extension if requested |
1326 if clientHello.tack: | 1329 if clientHello.tack: |
1327 tackExt = TackExtension.create(tacks, activationFlags) | 1330 tackExt = TackExtension.create(tacks, activationFlags) |
1328 else: | 1331 else: |
1329 tackExt = None | 1332 tackExt = None |
1330 serverHello = ServerHello() | 1333 serverHello = ServerHello() |
1331 serverHello.create(self.version, getRandomBytes(32), sessionID, \ | 1334 serverHello.create(self.version, getRandomBytes(32), sessionID, \ |
1332 cipherSuite, CertificateType.x509, tackExt, | 1335 cipherSuite, CertificateType.x509, tackExt, |
1333 nextProtos) | 1336 alpn_proto_selected, settings.nextProtos) |
1334 serverHello.channel_id = \ | 1337 serverHello.channel_id = \ |
1335 clientHello.channel_id and settings.enableChannelID | 1338 clientHello.channel_id and settings.enableChannelID |
1336 serverHello.extended_master_secret = \ | 1339 serverHello.extended_master_secret = \ |
1337 clientHello.extended_master_secret and \ | 1340 clientHello.extended_master_secret and \ |
1338 settings.enableExtendedMasterSecret | 1341 settings.enableExtendedMasterSecret |
1339 for param in clientHello.tb_client_params: | 1342 for param in clientHello.tb_client_params: |
1340 if param in settings.supportedTokenBindingParams: | 1343 if param in settings.supportedTokenBindingParams: |
1341 serverHello.tb_params = param | 1344 serverHello.tb_params = param |
1342 break | 1345 break |
1343 if clientHello.support_signed_cert_timestamps: | 1346 if clientHello.support_signed_cert_timestamps: |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1390 else: break | 1393 else: break |
1391 premasterSecret = result | 1394 premasterSecret = result |
1392 | 1395 |
1393 else: | 1396 else: |
1394 assert(False) | 1397 assert(False) |
1395 | 1398 |
1396 # Exchange Finished messages | 1399 # Exchange Finished messages |
1397 for result in self._serverFinished(premasterSecret, | 1400 for result in self._serverFinished(premasterSecret, |
1398 clientHello.random, serverHello.random, | 1401 clientHello.random, serverHello.random, |
1399 cipherSuite, settings.cipherImplementations, | 1402 cipherSuite, settings.cipherImplementations, |
1400 nextProtos, serverHello.channel_id, | 1403 settings.nextProtos, serverHello.channel_id, |
1401 serverHello.extended_master_secret): | 1404 serverHello.extended_master_secret): |
1402 if result in (0,1): yield result | 1405 if result in (0,1): yield result |
1403 else: break | 1406 else: break |
1404 masterSecret = result | 1407 masterSecret = result |
1405 | 1408 |
1406 self.clientRandom = clientHello.random | 1409 self.clientRandom = clientHello.random |
1407 self.serverRandom = serverHello.random | 1410 self.serverRandom = serverHello.random |
1408 | 1411 |
1409 #Create the session object | 1412 #Create the session object |
1410 self.session = Session() | 1413 self.session = Session() |
1411 if cipherSuite in CipherSuite.certAllSuites: | 1414 if cipherSuite in CipherSuite.certAllSuites: |
1412 serverCertChain = certChain | 1415 serverCertChain = certChain |
1413 else: | 1416 else: |
1414 serverCertChain = None | 1417 serverCertChain = None |
1415 srpUsername = None | 1418 srpUsername = None |
1416 serverName = None | 1419 serverName = None |
1417 if clientHello.srp_username: | 1420 if clientHello.srp_username: |
1418 srpUsername = clientHello.srp_username.decode("utf-8") | 1421 srpUsername = clientHello.srp_username.decode("utf-8") |
1419 if clientHello.server_name: | 1422 if clientHello.server_name: |
1420 serverName = clientHello.server_name.decode("utf-8") | 1423 serverName = clientHello.server_name.decode("utf-8") |
1421 self.session.create(masterSecret, serverHello.session_id, cipherSuite, | 1424 self.session.create(masterSecret, serverHello.session_id, cipherSuite, |
1422 srpUsername, clientCertChain, serverCertChain, | 1425 srpUsername, clientCertChain, serverCertChain, |
1423 tackExt, serverHello.tackExt!=None, serverName) | 1426 tackExt, serverHello.tackExt!=None, alpn_proto_selected, serverName) |
1424 | 1427 |
1425 #Add the session object to the session cache | 1428 #Add the session object to the session cache |
1426 if sessionCache and sessionID: | 1429 if sessionCache and sessionID: |
1427 sessionCache[sessionID] = self.session | 1430 sessionCache[sessionID] = self.session |
1428 | 1431 |
1429 self._handshakeDone(resumed=False) | 1432 self._handshakeDone(resumed=False) |
1430 | 1433 |
1431 | 1434 |
1432 def _serverGetClientHello(self, settings, certChain, verifierDB, | 1435 def _serverGetClientHello(self, settings, certChain, verifierDB, |
1433 sessionCache, anon, fallbackSCSV): | 1436 sessionCache, anon, fallbackSCSV): |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1533 yield result | 1536 yield result |
1534 except KeyError: | 1537 except KeyError: |
1535 pass | 1538 pass |
1536 | 1539 |
1537 #If a session is found.. | 1540 #If a session is found.. |
1538 if session: | 1541 if session: |
1539 #Send ServerHello | 1542 #Send ServerHello |
1540 serverHello = ServerHello() | 1543 serverHello = ServerHello() |
1541 serverHello.create(self.version, getRandomBytes(32), | 1544 serverHello.create(self.version, getRandomBytes(32), |
1542 session.sessionID, session.cipherSuite, | 1545 session.sessionID, session.cipherSuite, |
1543 CertificateType.x509, None, None) | 1546 CertificateType.x509, None, |
1547 session.alpn_proto_selected, None) | |
1544 serverHello.extended_master_secret = \ | 1548 serverHello.extended_master_secret = \ |
1545 clientHello.extended_master_secret and \ | 1549 clientHello.extended_master_secret and \ |
1546 settings.enableExtendedMasterSecret | 1550 settings.enableExtendedMasterSecret |
1547 for param in clientHello.tb_client_params: | 1551 for param in clientHello.tb_client_params: |
1548 if param in settings.supportedTokenBindingParams: | 1552 if param in settings.supportedTokenBindingParams: |
1549 serverHello.tb_params = param | 1553 serverHello.tb_params = param |
1550 break | 1554 break |
1551 for result in self._sendMsg(serverHello): | 1555 for result in self._sendMsg(serverHello): |
1552 yield result | 1556 yield result |
1553 | 1557 |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2039 seed += bytearray(2) | 2043 seed += bytearray(2) |
2040 seed[len(seed) - 2] = len(context) >> 8 | 2044 seed[len(seed) - 2] = len(context) >> 8 |
2041 seed[len(seed) - 1] = len(context) & 0xFF | 2045 seed[len(seed) - 1] = len(context) & 0xFF |
2042 seed += context | 2046 seed += context |
2043 if self.version in ((3,1), (3,2)): | 2047 if self.version in ((3,1), (3,2)): |
2044 return PRF(self.session.masterSecret, label, seed, length) | 2048 return PRF(self.session.masterSecret, label, seed, length) |
2045 elif self.version == (3,3): | 2049 elif self.version == (3,3): |
2046 return PRF_1_2(self.session.masterSecret, label, seed, length) | 2050 return PRF_1_2(self.session.masterSecret, label, seed, length) |
2047 else: | 2051 else: |
2048 raise AssertionError() | 2052 raise AssertionError() |
OLD | NEW |