PageRenderTime 94ms CodeModel.GetById 12ms app.highlight 72ms RepoModel.GetById 2ms app.codeStats 0ms

/gdata/tlslite/TLSConnection.py

http://radioappz.googlecode.com/
Python | 1487 lines | 1233 code | 120 blank | 134 comment | 244 complexity | 488f8801392a6ecc58a9c48c0afcc63c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1"""
   2MAIN CLASS FOR TLS LITE (START HERE!).
   3"""
   4from __future__ import generators
   5
   6import socket
   7from utils.compat import formatExceptionTrace
   8from TLSRecordLayer import TLSRecordLayer
   9from Session import Session
  10from constants import *
  11from utils.cryptomath import getRandomBytes
  12from errors import *
  13from messages import *
  14from mathtls import *
  15from HandshakeSettings import HandshakeSettings
  16
  17
  18class TLSConnection(TLSRecordLayer):
  19    """
  20    This class wraps a socket and provides TLS handshaking and data
  21    transfer.
  22
  23    To use this class, create a new instance, passing a connected
  24    socket into the constructor.  Then call some handshake function.
  25    If the handshake completes without raising an exception, then a TLS
  26    connection has been negotiated.  You can transfer data over this
  27    connection as if it were a socket.
  28
  29    This class provides both synchronous and asynchronous versions of
  30    its key functions.  The synchronous versions should be used when
  31    writing single-or multi-threaded code using blocking sockets.  The
  32    asynchronous versions should be used when performing asynchronous,
  33    event-based I/O with non-blocking sockets.
  34
  35    Asynchronous I/O is a complicated subject; typically, you should
  36    not use the asynchronous functions directly, but should use some
  37    framework like asyncore or Twisted which TLS Lite integrates with
  38    (see
  39    L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or
  40    L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}).
  41    """
  42
  43
  44    def __init__(self, sock):
  45        """Create a new TLSConnection instance.
  46
  47        @param sock: The socket data will be transmitted on.  The
  48        socket should already be connected.  It may be in blocking or
  49        non-blocking mode.
  50
  51        @type sock: L{socket.socket}
  52        """
  53        TLSRecordLayer.__init__(self, sock)
  54
  55    def handshakeClientSRP(self, username, password, session=None,
  56                           settings=None, checker=None, async=False):
  57        """Perform an SRP handshake in the role of client.
  58
  59        This function performs a TLS/SRP handshake.  SRP mutually
  60        authenticates both parties to each other using only a
  61        username and password.  This function may also perform a
  62        combined SRP and server-certificate handshake, if the server
  63        chooses to authenticate itself with a certificate chain in
  64        addition to doing SRP.
  65
  66        TLS/SRP is non-standard.  Most TLS implementations don't
  67        support it.  See
  68        U{http://www.ietf.org/html.charters/tls-charter.html} or
  69        U{http://trevp.net/tlssrp/} for the latest information on
  70        TLS/SRP.
  71
  72        Like any handshake function, this can be called on a closed
  73        TLS connection, or on a TLS connection that is already open.
  74        If called on an open connection it performs a re-handshake.
  75
  76        If the function completes without raising an exception, the
  77        TLS connection will be open and available for data transfer.
  78
  79        If an exception is raised, the connection will have been
  80        automatically closed (if it was ever open).
  81
  82        @type username: str
  83        @param username: The SRP username.
  84
  85        @type password: str
  86        @param password: The SRP password.
  87
  88        @type session: L{tlslite.Session.Session}
  89        @param session: A TLS session to attempt to resume.  This
  90        session must be an SRP session performed with the same username
  91        and password as were passed in.  If the resumption does not
  92        succeed, a full SRP handshake will be performed.
  93
  94        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
  95        @param settings: Various settings which can be used to control
  96        the ciphersuites, certificate types, and SSL/TLS versions
  97        offered by the client.
  98
  99        @type checker: L{tlslite.Checker.Checker}
 100        @param checker: A Checker instance.  This instance will be
 101        invoked to examine the other party's authentication
 102        credentials, if the handshake completes succesfully.
 103
 104        @type async: bool
 105        @param async: If False, this function will block until the
 106        handshake is completed.  If True, this function will return a
 107        generator.  Successive invocations of the generator will
 108        return 0 if it is waiting to read from the socket, 1 if it is
 109        waiting to write to the socket, or will raise StopIteration if
 110        the handshake operation is completed.
 111
 112        @rtype: None or an iterable
 113        @return: If 'async' is True, a generator object will be
 114        returned.
 115
 116        @raise socket.error: If a socket error occurs.
 117        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
 118        without a preceding alert.
 119        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
 120        @raise tlslite.errors.TLSAuthenticationError: If the checker
 121        doesn't like the other party's authentication credentials.
 122        """
 123        handshaker = self._handshakeClientAsync(srpParams=(username, password),
 124                        session=session, settings=settings, checker=checker)
 125        if async:
 126            return handshaker
 127        for result in handshaker:
 128            pass
 129
 130    def handshakeClientCert(self, certChain=None, privateKey=None,
 131                            session=None, settings=None, checker=None,
 132                            async=False):
 133        """Perform a certificate-based handshake in the role of client.
 134
 135        This function performs an SSL or TLS handshake.  The server
 136        will authenticate itself using an X.509 or cryptoID certificate
 137        chain.  If the handshake succeeds, the server's certificate
 138        chain will be stored in the session's serverCertChain attribute.
 139        Unless a checker object is passed in, this function does no
 140        validation or checking of the server's certificate chain.
 141
 142        If the server requests client authentication, the
 143        client will send the passed-in certificate chain, and use the
 144        passed-in private key to authenticate itself.  If no
 145        certificate chain and private key were passed in, the client
 146        will attempt to proceed without client authentication.  The
 147        server may or may not allow this.
 148
 149        Like any handshake function, this can be called on a closed
 150        TLS connection, or on a TLS connection that is already open.
 151        If called on an open connection it performs a re-handshake.
 152
 153        If the function completes without raising an exception, the
 154        TLS connection will be open and available for data transfer.
 155
 156        If an exception is raised, the connection will have been
 157        automatically closed (if it was ever open).
 158
 159        @type certChain: L{tlslite.X509CertChain.X509CertChain} or
 160        L{cryptoIDlib.CertChain.CertChain}
 161        @param certChain: The certificate chain to be used if the
 162        server requests client authentication.
 163
 164        @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
 165        @param privateKey: The private key to be used if the server
 166        requests client authentication.
 167
 168        @type session: L{tlslite.Session.Session}
 169        @param session: A TLS session to attempt to resume.  If the
 170        resumption does not succeed, a full handshake will be
 171        performed.
 172
 173        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
 174        @param settings: Various settings which can be used to control
 175        the ciphersuites, certificate types, and SSL/TLS versions
 176        offered by the client.
 177
 178        @type checker: L{tlslite.Checker.Checker}
 179        @param checker: A Checker instance.  This instance will be
 180        invoked to examine the other party's authentication
 181        credentials, if the handshake completes succesfully.
 182
 183        @type async: bool
 184        @param async: If False, this function will block until the
 185        handshake is completed.  If True, this function will return a
 186        generator.  Successive invocations of the generator will
 187        return 0 if it is waiting to read from the socket, 1 if it is
 188        waiting to write to the socket, or will raise StopIteration if
 189        the handshake operation is completed.
 190
 191        @rtype: None or an iterable
 192        @return: If 'async' is True, a generator object will be
 193        returned.
 194
 195        @raise socket.error: If a socket error occurs.
 196        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
 197        without a preceding alert.
 198        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
 199        @raise tlslite.errors.TLSAuthenticationError: If the checker
 200        doesn't like the other party's authentication credentials.
 201        """
 202        handshaker = self._handshakeClientAsync(certParams=(certChain,
 203                        privateKey), session=session, settings=settings,
 204                        checker=checker)
 205        if async:
 206            return handshaker
 207        for result in handshaker:
 208            pass
 209
 210    def handshakeClientUnknown(self, srpCallback=None, certCallback=None,
 211                               session=None, settings=None, checker=None,
 212                               async=False):
 213        """Perform a to-be-determined type of handshake in the role of client.
 214
 215        This function performs an SSL or TLS handshake.  If the server
 216        requests client certificate authentication, the
 217        certCallback will be invoked and should return a (certChain,
 218        privateKey) pair.  If the callback returns None, the library
 219        will attempt to proceed without client authentication.  The
 220        server may or may not allow this.
 221
 222        If the server requests SRP authentication, the srpCallback
 223        will be invoked and should return a (username, password) pair.
 224        If the callback returns None, the local implementation will
 225        signal a user_canceled error alert.
 226
 227        After the handshake completes, the client can inspect the
 228        connection's session attribute to determine what type of
 229        authentication was performed.
 230
 231        Like any handshake function, this can be called on a closed
 232        TLS connection, or on a TLS connection that is already open.
 233        If called on an open connection it performs a re-handshake.
 234
 235        If the function completes without raising an exception, the
 236        TLS connection will be open and available for data transfer.
 237
 238        If an exception is raised, the connection will have been
 239        automatically closed (if it was ever open).
 240
 241        @type srpCallback: callable
 242        @param srpCallback: The callback to be used if the server
 243        requests SRP authentication.  If None, the client will not
 244        offer support for SRP ciphersuites.
 245
 246        @type certCallback: callable
 247        @param certCallback: The callback to be used if the server
 248        requests client certificate authentication.
 249
 250        @type session: L{tlslite.Session.Session}
 251        @param session: A TLS session to attempt to resume.  If the
 252        resumption does not succeed, a full handshake will be
 253        performed.
 254
 255        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
 256        @param settings: Various settings which can be used to control
 257        the ciphersuites, certificate types, and SSL/TLS versions
 258        offered by the client.
 259
 260        @type checker: L{tlslite.Checker.Checker}
 261        @param checker: A Checker instance.  This instance will be
 262        invoked to examine the other party's authentication
 263        credentials, if the handshake completes succesfully.
 264
 265        @type async: bool
 266        @param async: If False, this function will block until the
 267        handshake is completed.  If True, this function will return a
 268        generator.  Successive invocations of the generator will
 269        return 0 if it is waiting to read from the socket, 1 if it is
 270        waiting to write to the socket, or will raise StopIteration if
 271        the handshake operation is completed.
 272
 273        @rtype: None or an iterable
 274        @return: If 'async' is True, a generator object will be
 275        returned.
 276
 277        @raise socket.error: If a socket error occurs.
 278        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
 279        without a preceding alert.
 280        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
 281        @raise tlslite.errors.TLSAuthenticationError: If the checker
 282        doesn't like the other party's authentication credentials.
 283        """
 284        handshaker = self._handshakeClientAsync(unknownParams=(srpCallback,
 285                        certCallback), session=session, settings=settings,
 286                        checker=checker)
 287        if async:
 288            return handshaker
 289        for result in handshaker:
 290            pass
 291
 292    def handshakeClientSharedKey(self, username, sharedKey, settings=None,
 293                                 checker=None, async=False):
 294        """Perform a shared-key handshake in the role of client.
 295
 296        This function performs a shared-key handshake.  Using shared
 297        symmetric keys of high entropy (128 bits or greater) mutually
 298        authenticates both parties to each other.
 299
 300        TLS with shared-keys is non-standard.  Most TLS
 301        implementations don't support it.  See
 302        U{http://www.ietf.org/html.charters/tls-charter.html} for the
 303        latest information on TLS with shared-keys.  If the shared-keys
 304        Internet-Draft changes or is superceded, TLS Lite will track
 305        those changes, so the shared-key support in later versions of
 306        TLS Lite may become incompatible with this version.
 307
 308        Like any handshake function, this can be called on a closed
 309        TLS connection, or on a TLS connection that is already open.
 310        If called on an open connection it performs a re-handshake.
 311
 312        If the function completes without raising an exception, the
 313        TLS connection will be open and available for data transfer.
 314
 315        If an exception is raised, the connection will have been
 316        automatically closed (if it was ever open).
 317
 318        @type username: str
 319        @param username: The shared-key username.
 320
 321        @type sharedKey: str
 322        @param sharedKey: The shared key.
 323
 324        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
 325        @param settings: Various settings which can be used to control
 326        the ciphersuites, certificate types, and SSL/TLS versions
 327        offered by the client.
 328
 329        @type checker: L{tlslite.Checker.Checker}
 330        @param checker: A Checker instance.  This instance will be
 331        invoked to examine the other party's authentication
 332        credentials, if the handshake completes succesfully.
 333
 334        @type async: bool
 335        @param async: If False, this function will block until the
 336        handshake is completed.  If True, this function will return a
 337        generator.  Successive invocations of the generator will
 338        return 0 if it is waiting to read from the socket, 1 if it is
 339        waiting to write to the socket, or will raise StopIteration if
 340        the handshake operation is completed.
 341
 342        @rtype: None or an iterable
 343        @return: If 'async' is True, a generator object will be
 344        returned.
 345
 346        @raise socket.error: If a socket error occurs.
 347        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
 348        without a preceding alert.
 349        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
 350        @raise tlslite.errors.TLSAuthenticationError: If the checker
 351        doesn't like the other party's authentication credentials.
 352        """
 353        handshaker = self._handshakeClientAsync(sharedKeyParams=(username,
 354                        sharedKey), settings=settings, checker=checker)
 355        if async:
 356            return handshaker
 357        for result in handshaker:
 358            pass
 359
 360    def _handshakeClientAsync(self, srpParams=(), certParams=(),
 361                             unknownParams=(), sharedKeyParams=(),
 362                             session=None, settings=None, checker=None,
 363                             recursive=False):
 364
 365        handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
 366                certParams=certParams, unknownParams=unknownParams,
 367                sharedKeyParams=sharedKeyParams, session=session,
 368                settings=settings, recursive=recursive)
 369        for result in self._handshakeWrapperAsync(handshaker, checker):
 370            yield result
 371
 372
 373    def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams,
 374                               sharedKeyParams, session, settings, recursive):
 375        if not recursive:
 376            self._handshakeStart(client=True)
 377
 378        #Unpack parameters
 379        srpUsername = None      # srpParams
 380        password = None         # srpParams
 381        clientCertChain = None  # certParams
 382        privateKey = None       # certParams
 383        srpCallback = None      # unknownParams
 384        certCallback = None     # unknownParams
 385        #session                # sharedKeyParams (or session)
 386        #settings               # settings
 387
 388        if srpParams:
 389            srpUsername, password = srpParams
 390        elif certParams:
 391            clientCertChain, privateKey = certParams
 392        elif unknownParams:
 393            srpCallback, certCallback = unknownParams
 394        elif sharedKeyParams:
 395            session = Session()._createSharedKey(*sharedKeyParams)
 396
 397        if not settings:
 398            settings = HandshakeSettings()
 399        settings = settings._filter()
 400
 401        #Validate parameters
 402        if srpUsername and not password:
 403            raise ValueError("Caller passed a username but no password")
 404        if password and not srpUsername:
 405            raise ValueError("Caller passed a password but no username")
 406
 407        if clientCertChain and not privateKey:
 408            raise ValueError("Caller passed a certChain but no privateKey")
 409        if privateKey and not clientCertChain:
 410            raise ValueError("Caller passed a privateKey but no certChain")
 411
 412        if clientCertChain:
 413            foundType = False
 414            try:
 415                import cryptoIDlib.CertChain
 416                if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain):
 417                    if "cryptoID" not in settings.certificateTypes:
 418                        raise ValueError("Client certificate doesn't "\
 419                                         "match Handshake Settings")
 420                    settings.certificateTypes = ["cryptoID"]
 421                    foundType = True
 422            except ImportError:
 423                pass
 424            if not foundType and isinstance(clientCertChain,
 425                                            X509CertChain):
 426                if "x509" not in settings.certificateTypes:
 427                    raise ValueError("Client certificate doesn't match "\
 428                                     "Handshake Settings")
 429                settings.certificateTypes = ["x509"]
 430                foundType = True
 431            if not foundType:
 432                raise ValueError("Unrecognized certificate type")
 433
 434
 435        if session:
 436            if not session.valid():
 437                session = None #ignore non-resumable sessions...
 438            elif session.resumable and \
 439                    (session.srpUsername != srpUsername):
 440                raise ValueError("Session username doesn't match")
 441
 442        #Add Faults to parameters
 443        if srpUsername and self.fault == Fault.badUsername:
 444            srpUsername += "GARBAGE"
 445        if password and self.fault == Fault.badPassword:
 446            password += "GARBAGE"
 447        if sharedKeyParams:
 448            identifier = sharedKeyParams[0]
 449            sharedKey = sharedKeyParams[1]
 450            if self.fault == Fault.badIdentifier:
 451                identifier += "GARBAGE"
 452                session = Session()._createSharedKey(identifier, sharedKey)
 453            elif self.fault == Fault.badSharedKey:
 454                sharedKey += "GARBAGE"
 455                session = Session()._createSharedKey(identifier, sharedKey)
 456
 457
 458        #Initialize locals
 459        serverCertChain = None
 460        cipherSuite = 0
 461        certificateType = CertificateType.x509
 462        premasterSecret = None
 463
 464        #Get client nonce
 465        clientRandom = getRandomBytes(32)
 466
 467        #Initialize acceptable ciphersuites
 468        cipherSuites = []
 469        if srpParams:
 470            cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
 471            cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
 472        elif certParams:
 473            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
 474        elif unknownParams:
 475            if srpCallback:
 476                cipherSuites += \
 477                    CipherSuite.getSrpRsaSuites(settings.cipherNames)
 478                cipherSuites += \
 479                    CipherSuite.getSrpSuites(settings.cipherNames)
 480            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
 481        elif sharedKeyParams:
 482            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
 483        else:
 484            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
 485
 486        #Initialize acceptable certificate types
 487        certificateTypes = settings._getCertificateTypes()
 488
 489        #Tentatively set the version to the client's minimum version.
 490        #We'll use this for the ClientHello, and if an error occurs
 491        #parsing the Server Hello, we'll use this version for the response
 492        self.version = settings.maxVersion
 493
 494        #Either send ClientHello (with a resumable session)...
 495        if session:
 496            #If it's a resumable (i.e. not a shared-key session), then its
 497            #ciphersuite must be one of the acceptable ciphersuites
 498            if (not sharedKeyParams) and \
 499                session.cipherSuite not in cipherSuites:
 500                raise ValueError("Session's cipher suite not consistent "\
 501                                 "with parameters")
 502            else:
 503                clientHello = ClientHello()
 504                clientHello.create(settings.maxVersion, clientRandom,
 505                                   session.sessionID, cipherSuites,
 506                                   certificateTypes, session.srpUsername)
 507
 508        #Or send ClientHello (without)
 509        else:
 510            clientHello = ClientHello()
 511            clientHello.create(settings.maxVersion, clientRandom,
 512                               createByteArraySequence([]), cipherSuites,
 513                               certificateTypes, srpUsername)
 514        for result in self._sendMsg(clientHello):
 515            yield result
 516
 517        #Get ServerHello (or missing_srp_username)
 518        for result in self._getMsg((ContentType.handshake,
 519                                  ContentType.alert),
 520                                  HandshakeType.server_hello):
 521            if result in (0,1):
 522                yield result
 523            else:
 524                break
 525        msg = result
 526
 527        if isinstance(msg, ServerHello):
 528            serverHello = msg
 529        elif isinstance(msg, Alert):
 530            alert = msg
 531
 532            #If it's not a missing_srp_username, re-raise
 533            if alert.description != AlertDescription.missing_srp_username:
 534                self._shutdown(False)
 535                raise TLSRemoteAlert(alert)
 536
 537            #If we're not in SRP callback mode, we won't have offered SRP
 538            #without a username, so we shouldn't get this alert
 539            if not srpCallback:
 540                for result in self._sendError(\
 541                                AlertDescription.unexpected_message):
 542                    yield result
 543            srpParams = srpCallback()
 544            #If the callback returns None, cancel the handshake
 545            if srpParams == None:
 546                for result in self._sendError(AlertDescription.user_canceled):
 547                    yield result
 548
 549            #Recursively perform handshake
 550            for result in self._handshakeClientAsyncHelper(srpParams,
 551                            None, None, None, None, settings, True):
 552                yield result
 553            return
 554
 555        #Get the server version.  Do this before anything else, so any
 556        #error alerts will use the server's version
 557        self.version = serverHello.server_version
 558
 559        #Future responses from server must use this version
 560        self._versionCheck = True
 561
 562        #Check ServerHello
 563        if serverHello.server_version < settings.minVersion:
 564            for result in self._sendError(\
 565                AlertDescription.protocol_version,
 566                "Too old version: %s" % str(serverHello.server_version)):
 567                yield result
 568        if serverHello.server_version > settings.maxVersion:
 569            for result in self._sendError(\
 570                AlertDescription.protocol_version,
 571                "Too new version: %s" % str(serverHello.server_version)):
 572                yield result
 573        if serverHello.cipher_suite not in cipherSuites:
 574            for result in self._sendError(\
 575                AlertDescription.illegal_parameter,
 576                "Server responded with incorrect ciphersuite"):
 577                yield result
 578        if serverHello.certificate_type not in certificateTypes:
 579            for result in self._sendError(\
 580                AlertDescription.illegal_parameter,
 581                "Server responded with incorrect certificate type"):
 582                yield result
 583        if serverHello.compression_method != 0:
 584            for result in self._sendError(\
 585                AlertDescription.illegal_parameter,
 586                "Server responded with incorrect compression method"):
 587                yield result
 588
 589        #Get the server nonce
 590        serverRandom = serverHello.random
 591
 592        #If the server agrees to resume
 593        if session and session.sessionID and \
 594                       serverHello.session_id == session.sessionID:
 595
 596            #If a shared-key, we're flexible about suites; otherwise the
 597            #server-chosen suite has to match the session's suite
 598            if sharedKeyParams:
 599                session.cipherSuite = serverHello.cipher_suite
 600            elif serverHello.cipher_suite != session.cipherSuite:
 601                for result in self._sendError(\
 602                    AlertDescription.illegal_parameter,\
 603                    "Server's ciphersuite doesn't match session"):
 604                    yield result
 605
 606            #Set the session for this connection
 607            self.session = session
 608
 609            #Calculate pending connection states
 610            self._calcPendingStates(clientRandom, serverRandom,
 611                                   settings.cipherImplementations)
 612
 613            #Exchange ChangeCipherSpec and Finished messages
 614            for result in self._getFinished():
 615                yield result
 616            for result in self._sendFinished():
 617                yield result
 618
 619            #Mark the connection as open
 620            self._handshakeDone(resumed=True)
 621
 622        #If server DOES NOT agree to resume
 623        else:
 624
 625            if sharedKeyParams:
 626                for result in self._sendError(\
 627                        AlertDescription.user_canceled,
 628                        "Was expecting a shared-key resumption"):
 629                    yield result
 630
 631            #We've already validated these
 632            cipherSuite = serverHello.cipher_suite
 633            certificateType = serverHello.certificate_type
 634
 635            #If the server chose an SRP suite...
 636            if cipherSuite in CipherSuite.srpSuites:
 637                #Get ServerKeyExchange, ServerHelloDone
 638                for result in self._getMsg(ContentType.handshake,
 639                        HandshakeType.server_key_exchange, cipherSuite):
 640                    if result in (0,1):
 641                        yield result
 642                    else:
 643                        break
 644                serverKeyExchange = result
 645
 646                for result in self._getMsg(ContentType.handshake,
 647                        HandshakeType.server_hello_done):
 648                    if result in (0,1):
 649                        yield result
 650                    else:
 651                        break
 652                serverHelloDone = result
 653
 654            #If the server chose an SRP+RSA suite...
 655            elif cipherSuite in CipherSuite.srpRsaSuites:
 656                #Get Certificate, ServerKeyExchange, ServerHelloDone
 657                for result in self._getMsg(ContentType.handshake,
 658                        HandshakeType.certificate, certificateType):
 659                    if result in (0,1):
 660                        yield result
 661                    else:
 662                        break
 663                serverCertificate = result
 664
 665                for result in self._getMsg(ContentType.handshake,
 666                        HandshakeType.server_key_exchange, cipherSuite):
 667                    if result in (0,1):
 668                        yield result
 669                    else:
 670                        break
 671                serverKeyExchange = result
 672
 673                for result in self._getMsg(ContentType.handshake,
 674                        HandshakeType.server_hello_done):
 675                    if result in (0,1):
 676                        yield result
 677                    else:
 678                        break
 679                serverHelloDone = result
 680
 681            #If the server chose an RSA suite...
 682            elif cipherSuite in CipherSuite.rsaSuites:
 683                #Get Certificate[, CertificateRequest], ServerHelloDone
 684                for result in self._getMsg(ContentType.handshake,
 685                        HandshakeType.certificate, certificateType):
 686                    if result in (0,1):
 687                        yield result
 688                    else:
 689                        break
 690                serverCertificate = result
 691
 692                for result in self._getMsg(ContentType.handshake,
 693                        (HandshakeType.server_hello_done,
 694                        HandshakeType.certificate_request)):
 695                    if result in (0,1):
 696                        yield result
 697                    else:
 698                        break
 699                msg = result
 700
 701                certificateRequest = None
 702                if isinstance(msg, CertificateRequest):
 703                    certificateRequest = msg
 704                    for result in self._getMsg(ContentType.handshake,
 705                            HandshakeType.server_hello_done):
 706                        if result in (0,1):
 707                            yield result
 708                        else:
 709                            break
 710                    serverHelloDone = result
 711                elif isinstance(msg, ServerHelloDone):
 712                    serverHelloDone = msg
 713            else:
 714                raise AssertionError()
 715
 716
 717            #Calculate SRP premaster secret, if server chose an SRP or
 718            #SRP+RSA suite
 719            if cipherSuite in CipherSuite.srpSuites + \
 720                              CipherSuite.srpRsaSuites:
 721                #Get and check the server's group parameters and B value
 722                N = serverKeyExchange.srp_N
 723                g = serverKeyExchange.srp_g
 724                s = serverKeyExchange.srp_s
 725                B = serverKeyExchange.srp_B
 726
 727                if (g,N) not in goodGroupParameters:
 728                    for result in self._sendError(\
 729                            AlertDescription.untrusted_srp_parameters,
 730                            "Unknown group parameters"):
 731                        yield result
 732                if numBits(N) < settings.minKeySize:
 733                    for result in self._sendError(\
 734                            AlertDescription.untrusted_srp_parameters,
 735                            "N value is too small: %d" % numBits(N)):
 736                        yield result
 737                if numBits(N) > settings.maxKeySize:
 738                    for result in self._sendError(\
 739                            AlertDescription.untrusted_srp_parameters,
 740                            "N value is too large: %d" % numBits(N)):
 741                        yield result
 742                if B % N == 0:
 743                    for result in self._sendError(\
 744                            AlertDescription.illegal_parameter,
 745                            "Suspicious B value"):
 746                        yield result
 747
 748                #Check the server's signature, if server chose an
 749                #SRP+RSA suite
 750                if cipherSuite in CipherSuite.srpRsaSuites:
 751                    #Hash ServerKeyExchange/ServerSRPParams
 752                    hashBytes = serverKeyExchange.hash(clientRandom,
 753                                                       serverRandom)
 754
 755                    #Extract signature bytes from ServerKeyExchange
 756                    sigBytes = serverKeyExchange.signature
 757                    if len(sigBytes) == 0:
 758                        for result in self._sendError(\
 759                                AlertDescription.illegal_parameter,
 760                                "Server sent an SRP ServerKeyExchange "\
 761                                "message without a signature"):
 762                            yield result
 763
 764                    #Get server's public key from the Certificate message
 765                    for result in self._getKeyFromChain(serverCertificate,
 766                                                       settings):
 767                        if result in (0,1):
 768                            yield result
 769                        else:
 770                            break
 771                    publicKey, serverCertChain = result
 772
 773                    #Verify signature
 774                    if not publicKey.verify(sigBytes, hashBytes):
 775                        for result in self._sendError(\
 776                                AlertDescription.decrypt_error,
 777                                "Signature failed to verify"):
 778                            yield result
 779
 780
 781                #Calculate client's ephemeral DH values (a, A)
 782                a = bytesToNumber(getRandomBytes(32))
 783                A = powMod(g, a, N)
 784
 785                #Calculate client's static DH values (x, v)
 786                x = makeX(bytesToString(s), srpUsername, password)
 787                v = powMod(g, x, N)
 788
 789                #Calculate u
 790                u = makeU(N, A, B)
 791
 792                #Calculate premaster secret
 793                k = makeK(N, g)
 794                S = powMod((B - (k*v)) % N, a+(u*x), N)
 795
 796                if self.fault == Fault.badA:
 797                    A = N
 798                    S = 0
 799                premasterSecret = numberToBytes(S)
 800
 801                #Send ClientKeyExchange
 802                for result in self._sendMsg(\
 803                        ClientKeyExchange(cipherSuite).createSRP(A)):
 804                    yield result
 805
 806
 807            #Calculate RSA premaster secret, if server chose an RSA suite
 808            elif cipherSuite in CipherSuite.rsaSuites:
 809
 810                #Handle the presence of a CertificateRequest
 811                if certificateRequest:
 812                    if unknownParams and certCallback:
 813                        certParamsNew = certCallback()
 814                        if certParamsNew:
 815                            clientCertChain, privateKey = certParamsNew
 816
 817                #Get server's public key from the Certificate message
 818                for result in self._getKeyFromChain(serverCertificate,
 819                                                   settings):
 820                    if result in (0,1):
 821                        yield result
 822                    else:
 823                        break
 824                publicKey, serverCertChain = result
 825
 826
 827                #Calculate premaster secret
 828                premasterSecret = getRandomBytes(48)
 829                premasterSecret[0] = settings.maxVersion[0]
 830                premasterSecret[1] = settings.maxVersion[1]
 831
 832                if self.fault == Fault.badPremasterPadding:
 833                    premasterSecret[0] = 5
 834                if self.fault == Fault.shortPremasterSecret:
 835                    premasterSecret = premasterSecret[:-1]
 836
 837                #Encrypt premaster secret to server's public key
 838                encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
 839
 840                #If client authentication was requested, send Certificate
 841                #message, either with certificates or empty
 842                if certificateRequest:
 843                    clientCertificate = Certificate(certificateType)
 844
 845                    if clientCertChain:
 846                        #Check to make sure we have the same type of
 847                        #certificates the server requested
 848                        wrongType = False
 849                        if certificateType == CertificateType.x509:
 850                            if not isinstance(clientCertChain, X509CertChain):
 851                                wrongType = True
 852                        elif certificateType == CertificateType.cryptoID:
 853                            if not isinstance(clientCertChain,
 854                                              cryptoIDlib.CertChain.CertChain):
 855                                wrongType = True
 856                        if wrongType:
 857                            for result in self._sendError(\
 858                                    AlertDescription.handshake_failure,
 859                                    "Client certificate is of wrong type"):
 860                                yield result
 861
 862                        clientCertificate.create(clientCertChain)
 863
 864                    for result in self._sendMsg(clientCertificate):
 865                        yield result
 866                else:
 867                    #The server didn't request client auth, so we
 868                    #zeroize these so the clientCertChain won't be
 869                    #stored in the session.
 870                    privateKey = None
 871                    clientCertChain = None
 872
 873                #Send ClientKeyExchange
 874                clientKeyExchange = ClientKeyExchange(cipherSuite,
 875                                                      self.version)
 876                clientKeyExchange.createRSA(encryptedPreMasterSecret)
 877                for result in self._sendMsg(clientKeyExchange):
 878                    yield result
 879
 880                #If client authentication was requested and we have a
 881                #private key, send CertificateVerify
 882                if certificateRequest and privateKey:
 883                    if self.version == (3,0):
 884                        #Create a temporary session object, just for the
 885                        #purpose of creating the CertificateVerify
 886                        session = Session()
 887                        session._calcMasterSecret(self.version,
 888                                                 premasterSecret,
 889                                                 clientRandom,
 890                                                 serverRandom)
 891                        verifyBytes = self._calcSSLHandshakeHash(\
 892                                          session.masterSecret, "")
 893                    elif self.version in ((3,1), (3,2)):
 894                        verifyBytes = stringToBytes(\
 895                            self._handshake_md5.digest() + \
 896                            self._handshake_sha.digest())
 897                    if self.fault == Fault.badVerifyMessage:
 898                        verifyBytes[0] = ((verifyBytes[0]+1) % 256)
 899                    signedBytes = privateKey.sign(verifyBytes)
 900                    certificateVerify = CertificateVerify()
 901                    certificateVerify.create(signedBytes)
 902                    for result in self._sendMsg(certificateVerify):
 903                        yield result
 904
 905
 906            #Create the session object
 907            self.session = Session()
 908            self.session._calcMasterSecret(self.version, premasterSecret,
 909                                          clientRandom, serverRandom)
 910            self.session.sessionID = serverHello.session_id
 911            self.session.cipherSuite = cipherSuite
 912            self.session.srpUsername = srpUsername
 913            self.session.clientCertChain = clientCertChain
 914            self.session.serverCertChain = serverCertChain
 915
 916            #Calculate pending connection states
 917            self._calcPendingStates(clientRandom, serverRandom,
 918                                   settings.cipherImplementations)
 919
 920            #Exchange ChangeCipherSpec and Finished messages
 921            for result in self._sendFinished():
 922                yield result
 923            for result in self._getFinished():
 924                yield result
 925
 926            #Mark the connection as open
 927            self.session._setResumable(True)
 928            self._handshakeDone(resumed=False)
 929
 930
 931
 932    def handshakeServer(self, sharedKeyDB=None, verifierDB=None,
 933                        certChain=None, privateKey=None, reqCert=False,
 934                        sessionCache=None, settings=None, checker=None):
 935        """Perform a handshake in the role of server.
 936
 937        This function performs an SSL or TLS handshake.  Depending on
 938        the arguments and the behavior of the client, this function can
 939        perform a shared-key, SRP, or certificate-based handshake.  It
 940        can also perform a combined SRP and server-certificate
 941        handshake.
 942
 943        Like any handshake function, this can be called on a closed
 944        TLS connection, or on a TLS connection that is already open.
 945        If called on an open connection it performs a re-handshake.
 946        This function does not send a Hello Request message before
 947        performing the handshake, so if re-handshaking is required,
 948        the server must signal the client to begin the re-handshake
 949        through some other means.
 950
 951        If the function completes without raising an exception, the
 952        TLS connection will be open and available for data transfer.
 953
 954        If an exception is raised, the connection will have been
 955        automatically closed (if it was ever open).
 956
 957        @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
 958        @param sharedKeyDB: A database of shared symmetric keys
 959        associated with usernames.  If the client performs a
 960        shared-key handshake, the session's sharedKeyUsername
 961        attribute will be set.
 962
 963        @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
 964        @param verifierDB: A database of SRP password verifiers
 965        associated with usernames.  If the client performs an SRP
 966        handshake, the session's srpUsername attribute will be set.
 967
 968        @type certChain: L{tlslite.X509CertChain.X509CertChain} or
 969        L{cryptoIDlib.CertChain.CertChain}
 970        @param certChain: The certificate chain to be used if the
 971        client requests server certificate authentication.
 972
 973        @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
 974        @param privateKey: The private key to be used if the client
 975        requests server certificate authentication.
 976
 977        @type reqCert: bool
 978        @param reqCert: Whether to request client certificate
 979        authentication.  This only applies if the client chooses server
 980        certificate authentication; if the client chooses SRP or
 981        shared-key authentication, this will be ignored.  If the client
 982        performs a client certificate authentication, the sessions's
 983        clientCertChain attribute will be set.
 984
 985        @type sessionCache: L{tlslite.SessionCache.SessionCache}
 986        @param sessionCache: An in-memory cache of resumable sessions.
 987        The client can resume sessions from this cache.  Alternatively,
 988        if the client performs a full handshake, a new session will be
 989        added to the cache.
 990
 991        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
 992        @param settings: Various settings which can be used to control
 993        the ciphersuites and SSL/TLS version chosen by the server.
 994
 995        @type checker: L{tlslite.Checker.Checker}
 996        @param checker: A Checker instance.  This instance will be
 997        invoked to examine the other party's authentication
 998        credentials, if the handshake completes succesfully.
 999
1000        @raise socket.error: If a socket error occurs.
1001        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1002        without a preceding alert.
1003        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1004        @raise tlslite.errors.TLSAuthenticationError: If the checker
1005        doesn't like the other party's authentication credentials.
1006        """
1007        for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
1008                certChain, privateKey, reqCert, sessionCache, settings,
1009                checker):
1010            pass
1011
1012
1013    def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None,
1014                             certChain=None, privateKey=None, reqCert=False,
1015                             sessionCache=None, settings=None, checker=None):
1016        """Start a server handshake operation on the TLS connection.
1017
1018        This function returns a generator which behaves similarly to
1019        handshakeServer().  Successive invocations of the generator
1020        will return 0 if it is waiting to read from the socket, 1 if it is
1021        waiting to write to the socket, or it will raise StopIteration
1022        if the handshake operation is complete.
1023
1024        @rtype: iterable
1025        @return: A generator; see above for details.
1026        """
1027        handshaker = self._handshakeServerAsyncHelper(\
1028            sharedKeyDB=sharedKeyDB,
1029            verifierDB=verifierDB, certChain=certChain,
1030            privateKey=privateKey, reqCert=reqCert,
1031            sessionCache=sessionCache, settings=settings)
1032        for result in self._handshakeWrapperAsync(handshaker, checker):
1033            yield result
1034
1035
1036    def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB,
1037                             certChain, privateKey, reqCert, sessionCache,
1038                             settings):
1039
1040        self._handshakeStart(client=False)
1041
1042        if (not sharedKeyDB) and (not verifierDB) and (not certChain):
1043            raise ValueError("Caller passed no authentication credentials")
1044        if certChain and not privateKey:
1045            raise ValueError("Caller passed a certChain but no privateKey")
1046        if privateKey and not certChain:
1047            raise ValueError("Caller passed a privateKey but no certChain")
1048
1049        if not settings:
1050            settings = HandshakeSettings()
1051        settings = settings._filter()
1052
1053        #Initialize acceptable cipher suites
1054        cipherSuites = []
1055        if verifierDB:
1056            if certChain:
1057                cipherSuites += \
1058                    CipherSuite.getSrpRsaSuites(settings.cipherNames)
1059            cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
1060        if sharedKeyDB or certChain:
1061            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
1062
1063        #Initialize acceptable certificate type
1064        certificateType = None
1065        if certChain:
1066            try:
1067                import cryptoIDlib.CertChain
1068                if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
1069                    certificateType = CertificateType.cryptoID
1070            except ImportError:
1071                pass
1072            if isinstance(certChain, X509CertChain):
1073                certificateType = CertificateType.x509
1074            if certificateType == None:
1075                raise ValueError("Unrecognized certificate type")
1076
1077        #Initialize locals
1078        clientCertChain = None
1079        serverCertChain = None #We may set certChain to this later
1080        postFinishedError = None
1081
1082        #Tentatively set version to most-desirable version, so if an error
1083        #occurs parsing the ClientHello, this is what we'll use for the
1084        #error alert
1085        self.version = settings.maxVersion
1086
1087        #Get ClientHello
1088        for result in self._getMsg(ContentType.handshake,
1089                                   HandshakeType.client_hello):
1090            if result in (0,1):
1091                yield result
1092            else:
1093                break
1094        clientHello = result
1095
1096        #If client's version is too low, reject it
1097        if clientHello.client_version < settings.minVersion:
1098            self.version = settings.minVersion
1099            for result in self._sendError(\
1100                  AlertDescription.protocol_version,
1101                  "Too old version: %s" % str(clientHello.client_version)):
1102                yield result
1103
1104        #If client's version is too high, propose my highest version
1105        elif clientHello.client_version > settings.maxVersion:
1106            self.version = settings.maxVersion
1107
1108        else:
1109            #Set the version to the client's version
1110            self.version = clientHello.client_version
1111
1112        #Get the client nonce; create server nonce
1113        clientRandom = clientHello.random
1114        serverRandom = getRandomBytes(32)
1115
1116        #Calculate the first cipher suite intersection.
1117        #This is the 'privileged' ciphersuite.  We'll use it if we're
1118        #doing a shared-key resumption or a new negotiation.  In fact,
1119        #the only time we won't use it is if we're resuming a non-sharedkey
1120        #session, in which case we use the ciphersuite from the session.
1121        #
1122        #Given the current ciphersuite ordering, this means we prefer SRP
1123        #over non-SRP.
1124        for cipherSuite in cipherSuites:
1125            if cipherSuite in clientHello.cipher_suites:
1126                break
1127        else:
1128            for result in self._sendError(\
1129                    AlertDescription.handshake_failure):
1130                yield result
1131
1132        #If resumption was requested...
1133        if clientHello.session_id and (sharedKeyDB or sessionCache):
1134            session = None
1135
1136            #Check in the sharedKeys container
1137            if sharedKeyDB and len(clientHello.session_id)==16:
1138                try:
1139                    #Trim off zero padding, if any
1140                    for x in range(16):
1141     

Large files files are truncated, but you can click here to view the full file