Home | History | Annotate | Download | only in patches
      1 diff --git a/third_party/tlslite/tlslite/TLSConnection.py b/third_party/tlslite/tlslite/TLSConnection.py
      2 index e6ce187..94ee5eb 100644
      3 --- a/third_party/tlslite/tlslite/TLSConnection.py
      4 +++ b/third_party/tlslite/tlslite/TLSConnection.py
      5 @@ -937,8 +937,8 @@ class TLSConnection(TLSRecordLayer):
      6                          certChain=None, privateKey=None, reqCert=False,
      7                          sessionCache=None, settings=None, checker=None,
      8                          reqCAs=None, tlsIntolerant=0,
      9 -                        signedCertTimestamps=None,
     10 -                        fallbackSCSV=False):
     11 +                        signedCertTimestamps=None, fallbackSCSV=False,
     12 +                        ocspResponse=None):
     13          """Perform a handshake in the role of server.
     14  
     15          This function performs an SSL or TLS handshake.  Depending on
     16 @@ -1014,6 +1014,16 @@ class TLSConnection(TLSRecordLayer):
     17          binary 8-bit string) that will be sent as a TLS extension whenever
     18          the client announces support for the extension.
     19  
     20 +        @type ocspResponse: str
     21 +        @param ocspResponse: An OCSP response (as a binary 8-bit string) that
     22 +        will be sent stapled in the handshake whenever the client announces
     23 +        support for the status_request extension.
     24 +        Note that the response is sent independent of the ClientHello
     25 +        status_request extension contents, and is thus only meant for testing
     26 +        environments. Real OCSP stapling is more complicated as it requires
     27 +        choosing a suitable response based on the ClientHello status_request
     28 +        extension contents.
     29 +
     30          @raise socket.error: If a socket error occurs.
     31          @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
     32          without a preceding alert.
     33 @@ -1024,7 +1034,7 @@ class TLSConnection(TLSRecordLayer):
     34          for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
     35                  certChain, privateKey, reqCert, sessionCache, settings,
     36                  checker, reqCAs, tlsIntolerant, signedCertTimestamps,
     37 -                fallbackSCSV):
     38 +                fallbackSCSV, ocspResponse):
     39              pass
     40  
     41  
     42 @@ -1033,7 +1043,7 @@ class TLSConnection(TLSRecordLayer):
     43                               sessionCache=None, settings=None, checker=None,
     44                               reqCAs=None, tlsIntolerant=0,
     45                               signedCertTimestamps=None,
     46 -                             fallbackSCSV=False):
     47 +                             fallbackSCSV=False, ocspResponse=None):
     48          """Start a server handshake operation on the TLS connection.
     49  
     50          This function returns a generator which behaves similarly to
     51 @@ -1053,7 +1063,8 @@ class TLSConnection(TLSRecordLayer):
     52              reqCAs=reqCAs,
     53              tlsIntolerant=tlsIntolerant,
     54              signedCertTimestamps=signedCertTimestamps,
     55 -            fallbackSCSV=fallbackSCSV)
     56 +            fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse)
     57 +
     58          for result in self._handshakeWrapperAsync(handshaker, checker):
     59              yield result
     60  
     61 @@ -1062,7 +1073,7 @@ class TLSConnection(TLSRecordLayer):
     62                                      certChain, privateKey, reqCert,
     63                                      sessionCache, settings, reqCAs,
     64                                      tlsIntolerant, signedCertTimestamps,
     65 -                                    fallbackSCSV):
     66 +                                    fallbackSCSV, ocspResponse):
     67  
     68          self._handshakeStart(client=False)
     69  
     70 @@ -1439,10 +1450,14 @@ class TLSConnection(TLSRecordLayer):
     71                      sessionID, cipherSuite, certificateType)
     72              serverHello.channel_id = clientHello.channel_id
     73              if clientHello.support_signed_cert_timestamps:
     74 -                serverHello.signed_cert_timestamps = signedCertTimestamps
     75 +              serverHello.signed_cert_timestamps = signedCertTimestamps
     76 +            serverHello.status_request = (clientHello.status_request and
     77 +                                          ocspResponse)
     78              doingChannelID = clientHello.channel_id
     79              msgs.append(serverHello)
     80              msgs.append(Certificate(certificateType).create(serverCertChain))
     81 +            if serverHello.status_request:
     82 +                msgs.append(CertificateStatus().create(ocspResponse))
     83              if reqCert and reqCAs:
     84                  msgs.append(CertificateRequest().create([], reqCAs))
     85              elif reqCert:
     86 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
     87 index 23e3dcb..d027ef5 100644
     88 --- a/third_party/tlslite/tlslite/constants.py
     89 +++ b/third_party/tlslite/tlslite/constants.py
     90 @@ -22,6 +22,7 @@ class HandshakeType:
     91      certificate_verify = 15
     92      client_key_exchange = 16
     93      finished = 20
     94 +    certificate_status = 22
     95      encrypted_extensions = 203
     96  
     97  class ContentType:
     98 @@ -31,7 +32,11 @@ class ContentType:
     99      application_data = 23
    100      all = (20,21,22,23)
    101  
    102 +class CertificateStatusType:
    103 +    ocsp = 1
    104 +
    105  class ExtensionType:
    106 +    status_request = 5  # OCSP stapling
    107      signed_cert_timestamps = 18  # signed_certificate_timestamp in RFC 6962
    108      channel_id = 30031
    109  
    110 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
    111 index 296f422..497ef60 100644
    112 --- a/third_party/tlslite/tlslite/messages.py
    113 +++ b/third_party/tlslite/tlslite/messages.py
    114 @@ -132,6 +132,7 @@ class ClientHello(HandshakeMsg):
    115          self.srp_username = None        # a string
    116          self.channel_id = False
    117          self.support_signed_cert_timestamps = False
    118 +        self.status_request = False
    119  
    120      def create(self, version, random, session_id, cipher_suites,
    121                 certificate_types=None, srp_username=None):
    122 @@ -182,6 +183,19 @@ class ClientHello(HandshakeMsg):
    123                          if extLength:
    124                              raise SyntaxError()
    125                          self.support_signed_cert_timestamps = True
    126 +                    elif extType == ExtensionType.status_request:
    127 +                        # Extension contents are currently ignored.
    128 +                        # According to RFC 6066, this is not strictly forbidden
    129 +                        # (although it is suboptimal):
    130 +                        # Servers that receive a client hello containing the
    131 +                        # "status_request" extension MAY return a suitable
    132 +                        # certificate status response to the client along with
    133 +                        # their certificate.  If OCSP is requested, they
    134 +                        # SHOULD use the information contained in the extension
    135 +                        # when selecting an OCSP responder and SHOULD include
    136 +                        # request_extensions in the OCSP request.
    137 +                        p.getFixBytes(extLength)
    138 +                        self.status_request = True
    139                      else:
    140                          p.getFixBytes(extLength)
    141                      soFar += 4 + extLength
    142 @@ -230,6 +244,7 @@ class ServerHello(HandshakeMsg):
    143          self.compression_method = 0
    144          self.channel_id = False
    145          self.signed_cert_timestamps = None
    146 +        self.status_request = False
    147  
    148      def create(self, version, random, session_id, cipher_suite,
    149                 certificate_type):
    150 @@ -282,6 +297,9 @@ class ServerHello(HandshakeMsg):
    151          if self.signed_cert_timestamps:
    152              extLength += 4 + len(self.signed_cert_timestamps)
    153  
    154 +        if self.status_request:
    155 +            extLength += 4
    156 +
    157          if extLength != 0:
    158              w.add(extLength, 2)
    159  
    160 @@ -299,6 +317,10 @@ class ServerHello(HandshakeMsg):
    161              w.add(ExtensionType.signed_cert_timestamps, 2)
    162              w.addVarSeq(stringToBytes(self.signed_cert_timestamps), 1, 2)
    163  
    164 +        if self.status_request:
    165 +            w.add(ExtensionType.status_request, 2)
    166 +            w.add(0, 2)
    167 +
    168          return HandshakeMsg.postWrite(self, w, trial)
    169  
    170  class Certificate(HandshakeMsg):
    171 @@ -367,6 +389,37 @@ class Certificate(HandshakeMsg):
    172              raise AssertionError()
    173          return HandshakeMsg.postWrite(self, w, trial)
    174  
    175 +class CertificateStatus(HandshakeMsg):
    176 +    def __init__(self):
    177 +        self.contentType = ContentType.handshake
    178 +
    179 +    def create(self, ocsp_response):
    180 +        self.ocsp_response = ocsp_response
    181 +        return self
    182 +
    183 +    # Defined for the sake of completeness, even though we currently only
    184 +    # support sending the status message (server-side), not requesting
    185 +    # or receiving it (client-side).
    186 +    def parse(self, p):
    187 +        p.startLengthCheck(3)
    188 +        status_type = p.get(1)
    189 +        # Only one type is specified, so hardwire it.
    190 +        if status_type != CertificateStatusType.ocsp:
    191 +            raise SyntaxError()
    192 +        ocsp_response = p.getVarBytes(3)
    193 +        if not ocsp_response:
    194 +            # Can't be empty
    195 +            raise SyntaxError()
    196 +        self.ocsp_response = ocsp_response
    197 +        return self
    198 +
    199 +    def write(self, trial=False):
    200 +        w = HandshakeMsg.preWrite(self, HandshakeType.certificate_status,
    201 +                                  trial)
    202 +        w.add(CertificateStatusType.ocsp, 1)
    203 +        w.addVarSeq(stringToBytes(self.ocsp_response), 1, 3)
    204 +        return HandshakeMsg.postWrite(self, w, trial)
    205 +
    206  class CertificateRequest(HandshakeMsg):
    207      def __init__(self):
    208          self.contentType = ContentType.handshake
    209