diff options
Diffstat (limited to 'third_party/tlslite/patches/status_request.patch')
-rw-r--r-- | third_party/tlslite/patches/status_request.patch | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/third_party/tlslite/patches/status_request.patch b/third_party/tlslite/patches/status_request.patch new file mode 100644 index 0000000..15f01d4 --- /dev/null +++ b/third_party/tlslite/patches/status_request.patch @@ -0,0 +1,208 @@ +diff --git a/third_party/tlslite/tlslite/TLSConnection.py b/third_party/tlslite/tlslite/TLSConnection.py +index e6ce187..94ee5eb 100644 +--- a/third_party/tlslite/tlslite/TLSConnection.py ++++ b/third_party/tlslite/tlslite/TLSConnection.py +@@ -937,8 +937,8 @@ class TLSConnection(TLSRecordLayer): + certChain=None, privateKey=None, reqCert=False, + sessionCache=None, settings=None, checker=None, + reqCAs=None, tlsIntolerant=0, +- signedCertTimestamps=None, +- fallbackSCSV=False): ++ signedCertTimestamps=None, fallbackSCSV=False, ++ ocspResponse=None): + """Perform a handshake in the role of server. + + This function performs an SSL or TLS handshake. Depending on +@@ -1014,6 +1014,16 @@ class TLSConnection(TLSRecordLayer): + binary 8-bit string) that will be sent as a TLS extension whenever + the client announces support for the extension. + ++ @type ocspResponse: str ++ @param ocspResponse: An OCSP response (as a binary 8-bit string) that ++ will be sent stapled in the handshake whenever the client announces ++ support for the status_request extension. ++ Note that the response is sent independent of the ClientHello ++ status_request extension contents, and is thus only meant for testing ++ environments. Real OCSP stapling is more complicated as it requires ++ choosing a suitable response based on the ClientHello status_request ++ extension contents. ++ + @raise socket.error: If a socket error occurs. + @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed + without a preceding alert. +@@ -1024,7 +1034,7 @@ class TLSConnection(TLSRecordLayer): + for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, + certChain, privateKey, reqCert, sessionCache, settings, + checker, reqCAs, tlsIntolerant, signedCertTimestamps, +- fallbackSCSV): ++ fallbackSCSV, ocspResponse): + pass + + +@@ -1033,7 +1043,7 @@ class TLSConnection(TLSRecordLayer): + sessionCache=None, settings=None, checker=None, + reqCAs=None, tlsIntolerant=0, + signedCertTimestamps=None, +- fallbackSCSV=False): ++ fallbackSCSV=False, ocspResponse=None): + """Start a server handshake operation on the TLS connection. + + This function returns a generator which behaves similarly to +@@ -1053,7 +1063,8 @@ class TLSConnection(TLSRecordLayer): + reqCAs=reqCAs, + tlsIntolerant=tlsIntolerant, + signedCertTimestamps=signedCertTimestamps, +- fallbackSCSV=fallbackSCSV) ++ fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse) ++ + for result in self._handshakeWrapperAsync(handshaker, checker): + yield result + +@@ -1062,7 +1073,7 @@ class TLSConnection(TLSRecordLayer): + certChain, privateKey, reqCert, + sessionCache, settings, reqCAs, + tlsIntolerant, signedCertTimestamps, +- fallbackSCSV): ++ fallbackSCSV, ocspResponse): + + self._handshakeStart(client=False) + +@@ -1439,10 +1450,14 @@ class TLSConnection(TLSRecordLayer): + sessionID, cipherSuite, certificateType) + serverHello.channel_id = clientHello.channel_id + if clientHello.support_signed_cert_timestamps: +- serverHello.signed_cert_timestamps = signedCertTimestamps ++ serverHello.signed_cert_timestamps = signedCertTimestamps ++ serverHello.status_request = (clientHello.status_request and ++ ocspResponse) + doingChannelID = clientHello.channel_id + msgs.append(serverHello) + msgs.append(Certificate(certificateType).create(serverCertChain)) ++ if serverHello.status_request: ++ msgs.append(CertificateStatus().create(ocspResponse)) + if reqCert and reqCAs: + msgs.append(CertificateRequest().create([], reqCAs)) + elif reqCert: +diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py +index 23e3dcb..d027ef5 100644 +--- a/third_party/tlslite/tlslite/constants.py ++++ b/third_party/tlslite/tlslite/constants.py +@@ -22,6 +22,7 @@ class HandshakeType: + certificate_verify = 15 + client_key_exchange = 16 + finished = 20 ++ certificate_status = 22 + encrypted_extensions = 203 + + class ContentType: +@@ -31,7 +32,11 @@ class ContentType: + application_data = 23 + all = (20,21,22,23) + ++class CertificateStatusType: ++ ocsp = 1 ++ + class ExtensionType: ++ status_request = 5 # OCSP stapling + signed_cert_timestamps = 18 # signed_certificate_timestamp in RFC 6962 + channel_id = 30031 + +diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py +index 296f422..497ef60 100644 +--- a/third_party/tlslite/tlslite/messages.py ++++ b/third_party/tlslite/tlslite/messages.py +@@ -132,6 +132,7 @@ class ClientHello(HandshakeMsg): + self.srp_username = None # a string + self.channel_id = False + self.support_signed_cert_timestamps = False ++ self.status_request = False + + def create(self, version, random, session_id, cipher_suites, + certificate_types=None, srp_username=None): +@@ -182,6 +183,19 @@ class ClientHello(HandshakeMsg): + if extLength: + raise SyntaxError() + self.support_signed_cert_timestamps = True ++ elif extType == ExtensionType.status_request: ++ # Extension contents are currently ignored. ++ # According to RFC 6066, this is not strictly forbidden ++ # (although it is suboptimal): ++ # Servers that receive a client hello containing the ++ # "status_request" extension MAY return a suitable ++ # certificate status response to the client along with ++ # their certificate. If OCSP is requested, they ++ # SHOULD use the information contained in the extension ++ # when selecting an OCSP responder and SHOULD include ++ # request_extensions in the OCSP request. ++ p.getFixBytes(extLength) ++ self.status_request = True + else: + p.getFixBytes(extLength) + soFar += 4 + extLength +@@ -230,6 +244,7 @@ class ServerHello(HandshakeMsg): + self.compression_method = 0 + self.channel_id = False + self.signed_cert_timestamps = None ++ self.status_request = False + + def create(self, version, random, session_id, cipher_suite, + certificate_type): +@@ -282,6 +297,9 @@ class ServerHello(HandshakeMsg): + if self.signed_cert_timestamps: + extLength += 4 + len(self.signed_cert_timestamps) + ++ if self.status_request: ++ extLength += 4 ++ + if extLength != 0: + w.add(extLength, 2) + +@@ -299,6 +317,10 @@ class ServerHello(HandshakeMsg): + w.add(ExtensionType.signed_cert_timestamps, 2) + w.addVarSeq(stringToBytes(self.signed_cert_timestamps), 1, 2) + ++ if self.status_request: ++ w.add(ExtensionType.status_request, 2) ++ w.add(0, 2) ++ + return HandshakeMsg.postWrite(self, w, trial) + + class Certificate(HandshakeMsg): +@@ -367,6 +389,37 @@ class Certificate(HandshakeMsg): + raise AssertionError() + return HandshakeMsg.postWrite(self, w, trial) + ++class CertificateStatus(HandshakeMsg): ++ def __init__(self): ++ self.contentType = ContentType.handshake ++ ++ def create(self, ocsp_response): ++ self.ocsp_response = ocsp_response ++ return self ++ ++ # Defined for the sake of completeness, even though we currently only ++ # support sending the status message (server-side), not requesting ++ # or receiving it (client-side). ++ def parse(self, p): ++ p.startLengthCheck(3) ++ status_type = p.get(1) ++ # Only one type is specified, so hardwire it. ++ if status_type != CertificateStatusType.ocsp: ++ raise SyntaxError() ++ ocsp_response = p.getVarBytes(3) ++ if not ocsp_response: ++ # Can't be empty ++ raise SyntaxError() ++ self.ocsp_response = ocsp_response ++ return self ++ ++ def write(self, trial=False): ++ w = HandshakeMsg.preWrite(self, HandshakeType.certificate_status, ++ trial) ++ w.add(CertificateStatusType.ocsp, 1) ++ w.addVarSeq(stringToBytes(self.ocsp_response), 1, 3) ++ return HandshakeMsg.postWrite(self, w, trial) ++ + class CertificateRequest(HandshakeMsg): + def __init__(self): + self.contentType = ContentType.handshake |