Chromium Code Reviews| 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 |