OLD | NEW |
| (Empty) |
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/tlsl
ite/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/tlsli
te/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 | |
OLD | NEW |