OLD | NEW |
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 | 1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlsl
ite/constants.py |
87 index 23e3dcb..d027ef5 100644 | 2 index d132b78..ceaa903 100755 |
88 --- a/third_party/tlslite/tlslite/constants.py | 3 --- a/third_party/tlslite/tlslite/constants.py |
89 +++ b/third_party/tlslite/tlslite/constants.py | 4 +++ b/third_party/tlslite/tlslite/constants.py |
90 @@ -22,6 +22,7 @@ class HandshakeType: | 5 @@ -30,6 +30,7 @@ class HandshakeType: |
91 certificate_verify = 15 | 6 certificate_verify = 15 |
92 client_key_exchange = 16 | 7 client_key_exchange = 16 |
93 finished = 20 | 8 finished = 20 |
94 + certificate_status = 22 | 9 + certificate_status = 22 |
| 10 next_protocol = 67 |
95 encrypted_extensions = 203 | 11 encrypted_extensions = 203 |
96 | 12 |
97 class ContentType: | 13 @@ -40,8 +41,12 @@ class ContentType: |
98 @@ -31,7 +32,11 @@ class ContentType: | |
99 application_data = 23 | 14 application_data = 23 |
100 all = (20,21,22,23) | 15 all = (20,21,22,23) |
101 | 16 |
102 +class CertificateStatusType: | 17 +class CertificateStatusType: |
103 + ocsp = 1 | 18 + ocsp = 1 |
104 + | 19 + |
105 class ExtensionType: | 20 class ExtensionType: # RFC 6066 / 4366 |
106 + status_request = 5 # OCSP stapling | 21 server_name = 0 # RFC 6066 / 4366 |
107 signed_cert_timestamps = 18 # signed_certificate_timestamp in RFC 6962 | 22 + status_request = 5 # RFC 6066 / 4366 |
108 channel_id = 30031 | 23 srp = 12 # RFC 5054 |
109 | 24 cert_type = 9 # RFC 6091 |
| 25 signed_cert_timestamps = 18 # RFC 6962 |
110 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlsli
te/messages.py | 26 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlsli
te/messages.py |
111 index 296f422..497ef60 100644 | 27 index 5a2cd6c..532d86b 100755 |
112 --- a/third_party/tlslite/tlslite/messages.py | 28 --- a/third_party/tlslite/tlslite/messages.py |
113 +++ b/third_party/tlslite/tlslite/messages.py | 29 +++ b/third_party/tlslite/tlslite/messages.py |
114 @@ -132,6 +132,7 @@ class ClientHello(HandshakeMsg): | 30 @@ -114,6 +114,7 @@ class ClientHello(HandshakeMsg): |
115 self.srp_username = None # a string | 31 self.server_name = bytearray(0) |
116 self.channel_id = False | 32 self.channel_id = False |
117 self.support_signed_cert_timestamps = False | 33 self.support_signed_cert_timestamps = False |
118 + self.status_request = False | 34 + self.status_request = False |
119 | 35 |
120 def create(self, version, random, session_id, cipher_suites, | 36 def create(self, version, random, session_id, cipher_suites, |
121 certificate_types=None, srp_username=None): | 37 certificate_types=None, srpUsername=None, |
122 @@ -182,6 +183,19 @@ class ClientHello(HandshakeMsg): | 38 @@ -187,6 +188,19 @@ class ClientHello(HandshakeMsg): |
123 if extLength: | 39 if extLength: |
124 raise SyntaxError() | 40 raise SyntaxError() |
125 self.support_signed_cert_timestamps = True | 41 self.support_signed_cert_timestamps = True |
126 + elif extType == ExtensionType.status_request: | 42 + elif extType == ExtensionType.status_request: |
127 + # Extension contents are currently ignored. | 43 + # Extension contents are currently ignored. |
128 + # According to RFC 6066, this is not strictly forbidden | 44 + # According to RFC 6066, this is not strictly forbidden |
129 + # (although it is suboptimal): | 45 + # (although it is suboptimal): |
130 + # Servers that receive a client hello containing the | 46 + # Servers that receive a client hello containing the |
131 + # "status_request" extension MAY return a suitable | 47 + # "status_request" extension MAY return a suitable |
132 + # certificate status response to the client along with | 48 + # certificate status response to the client along with |
133 + # their certificate. If OCSP is requested, they | 49 + # their certificate. If OCSP is requested, they |
134 + # SHOULD use the information contained in the extension | 50 + # SHOULD use the information contained in the extension |
135 + # when selecting an OCSP responder and SHOULD include | 51 + # when selecting an OCSP responder and SHOULD include |
136 + # request_extensions in the OCSP request. | 52 + # request_extensions in the OCSP request. |
137 + p.getFixBytes(extLength) | 53 + p.getFixBytes(extLength) |
138 + self.status_request = True | 54 + self.status_request = True |
139 else: | 55 else: |
140 p.getFixBytes(extLength) | 56 _ = p.getFixBytes(extLength) |
141 soFar += 4 + extLength | 57 index2 = p.index |
142 @@ -230,6 +244,7 @@ class ServerHello(HandshakeMsg): | 58 @@ -253,6 +267,7 @@ class ServerHello(HandshakeMsg): |
143 self.compression_method = 0 | 59 self.next_protos = None |
144 self.channel_id = False | 60 self.channel_id = False |
145 self.signed_cert_timestamps = None | 61 self.signed_cert_timestamps = None |
146 + self.status_request = False | 62 + self.status_request = False |
147 | 63 |
148 def create(self, version, random, session_id, cipher_suite, | 64 def create(self, version, random, session_id, cipher_suite, |
149 certificate_type): | 65 certificate_type, tackExt, next_protos_advertised): |
150 @@ -282,6 +297,9 @@ class ServerHello(HandshakeMsg): | 66 @@ -345,6 +360,9 @@ class ServerHello(HandshakeMsg): |
151 if self.signed_cert_timestamps: | 67 if self.signed_cert_timestamps: |
152 extLength += 4 + len(self.signed_cert_timestamps) | 68 w2.add(ExtensionType.signed_cert_timestamps, 2) |
153 | 69 w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2) |
154 + if self.status_request: | 70 + if self.status_request: |
155 + extLength += 4 | 71 + w2.add(ExtensionType.status_request, 2) |
156 + | 72 + w2.add(0, 2) |
157 if extLength != 0: | 73 if len(w2.bytes): |
158 w.add(extLength, 2) | 74 w.add(len(w2.bytes), 2) |
159 | 75 w.bytes += w2.bytes |
160 @@ -299,6 +317,10 @@ class ServerHello(HandshakeMsg): | 76 @@ -402,6 +420,37 @@ class Certificate(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() | 77 raise AssertionError() |
173 return HandshakeMsg.postWrite(self, w, trial) | 78 return self.postWrite(w) |
174 | 79 |
175 +class CertificateStatus(HandshakeMsg): | 80 +class CertificateStatus(HandshakeMsg): |
176 + def __init__(self): | 81 + def __init__(self): |
177 + self.contentType = ContentType.handshake | 82 + HandshakeMsg.__init__(self, HandshakeType.certificate_status) |
178 + | 83 + |
179 + def create(self, ocsp_response): | 84 + def create(self, ocsp_response): |
180 + self.ocsp_response = ocsp_response | 85 + self.ocsp_response = ocsp_response |
181 + return self | 86 + return self |
182 + | 87 + |
183 + # Defined for the sake of completeness, even though we currently only | 88 + # Defined for the sake of completeness, even though we currently only |
184 + # support sending the status message (server-side), not requesting | 89 + # support sending the status message (server-side), not requesting |
185 + # or receiving it (client-side). | 90 + # or receiving it (client-side). |
186 + def parse(self, p): | 91 + def parse(self, p): |
187 + p.startLengthCheck(3) | 92 + p.startLengthCheck(3) |
188 + status_type = p.get(1) | 93 + status_type = p.get(1) |
189 + # Only one type is specified, so hardwire it. | 94 + # Only one type is specified, so hardwire it. |
190 + if status_type != CertificateStatusType.ocsp: | 95 + if status_type != CertificateStatusType.ocsp: |
191 + raise SyntaxError() | 96 + raise SyntaxError() |
192 + ocsp_response = p.getVarBytes(3) | 97 + ocsp_response = p.getVarBytes(3) |
193 + if not ocsp_response: | 98 + if not ocsp_response: |
194 + # Can't be empty | 99 + # Can't be empty |
195 + raise SyntaxError() | 100 + raise SyntaxError() |
196 + self.ocsp_response = ocsp_response | 101 + self.ocsp_response = ocsp_response |
| 102 + p.stopLengthCheck() |
197 + return self | 103 + return self |
198 + | 104 + |
199 + def write(self, trial=False): | 105 + def write(self): |
200 + w = HandshakeMsg.preWrite(self, HandshakeType.certificate_status, | 106 + w = Writer() |
201 + trial) | |
202 + w.add(CertificateStatusType.ocsp, 1) | 107 + w.add(CertificateStatusType.ocsp, 1) |
203 + w.addVarSeq(stringToBytes(self.ocsp_response), 1, 3) | 108 + w.addVarSeq(bytearray(self.ocsp_response), 1, 3) |
204 + return HandshakeMsg.postWrite(self, w, trial) | 109 + return self.postWrite(w) |
205 + | 110 + |
206 class CertificateRequest(HandshakeMsg): | 111 class CertificateRequest(HandshakeMsg): |
207 def __init__(self): | 112 def __init__(self): |
208 self.contentType = ContentType.handshake | 113 HandshakeMsg.__init__(self, HandshakeType.certificate_request) |
| 114 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/
tlslite/tlsconnection.py |
| 115 index bd92161..b9797d2 100755 |
| 116 --- a/third_party/tlslite/tlslite/tlsconnection.py |
| 117 +++ b/third_party/tlslite/tlslite/tlsconnection.py |
| 118 @@ -967,7 +967,7 @@ class TLSConnection(TLSRecordLayer): |
| 119 tacks=None, activationFlags=0, |
| 120 nextProtos=None, anon=False, |
| 121 tlsIntolerant=None, signedCertTimestamps=None, |
| 122 - fallbackSCSV=False): |
| 123 + fallbackSCSV=False, ocspResponse=None): |
| 124 """Perform a handshake in the role of server. |
| 125 |
| 126 This function performs an SSL or TLS handshake. Depending on |
| 127 @@ -1051,6 +1051,16 @@ class TLSConnection(TLSRecordLayer): |
| 128 TLS_FALLBACK_SCSV and thus reject connections using less than the |
| 129 server's maximum TLS version that include this cipher suite. |
| 130 |
| 131 + @type ocspResponse: str |
| 132 + @param ocspResponse: An OCSP response (as a binary 8-bit string) that |
| 133 + will be sent stapled in the handshake whenever the client announces |
| 134 + support for the status_request extension. |
| 135 + Note that the response is sent independent of the ClientHello |
| 136 + status_request extension contents, and is thus only meant for testing |
| 137 + environments. Real OCSP stapling is more complicated as it requires |
| 138 + choosing a suitable response based on the ClientHello status_request |
| 139 + extension contents. |
| 140 + |
| 141 @raise socket.error: If a socket error occurs. |
| 142 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed |
| 143 without a preceding alert. |
| 144 @@ -1064,7 +1074,7 @@ class TLSConnection(TLSRecordLayer): |
| 145 tacks=tacks, activationFlags=activationFlags, |
| 146 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, |
| 147 signedCertTimestamps=signedCertTimestamps, |
| 148 - fallbackSCSV=fallbackSCSV): |
| 149 + fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): |
| 150 pass |
| 151 |
| 152 |
| 153 @@ -1076,7 +1086,8 @@ class TLSConnection(TLSRecordLayer): |
| 154 nextProtos=None, anon=False, |
| 155 tlsIntolerant=None, |
| 156 signedCertTimestamps=None, |
| 157 - fallbackSCSV=False |
| 158 + fallbackSCSV=False, |
| 159 + ocspResponse=None |
| 160 ): |
| 161 """Start a server handshake operation on the TLS connection. |
| 162 |
| 163 @@ -1098,7 +1109,8 @@ class TLSConnection(TLSRecordLayer): |
| 164 nextProtos=nextProtos, anon=anon, |
| 165 tlsIntolerant=tlsIntolerant, |
| 166 signedCertTimestamps=signedCertTimestamps, |
| 167 - fallbackSCSV=fallbackSCSV) |
| 168 + fallbackSCSV=fallbackSCSV, |
| 169 + ocspResponse=ocspResponse) |
| 170 for result in self._handshakeWrapperAsync(handshaker, checker): |
| 171 yield result |
| 172 |
| 173 @@ -1108,7 +1120,8 @@ class TLSConnection(TLSRecordLayer): |
| 174 settings, reqCAs, |
| 175 tacks, activationFlags, |
| 176 nextProtos, anon, |
| 177 - tlsIntolerant, signedCertTimestamps, fallbackSCSV)
: |
| 178 + tlsIntolerant, signedCertTimestamps, fallbackSCSV, |
| 179 + ocspResponse): |
| 180 |
| 181 self._handshakeStart(client=False) |
| 182 |
| 183 @@ -1178,6 +1191,8 @@ class TLSConnection(TLSRecordLayer): |
| 184 serverHello.channel_id = clientHello.channel_id |
| 185 if clientHello.support_signed_cert_timestamps: |
| 186 serverHello.signed_cert_timestamps = signedCertTimestamps |
| 187 + if clientHello.status_request: |
| 188 + serverHello.status_request = ocspResponse |
| 189 |
| 190 # Perform the SRP key exchange |
| 191 clientCertChain = None |
| 192 @@ -1194,7 +1209,7 @@ class TLSConnection(TLSRecordLayer): |
| 193 for result in self._serverCertKeyExchange(clientHello, serverHello,
|
| 194 certChain, privateKey, |
| 195 reqCert, reqCAs, cipherSuite, |
| 196 - settings): |
| 197 + settings, ocspResponse): |
| 198 if result in (0,1): yield result |
| 199 else: break |
| 200 (premasterSecret, clientCertChain) = result |
| 201 @@ -1471,7 +1486,7 @@ class TLSConnection(TLSRecordLayer): |
| 202 def _serverCertKeyExchange(self, clientHello, serverHello, |
| 203 serverCertChain, privateKey, |
| 204 reqCert, reqCAs, cipherSuite, |
| 205 - settings): |
| 206 + settings, ocspResponse): |
| 207 #Send ServerHello, Certificate[, CertificateRequest], |
| 208 #ServerHelloDone |
| 209 msgs = [] |
| 210 @@ -1481,6 +1496,8 @@ class TLSConnection(TLSRecordLayer): |
| 211 |
| 212 msgs.append(serverHello) |
| 213 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) |
| 214 + if serverHello.status_request: |
| 215 + msgs.append(CertificateStatus().create(ocspResponse)) |
| 216 if reqCert and reqCAs: |
| 217 msgs.append(CertificateRequest().create(\ |
| 218 [ClientCertificateType.rsa_sign], reqCAs)) |
OLD | NEW |