blob: 36ef14a3a4a3a3a5cb3163aadf239ec4402fc4f5 [file] [log] [blame]
Abraham Martind2f0b072015-03-25 13:56:25 +00001from sys import platform
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002from functools import wraps, partial
Cory Benfieldbe3e7b82014-05-10 09:48:55 +01003from itertools import count, chain
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08004from weakref import WeakValueDictionary
5from errno import errorcode
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -08006
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05007from six import text_type as _text_type
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -08008from six import integer_types as integer_types
Cory Benfieldcd010f62014-05-15 19:00:27 +01009from six import int2byte, indexbytes
Jean-Paul Calderone63eab692014-01-18 10:19:56 -050010
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050011from OpenSSL._util import (
12 ffi as _ffi,
13 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050014 exception_from_error_queue as _exception_from_error_queue,
Jean-Paul Calderone6462b072015-03-29 07:03:11 -040015 native as _native,
Jean-Paul Calderone17eca482015-04-13 20:31:07 -040016 warn_text as _warn_text,
Jean-Paul Calderone55f9e882015-04-12 09:31:03 -040017 path_string as _path_string,
18)
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080019
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080020from OpenSSL.crypto import (
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050021 FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080022
23_unspecified = object()
24
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -050025try:
26 _memoryview = memoryview
27except NameError:
28 class _memoryview(object):
29 pass
30
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +020031try:
32 _buffer = buffer
33except NameError:
34 class _buffer(object):
35 pass
36
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050037OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
38SSLEAY_VERSION = _lib.SSLEAY_VERSION
39SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
40SSLEAY_PLATFORM = _lib.SSLEAY_PLATFORM
41SSLEAY_DIR = _lib.SSLEAY_DIR
42SSLEAY_BUILT_ON = _lib.SSLEAY_BUILT_ON
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080043
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050044SENT_SHUTDOWN = _lib.SSL_SENT_SHUTDOWN
45RECEIVED_SHUTDOWN = _lib.SSL_RECEIVED_SHUTDOWN
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080046
47SSLv2_METHOD = 1
48SSLv3_METHOD = 2
49SSLv23_METHOD = 3
50TLSv1_METHOD = 4
Jean-Paul Calderone56bff942013-11-03 11:30:43 -050051TLSv1_1_METHOD = 5
52TLSv1_2_METHOD = 6
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080053
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050054OP_NO_SSLv2 = _lib.SSL_OP_NO_SSLv2
55OP_NO_SSLv3 = _lib.SSL_OP_NO_SSLv3
56OP_NO_TLSv1 = _lib.SSL_OP_NO_TLSv1
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -050057
58OP_NO_TLSv1_1 = getattr(_lib, "SSL_OP_NO_TLSv1_1", 0)
59OP_NO_TLSv1_2 = getattr(_lib, "SSL_OP_NO_TLSv1_2", 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080060
Jean-Paul Calderone0d7e8a12014-01-08 16:54:13 -050061try:
62 MODE_RELEASE_BUFFERS = _lib.SSL_MODE_RELEASE_BUFFERS
63except AttributeError:
64 pass
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080065
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050066OP_SINGLE_DH_USE = _lib.SSL_OP_SINGLE_DH_USE
67OP_EPHEMERAL_RSA = _lib.SSL_OP_EPHEMERAL_RSA
68OP_MICROSOFT_SESS_ID_BUG = _lib.SSL_OP_MICROSOFT_SESS_ID_BUG
69OP_NETSCAPE_CHALLENGE_BUG = _lib.SSL_OP_NETSCAPE_CHALLENGE_BUG
70OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = _lib.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
71OP_SSLREF2_REUSE_CERT_TYPE_BUG = _lib.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
72OP_MICROSOFT_BIG_SSLV3_BUFFER = _lib.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
Jean-Paul Calderone0d7e8a12014-01-08 16:54:13 -050073try:
74 OP_MSIE_SSLV2_RSA_PADDING = _lib.SSL_OP_MSIE_SSLV2_RSA_PADDING
75except AttributeError:
76 pass
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050077OP_SSLEAY_080_CLIENT_DH_BUG = _lib.SSL_OP_SSLEAY_080_CLIENT_DH_BUG
78OP_TLS_D5_BUG = _lib.SSL_OP_TLS_D5_BUG
79OP_TLS_BLOCK_PADDING_BUG = _lib.SSL_OP_TLS_BLOCK_PADDING_BUG
80OP_DONT_INSERT_EMPTY_FRAGMENTS = _lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
81OP_CIPHER_SERVER_PREFERENCE = _lib.SSL_OP_CIPHER_SERVER_PREFERENCE
82OP_TLS_ROLLBACK_BUG = _lib.SSL_OP_TLS_ROLLBACK_BUG
83OP_PKCS1_CHECK_1 = _lib.SSL_OP_PKCS1_CHECK_1
84OP_PKCS1_CHECK_2 = _lib.SSL_OP_PKCS1_CHECK_2
85OP_NETSCAPE_CA_DN_BUG = _lib.SSL_OP_NETSCAPE_CA_DN_BUG
86OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG= _lib.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
Jean-Paul Calderonec1780342014-01-08 16:59:03 -050087try:
88 OP_NO_COMPRESSION = _lib.SSL_OP_NO_COMPRESSION
89except AttributeError:
90 pass
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080091
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050092OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
93OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
Arturo Filastò5f8c7a82014-03-09 20:01:25 +010094try:
95 OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
96except AttributeError:
97 pass
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080098
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050099OP_ALL = _lib.SSL_OP_ALL
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -0800100
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500101VERIFY_PEER = _lib.SSL_VERIFY_PEER
102VERIFY_FAIL_IF_NO_PEER_CERT = _lib.SSL_VERIFY_FAIL_IF_NO_PEER_CERT
103VERIFY_CLIENT_ONCE = _lib.SSL_VERIFY_CLIENT_ONCE
104VERIFY_NONE = _lib.SSL_VERIFY_NONE
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -0800105
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500106SESS_CACHE_OFF = _lib.SSL_SESS_CACHE_OFF
107SESS_CACHE_CLIENT = _lib.SSL_SESS_CACHE_CLIENT
108SESS_CACHE_SERVER = _lib.SSL_SESS_CACHE_SERVER
109SESS_CACHE_BOTH = _lib.SSL_SESS_CACHE_BOTH
110SESS_CACHE_NO_AUTO_CLEAR = _lib.SSL_SESS_CACHE_NO_AUTO_CLEAR
111SESS_CACHE_NO_INTERNAL_LOOKUP = _lib.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
112SESS_CACHE_NO_INTERNAL_STORE = _lib.SSL_SESS_CACHE_NO_INTERNAL_STORE
113SESS_CACHE_NO_INTERNAL = _lib.SSL_SESS_CACHE_NO_INTERNAL
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -0800114
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500115SSL_ST_CONNECT = _lib.SSL_ST_CONNECT
116SSL_ST_ACCEPT = _lib.SSL_ST_ACCEPT
117SSL_ST_MASK = _lib.SSL_ST_MASK
118SSL_ST_INIT = _lib.SSL_ST_INIT
119SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
120SSL_ST_OK = _lib.SSL_ST_OK
121SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800122
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500123SSL_CB_LOOP = _lib.SSL_CB_LOOP
124SSL_CB_EXIT = _lib.SSL_CB_EXIT
125SSL_CB_READ = _lib.SSL_CB_READ
126SSL_CB_WRITE = _lib.SSL_CB_WRITE
127SSL_CB_ALERT = _lib.SSL_CB_ALERT
128SSL_CB_READ_ALERT = _lib.SSL_CB_READ_ALERT
129SSL_CB_WRITE_ALERT = _lib.SSL_CB_WRITE_ALERT
130SSL_CB_ACCEPT_LOOP = _lib.SSL_CB_ACCEPT_LOOP
131SSL_CB_ACCEPT_EXIT = _lib.SSL_CB_ACCEPT_EXIT
132SSL_CB_CONNECT_LOOP = _lib.SSL_CB_CONNECT_LOOP
133SSL_CB_CONNECT_EXIT = _lib.SSL_CB_CONNECT_EXIT
134SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START
135SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800136
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500137class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -0500138 """
139 An error occurred in an `OpenSSL.SSL` API.
140 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500141
142
143
144_raise_current_error = partial(_exception_from_error_queue, Error)
145
146
147class WantReadError(Error):
148 pass
149
150
151
152class WantWriteError(Error):
153 pass
154
155
156
157class WantX509LookupError(Error):
158 pass
159
160
161
162class ZeroReturnError(Error):
163 pass
164
165
166
167class SysCallError(Error):
168 pass
169
170
Cory Benfield0ea76e72015-03-22 09:05:28 +0000171class _CallbackExceptionHelper(object):
172 """
173 A base class for wrapper classes that allow for intelligent exception
174 handling in OpenSSL callbacks.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500175
Jean-Paul Calderone1b172982015-03-22 19:37:11 -0400176 :ivar list _problems: Any exceptions that occurred while executing in a
177 context where they could not be raised in the normal way. Typically
178 this is because OpenSSL has called into some Python code and requires a
179 return value. The exceptions are saved to be raised later when it is
180 possible to do so.
Cory Benfield0ea76e72015-03-22 09:05:28 +0000181 """
Jean-Paul Calderone09540d72015-03-22 19:37:20 -0400182 def __init__(self):
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800183 self._problems = []
184
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800185
Cory Benfield0ea76e72015-03-22 09:05:28 +0000186 def raise_if_problem(self):
Jean-Paul Calderone1b172982015-03-22 19:37:11 -0400187 """
188 Raise an exception from the OpenSSL error queue or that was previously
189 captured whe running a callback.
190 """
Cory Benfield0ea76e72015-03-22 09:05:28 +0000191 if self._problems:
192 try:
193 _raise_current_error()
194 except Error:
195 pass
196 raise self._problems.pop(0)
197
198
199class _VerifyHelper(_CallbackExceptionHelper):
Jean-Paul Calderone1b172982015-03-22 19:37:11 -0400200 """
201 Wrap a callback such that it can be used as a certificate verification
202 callback.
203 """
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800204 def __init__(self, callback):
Jean-Paul Calderone837f4032015-03-22 17:38:28 -0400205 _CallbackExceptionHelper.__init__(self)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800206
207 @wraps(callback)
208 def wrapper(ok, store_ctx):
209 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500210 cert._x509 = _lib.X509_STORE_CTX_get_current_cert(store_ctx)
211 error_number = _lib.X509_STORE_CTX_get_error(store_ctx)
212 error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800213
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400214 index = _lib.SSL_get_ex_data_X509_STORE_CTX_idx()
215 ssl = _lib.X509_STORE_CTX_get_ex_data(store_ctx, index)
216 connection = Connection._reverse_mapping[ssl]
217
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800218 try:
219 result = callback(connection, cert, error_number, error_depth, ok)
220 except Exception as e:
221 self._problems.append(e)
222 return 0
223 else:
224 if result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500225 _lib.X509_STORE_CTX_set_error(store_ctx, _lib.X509_V_OK)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800226 return 1
227 else:
228 return 0
229
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500230 self.callback = _ffi.callback(
231 "int (*)(int, X509_STORE_CTX *)", wrapper)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800232
233
Cory Benfield0ea76e72015-03-22 09:05:28 +0000234class _NpnAdvertiseHelper(_CallbackExceptionHelper):
Jean-Paul Calderone1b172982015-03-22 19:37:11 -0400235 """
236 Wrap a callback such that it can be used as an NPN advertisement callback.
237 """
Cory Benfield0ea76e72015-03-22 09:05:28 +0000238 def __init__(self, callback):
Jean-Paul Calderone837f4032015-03-22 17:38:28 -0400239 _CallbackExceptionHelper.__init__(self)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800240
Cory Benfield0ea76e72015-03-22 09:05:28 +0000241 @wraps(callback)
242 def wrapper(ssl, out, outlen, arg):
243 try:
244 conn = Connection._reverse_mapping[ssl]
245 protos = callback(conn)
246
247 # Join the protocols into a Python bytestring, length-prefixing
248 # each element.
249 protostr = b''.join(
250 chain.from_iterable((int2byte(len(p)), p) for p in protos)
251 )
252
253 # Save our callback arguments on the connection object. This is
254 # done to make sure that they don't get freed before OpenSSL
255 # uses them. Then, return them appropriately in the output
256 # parameters.
257 conn._npn_advertise_callback_args = [
258 _ffi.new("unsigned int *", len(protostr)),
259 _ffi.new("unsigned char[]", protostr),
260 ]
261 outlen[0] = conn._npn_advertise_callback_args[0][0]
262 out[0] = conn._npn_advertise_callback_args[1]
263 return 0
264 except Exception as e:
265 self._problems.append(e)
266 return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
267
268 self.callback = _ffi.callback(
269 "int (*)(SSL *, const unsigned char **, unsigned int *, void *)",
270 wrapper
271 )
272
273
274class _NpnSelectHelper(_CallbackExceptionHelper):
Jean-Paul Calderone1b172982015-03-22 19:37:11 -0400275 """
276 Wrap a callback such that it can be used as an NPN selection callback.
277 """
Cory Benfield0ea76e72015-03-22 09:05:28 +0000278 def __init__(self, callback):
Jean-Paul Calderone837f4032015-03-22 17:38:28 -0400279 _CallbackExceptionHelper.__init__(self)
Cory Benfield0ea76e72015-03-22 09:05:28 +0000280
281 @wraps(callback)
282 def wrapper(ssl, out, outlen, in_, inlen, arg):
283 try:
284 conn = Connection._reverse_mapping[ssl]
285
286 # The string passed to us is actually made up of multiple
287 # length-prefixed bytestrings. We need to split that into a
288 # list.
289 instr = _ffi.buffer(in_, inlen)[:]
290 protolist = []
291 while instr:
292 l = indexbytes(instr, 0)
293 proto = instr[1:l+1]
294 protolist.append(proto)
295 instr = instr[l+1:]
296
297 # Call the callback
298 outstr = callback(conn, protolist)
299
300 # Save our callback arguments on the connection object. This is
301 # done to make sure that they don't get freed before OpenSSL
302 # uses them. Then, return them appropriately in the output
303 # parameters.
304 conn._npn_select_callback_args = [
305 _ffi.new("unsigned char *", len(outstr)),
306 _ffi.new("unsigned char[]", outstr),
307 ]
308 outlen[0] = conn._npn_select_callback_args[0][0]
309 out[0] = conn._npn_select_callback_args[1]
310 return 0
311 except Exception as e:
312 self._problems.append(e)
313 return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
314
315 self.callback = _ffi.callback(
316 "int (*)(SSL *, unsigned char **, unsigned char *, "
317 "const unsigned char *, unsigned int, void *)",
318 wrapper
319 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800320
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800321
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800322def _asFileDescriptor(obj):
323 fd = None
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800324 if not isinstance(obj, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800325 meth = getattr(obj, "fileno", None)
326 if meth is not None:
327 obj = meth()
328
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800329 if isinstance(obj, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800330 fd = obj
331
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800332 if not isinstance(fd, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800333 raise TypeError("argument must be an int, or have a fileno() method.")
334 elif fd < 0:
335 raise ValueError(
336 "file descriptor cannot be a negative integer (%i)" % (fd,))
337
338 return fd
339
340
341
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -0800342def SSLeay_version(type):
343 """
344 Return a string describing the version of OpenSSL in use.
345
346 :param type: One of the SSLEAY_ constants defined in this module.
347 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500348 return _ffi.string(_lib.SSLeay_version(type))
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800349
350
351
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800352class Session(object):
353 pass
354
355
356
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800357class Context(object):
358 """
359 :py:obj:`OpenSSL.SSL.Context` instances define the parameters for setting up
360 new SSL connections.
361 """
362 _methods = {
Andrew Dunhamec84a0a2014-02-24 12:41:37 -0800363 SSLv2_METHOD: "SSLv2_method",
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500364 SSLv3_METHOD: "SSLv3_method",
365 SSLv23_METHOD: "SSLv23_method",
366 TLSv1_METHOD: "TLSv1_method",
367 TLSv1_1_METHOD: "TLSv1_1_method",
368 TLSv1_2_METHOD: "TLSv1_2_method",
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800369 }
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500370 _methods = dict(
371 (identifier, getattr(_lib, name))
372 for (identifier, name) in _methods.items()
373 if getattr(_lib, name, None) is not None)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800374
Jean-Paul Calderone63157872013-03-20 16:43:38 -0700375
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800376 def __init__(self, method):
377 """
378 :param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or
379 TLSv1_METHOD.
380 """
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500381 if not isinstance(method, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800382 raise TypeError("method must be an integer")
383
384 try:
385 method_func = self._methods[method]
386 except KeyError:
387 raise ValueError("No such protocol")
388
389 method_obj = method_func()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500390 if method_obj == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500391 # TODO: This is untested.
392 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800393
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500394 context = _lib.SSL_CTX_new(method_obj)
395 if context == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500396 # TODO: This is untested.
397 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500398 context = _ffi.gc(context, _lib.SSL_CTX_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800399
400 self._context = context
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800401 self._passphrase_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800402 self._passphrase_callback = None
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800403 self._passphrase_userdata = None
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800404 self._verify_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800405 self._verify_callback = None
406 self._info_callback = None
407 self._tlsext_servername_callback = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800408 self._app_data = None
Cory Benfield0ea76e72015-03-22 09:05:28 +0000409 self._npn_advertise_helper = None
Cory Benfield84a121e2014-03-31 20:30:25 +0100410 self._npn_advertise_callback = None
Cory Benfield0ea76e72015-03-22 09:05:28 +0000411 self._npn_select_helper = None
Cory Benfield84a121e2014-03-31 20:30:25 +0100412 self._npn_select_callback = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800413
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -0800414 # SSL_CTX_set_app_data(self->ctx, self);
415 # SSL_CTX_set_mode(self->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
416 # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
417 # SSL_MODE_AUTO_RETRY);
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500418 self.set_mode(_lib.SSL_MODE_ENABLE_PARTIAL_WRITE)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800419
420
421 def load_verify_locations(self, cafile, capath=None):
422 """
423 Let SSL know where we can find trusted certificates for the certificate
424 chain
425
Jean-Paul Calderone55f9e882015-04-12 09:31:03 -0400426 :param cafile: In which file we can find the certificates (``bytes`` or
427 ``unicode``).
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800428 :param capath: In which directory we can find the certificates
Jean-Paul Calderone55f9e882015-04-12 09:31:03 -0400429 (``bytes`` or ``unicode``).
430
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800431 :return: None
432 """
433 if cafile is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500434 cafile = _ffi.NULL
Jean-Paul Calderone55f9e882015-04-12 09:31:03 -0400435 else:
436 cafile = _path_string(cafile)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800437
438 if capath is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500439 capath = _ffi.NULL
Jean-Paul Calderone55f9e882015-04-12 09:31:03 -0400440 else:
441 capath = _path_string(capath)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800442
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500443 load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800444 if not load_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500445 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800446
447
448 def _wrap_callback(self, callback):
449 @wraps(callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800450 def wrapper(size, verify, userdata):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800451 return callback(size, verify, self._passphrase_userdata)
452 return _PassphraseHelper(
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800453 FILETYPE_PEM, wrapper, more_args=True, truncate=True)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800454
455
456 def set_passwd_cb(self, callback, userdata=None):
457 """
458 Set the passphrase callback
459
460 :param callback: The Python callback to use
461 :param userdata: (optional) A Python object which will be given as
462 argument to the callback
463 :return: None
464 """
465 if not callable(callback):
466 raise TypeError("callback must be callable")
467
468 self._passphrase_helper = self._wrap_callback(callback)
469 self._passphrase_callback = self._passphrase_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500470 _lib.SSL_CTX_set_default_passwd_cb(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800471 self._context, self._passphrase_callback)
472 self._passphrase_userdata = userdata
473
474
475 def set_default_verify_paths(self):
476 """
477 Use the platform-specific CA certificate locations
478
479 :return: None
480 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500481 set_result = _lib.SSL_CTX_set_default_verify_paths(self._context)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800482 if not set_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500483 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500484 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800485
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800486
487 def use_certificate_chain_file(self, certfile):
488 """
489 Load a certificate chain from a file
490
Jean-Paul Calderoneb6f8a792015-04-13 10:10:06 -0400491 :param certfile: The name of the certificate chain file (``bytes`` or
492 ``unicode``).
493
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800494 :return: None
495 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -0400496 certfile = _path_string(certfile)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800497
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500498 result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800499 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500500 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800501
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800502
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800503 def use_certificate_file(self, certfile, filetype=FILETYPE_PEM):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800504 """
505 Load a certificate from a file
506
Jean-Paul Calderoneb6f8a792015-04-13 10:10:06 -0400507 :param certfile: The name of the certificate file (``bytes`` or
508 ``unicode``).
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800509 :param filetype: (optional) The encoding of the file, default is PEM
Jean-Paul Calderoneb6f8a792015-04-13 10:10:06 -0400510
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800511 :return: None
512 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400513 certfile = _path_string(certfile)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500514 if not isinstance(filetype, integer_types):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800515 raise TypeError("filetype must be an integer")
516
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 use_result = _lib.SSL_CTX_use_certificate_file(self._context, certfile, filetype)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800518 if not use_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500519 _raise_current_error()
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800520
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800521
522 def use_certificate(self, cert):
523 """
524 Load a certificate from a X509 object
525
526 :param cert: The X509 object
527 :return: None
528 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800529 if not isinstance(cert, X509):
530 raise TypeError("cert must be an X509 instance")
531
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500532 use_result = _lib.SSL_CTX_use_certificate(self._context, cert._x509)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800533 if not use_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500534 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800535
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800536
537 def add_extra_chain_cert(self, certobj):
538 """
539 Add certificate to chain
540
541 :param certobj: The X509 certificate object to add to the chain
542 :return: None
543 """
544 if not isinstance(certobj, X509):
545 raise TypeError("certobj must be an X509 instance")
546
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500547 copy = _lib.X509_dup(certobj._x509)
548 add_result = _lib.SSL_CTX_add_extra_chain_cert(self._context, copy)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800549 if not add_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500550 # TODO: This is untested.
551 _lib.X509_free(copy)
552 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800553
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800554
555 def _raise_passphrase_exception(self):
556 if self._passphrase_helper is None:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500557 _raise_current_error()
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800558 exception = self._passphrase_helper.raise_if_problem(Error)
559 if exception is not None:
560 raise exception
561
562
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800563 def use_privatekey_file(self, keyfile, filetype=_unspecified):
564 """
565 Load a private key from a file
566
Jean-Paul Calderoneb6f8a792015-04-13 10:10:06 -0400567 :param keyfile: The name of the key file (``bytes`` or ``unicode``)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800568 :param filetype: (optional) The encoding of the file, default is PEM
Jean-Paul Calderoneb6f8a792015-04-13 10:10:06 -0400569
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800570 :return: None
571 """
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400572 keyfile = _path_string(keyfile)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800573
574 if filetype is _unspecified:
575 filetype = FILETYPE_PEM
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500576 elif not isinstance(filetype, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800577 raise TypeError("filetype must be an integer")
578
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500579 use_result = _lib.SSL_CTX_use_PrivateKey_file(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800580 self._context, keyfile, filetype)
581 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800582 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800583
584
585 def use_privatekey(self, pkey):
586 """
587 Load a private key from a PKey object
588
589 :param pkey: The PKey object
590 :return: None
591 """
592 if not isinstance(pkey, PKey):
593 raise TypeError("pkey must be a PKey instance")
594
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500595 use_result = _lib.SSL_CTX_use_PrivateKey(self._context, pkey._pkey)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800596 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800597 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800598
599
600 def check_privatekey(self):
601 """
602 Check that the private key and certificate match up
603
604 :return: None (raises an exception if something's wrong)
605 """
Jean-Paul Calderonea0344922014-12-11 14:02:31 -0500606 if not _lib.SSL_CTX_check_private_key(self._context):
607 _raise_current_error()
608
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800609
610 def load_client_ca(self, cafile):
611 """
612 Load the trusted certificates that will be sent to the client (basically
613 telling the client "These are the guys I trust"). Does not actually
614 imply any of the certificates are trusted; that must be configured
615 separately.
616
617 :param cafile: The name of the certificates file
618 :return: None
619 """
620
621 def set_session_id(self, buf):
622 """
623 Set the session identifier. This is needed if you want to do session
624 resumption.
625
626 :param buf: A Python object that can be safely converted to a string
627 :returns: None
628 """
629
630 def set_session_cache_mode(self, mode):
631 """
632 Enable/disable session caching and specify the mode used.
633
634 :param mode: One or more of the SESS_CACHE_* flags (combine using
635 bitwise or)
636 :returns: The previously set caching mode.
637 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500638 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800639 raise TypeError("mode must be an integer")
640
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500641 return _lib.SSL_CTX_set_session_cache_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800642
643
644 def get_session_cache_mode(self):
645 """
646 :returns: The currently used cache mode.
647 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500648 return _lib.SSL_CTX_get_session_cache_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800649
650
651 def set_verify(self, mode, callback):
652 """
653 Set the verify mode and verify callback
654
655 :param mode: The verify mode, this is either VERIFY_NONE or
656 VERIFY_PEER combined with possible other flags
657 :param callback: The Python callback to use
658 :return: None
659
660 See SSL_CTX_set_verify(3SSL) for further details.
661 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500662 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800663 raise TypeError("mode must be an integer")
664
665 if not callable(callback):
666 raise TypeError("callback must be callable")
667
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400668 self._verify_helper = _VerifyHelper(callback)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800669 self._verify_callback = self._verify_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500670 _lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800671
672
673 def set_verify_depth(self, depth):
674 """
675 Set the verify depth
676
677 :param depth: An integer specifying the verify depth
678 :return: None
679 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500680 if not isinstance(depth, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800681 raise TypeError("depth must be an integer")
682
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500683 _lib.SSL_CTX_set_verify_depth(self._context, depth)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800684
685
686 def get_verify_mode(self):
687 """
688 Get the verify mode
689
690 :return: The verify mode
691 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500692 return _lib.SSL_CTX_get_verify_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800693
694
695 def get_verify_depth(self):
696 """
697 Get the verify depth
698
699 :return: The verify depth
700 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500701 return _lib.SSL_CTX_get_verify_depth(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800702
703
704 def load_tmp_dh(self, dhfile):
705 """
706 Load parameters for Ephemeral Diffie-Hellman
707
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400708 :param dhfile: The file to load EDH parameters from (``bytes`` or
709 ``unicode``).
710
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800711 :return: None
712 """
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -0400713 dhfile = _path_string(dhfile)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800714
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500715 bio = _lib.BIO_new_file(dhfile, b"r")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500716 if bio == _ffi.NULL:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500717 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500718 bio = _ffi.gc(bio, _lib.BIO_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800719
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500720 dh = _lib.PEM_read_bio_DHparams(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
721 dh = _ffi.gc(dh, _lib.DH_free)
722 _lib.SSL_CTX_set_tmp_dh(self._context, dh)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800723
724
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -0400725 def set_tmp_ecdh(self, curve):
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600726 """
Andy Lutomirski76a61332014-03-12 15:02:56 -0700727 Select a curve to use for ECDHE key exchange.
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600728
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400729 :param curve: A curve object to use as returned by either
730 :py:meth:`OpenSSL.crypto.get_elliptic_curve` or
731 :py:meth:`OpenSSL.crypto.get_elliptic_curves`.
Andy Lutomirskif05a2732014-03-13 17:22:25 -0700732
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600733 :return: None
734 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400735 _lib.SSL_CTX_set_tmp_ecdh(self._context, curve._to_EC_KEY())
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600736
737
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800738 def set_cipher_list(self, cipher_list):
739 """
740 Change the cipher list
741
742 :param cipher_list: A cipher list, see ciphers(1)
743 :return: None
744 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -0500745 if isinstance(cipher_list, _text_type):
746 cipher_list = cipher_list.encode("ascii")
747
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800748 if not isinstance(cipher_list, bytes):
Jean-Paul Calderone63eab692014-01-18 10:19:56 -0500749 raise TypeError("cipher_list must be bytes or unicode")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800750
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500751 result = _lib.SSL_CTX_set_cipher_list(self._context, cipher_list)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800752 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500753 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800754
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800755
756 def set_client_ca_list(self, certificate_authorities):
757 """
758 Set the list of preferred client certificate signers for this server context.
759
760 This list of certificate authorities will be sent to the client when the
761 server requests a client certificate.
762
763 :param certificate_authorities: a sequence of X509Names.
764 :return: None
765 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500766 name_stack = _lib.sk_X509_NAME_new_null()
767 if name_stack == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500768 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500769 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800770
771 try:
772 for ca_name in certificate_authorities:
773 if not isinstance(ca_name, X509Name):
774 raise TypeError(
775 "client CAs must be X509Name objects, not %s objects" % (
776 type(ca_name).__name__,))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500777 copy = _lib.X509_NAME_dup(ca_name._name)
778 if copy == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500779 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500780 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500781 push_result = _lib.sk_X509_NAME_push(name_stack, copy)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800782 if not push_result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500783 _lib.X509_NAME_free(copy)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500784 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800785 except:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500786 _lib.sk_X509_NAME_free(name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800787 raise
788
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500789 _lib.SSL_CTX_set_client_CA_list(self._context, name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800790
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800791
792 def add_client_ca(self, certificate_authority):
793 """
794 Add the CA certificate to the list of preferred signers for this context.
795
796 The list of certificate authorities will be sent to the client when the
797 server requests a client certificate.
798
799 :param certificate_authority: certificate authority's X509 certificate.
800 :return: None
801 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800802 if not isinstance(certificate_authority, X509):
803 raise TypeError("certificate_authority must be an X509 instance")
804
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500805 add_result = _lib.SSL_CTX_add_client_CA(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800806 self._context, certificate_authority._x509)
807 if not add_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500808 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500809 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800810
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800811
812 def set_timeout(self, timeout):
813 """
814 Set session timeout
815
816 :param timeout: The timeout in seconds
817 :return: The previous session timeout
818 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500819 if not isinstance(timeout, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800820 raise TypeError("timeout must be an integer")
821
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500822 return _lib.SSL_CTX_set_timeout(self._context, timeout)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800823
824
825 def get_timeout(self):
826 """
827 Get the session timeout
828
829 :return: The session timeout
830 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500831 return _lib.SSL_CTX_get_timeout(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800832
833
834 def set_info_callback(self, callback):
835 """
836 Set the info callback
837
838 :param callback: The Python callback to use
839 :return: None
840 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800841 @wraps(callback)
842 def wrapper(ssl, where, return_code):
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500843 callback(Connection._reverse_mapping[ssl], where, return_code)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500844 self._info_callback = _ffi.callback(
845 "void (*)(const SSL *, int, int)", wrapper)
846 _lib.SSL_CTX_set_info_callback(self._context, self._info_callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800847
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800848
849 def get_app_data(self):
850 """
851 Get the application data (supplied via set_app_data())
852
853 :return: The application data
854 """
855 return self._app_data
856
857
858 def set_app_data(self, data):
859 """
860 Set the application data (will be returned from get_app_data())
861
862 :param data: Any Python object
863 :return: None
864 """
865 self._app_data = data
866
867
868 def get_cert_store(self):
869 """
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500870 Get the certificate store for the context.
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800871
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500872 :return: A X509Store object or None if it does not have one.
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800873 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500874 store = _lib.SSL_CTX_get_cert_store(self._context)
875 if store == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500876 # TODO: This is untested.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800877 return None
878
879 pystore = X509Store.__new__(X509Store)
880 pystore._store = store
881 return pystore
882
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800883
884 def set_options(self, options):
885 """
886 Add options. Options set before are not cleared!
887
888 :param options: The options to add.
889 :return: The new option bitmask.
890 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500891 if not isinstance(options, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800892 raise TypeError("options must be an integer")
893
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500894 return _lib.SSL_CTX_set_options(self._context, options)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800895
896
897 def set_mode(self, mode):
898 """
899 Add modes via bitmask. Modes set before are not cleared!
900
901 :param mode: The mode to add.
902 :return: The new mode bitmask.
903 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500904 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800905 raise TypeError("mode must be an integer")
906
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500907 return _lib.SSL_CTX_set_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800908
909
910 def set_tlsext_servername_callback(self, callback):
911 """
912 Specify a callback function to be called when clients specify a server name.
913
914 :param callback: The callback function. It will be invoked with one
915 argument, the Connection instance.
916 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800917 @wraps(callback)
918 def wrapper(ssl, alert, arg):
919 callback(Connection._reverse_mapping[ssl])
920 return 0
921
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500922 self._tlsext_servername_callback = _ffi.callback(
923 "int (*)(const SSL *, int *, void *)", wrapper)
924 _lib.SSL_CTX_set_tlsext_servername_callback(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800925 self._context, self._tlsext_servername_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800926
Cory Benfield84a121e2014-03-31 20:30:25 +0100927
928 def set_npn_advertise_callback(self, callback):
929 """
Cory Benfieldbe3e7b82014-05-10 09:48:55 +0100930 Specify a callback function that will be called when offering `Next
931 Protocol Negotiation
932 <https://technotes.googlecode.com/git/nextprotoneg.html>`_ as a server.
Cory Benfield84a121e2014-03-31 20:30:25 +0100933
934 :param callback: The callback function. It will be invoked with one
Cory Benfieldbe3e7b82014-05-10 09:48:55 +0100935 argument, the Connection instance. It should return a list of
936 bytestrings representing the advertised protocols, like
937 ``[b'http/1.1', b'spdy/2']``.
Cory Benfield84a121e2014-03-31 20:30:25 +0100938 """
Cory Benfield0ea76e72015-03-22 09:05:28 +0000939 self._npn_advertise_helper = _NpnAdvertiseHelper(callback)
940 self._npn_advertise_callback = self._npn_advertise_helper.callback
Cory Benfield84a121e2014-03-31 20:30:25 +0100941 _lib.SSL_CTX_set_next_protos_advertised_cb(
942 self._context, self._npn_advertise_callback, _ffi.NULL)
943
944
945 def set_npn_select_callback(self, callback):
946 """
947 Specify a callback function that will be called when a server offers
948 Next Protocol Negotiation options.
949
950 :param callback: The callback function. It will be invoked with two
951 arguments: the Connection, and a list of offered protocols as
Cory Benfieldbe3e7b82014-05-10 09:48:55 +0100952 bytestrings, e.g. ``[b'http/1.1', b'spdy/2']``. It should return
953 one of those bytestrings, the chosen protocol.
Cory Benfield84a121e2014-03-31 20:30:25 +0100954 """
Cory Benfield0ea76e72015-03-22 09:05:28 +0000955 self._npn_select_helper = _NpnSelectHelper(callback)
956 self._npn_select_callback = self._npn_select_helper.callback
Cory Benfield84a121e2014-03-31 20:30:25 +0100957 _lib.SSL_CTX_set_next_proto_select_cb(
958 self._context, self._npn_select_callback, _ffi.NULL)
959
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800960ContextType = Context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800961
962
963
964class Connection(object):
965 """
966 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800967 _reverse_mapping = WeakValueDictionary()
968
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800969 def __init__(self, context, socket=None):
970 """
971 Create a new Connection object, using the given OpenSSL.SSL.Context
972 instance and socket.
973
974 :param context: An SSL Context to use for this connection
975 :param socket: The socket to use for transport layer
976 """
977 if not isinstance(context, Context):
978 raise TypeError("context must be a Context instance")
979
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500980 ssl = _lib.SSL_new(context._context)
981 self._ssl = _ffi.gc(ssl, _lib.SSL_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800982 self._context = context
983
Cory Benfieldbe3e7b82014-05-10 09:48:55 +0100984 # References to strings used for Next Protocol Negotiation. OpenSSL's
985 # header files suggest that these might get copied at some point, but
986 # doesn't specify when, so we store them here to make sure they don't
987 # get freed before OpenSSL uses them.
988 self._npn_advertise_callback_args = None
989 self._npn_select_callback_args = None
990
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800991 self._reverse_mapping[self._ssl] = self
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800992
993 if socket is None:
994 self._socket = None
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -0800995 # Don't set up any gc for these, SSL_free will take care of them.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500996 self._into_ssl = _lib.BIO_new(_lib.BIO_s_mem())
997 self._from_ssl = _lib.BIO_new(_lib.BIO_s_mem())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800998
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500999 if self._into_ssl == _ffi.NULL or self._from_ssl == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001000 # TODO: This is untested.
1001 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001002
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001003 _lib.SSL_set_bio(self._ssl, self._into_ssl, self._from_ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001004 else:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001005 self._into_ssl = None
1006 self._from_ssl = None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001007 self._socket = socket
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001008 set_result = _lib.SSL_set_fd(self._ssl, _asFileDescriptor(self._socket))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001009 if not set_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001010 # TODO: This is untested.
1011 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001012
1013
1014 def __getattr__(self, name):
1015 """
1016 Look up attributes on the wrapped socket object if they are not found on
1017 the Connection object.
1018 """
1019 return getattr(self._socket, name)
1020
1021
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001022 def _raise_ssl_error(self, ssl, result):
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001023 if self._context._verify_helper is not None:
1024 self._context._verify_helper.raise_if_problem()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001025 if self._context._npn_advertise_helper is not None:
1026 self._context._npn_advertise_helper.raise_if_problem()
1027 if self._context._npn_select_helper is not None:
1028 self._context._npn_select_helper.raise_if_problem()
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001029
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001030 error = _lib.SSL_get_error(ssl, result)
1031 if error == _lib.SSL_ERROR_WANT_READ:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001032 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001033 elif error == _lib.SSL_ERROR_WANT_WRITE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001034 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001035 elif error == _lib.SSL_ERROR_ZERO_RETURN:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001036 raise ZeroReturnError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001037 elif error == _lib.SSL_ERROR_WANT_X509_LOOKUP:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001038 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001039 raise WantX509LookupError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001040 elif error == _lib.SSL_ERROR_SYSCALL:
1041 if _lib.ERR_peek_error() == 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001042 if result < 0:
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02001043 if platform == "win32":
1044 errno = _ffi.getwinerror()[0]
1045 else:
1046 errno = _ffi.errno
1047 raise SysCallError(errno, errorcode[errno])
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001048 else:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001049 raise SysCallError(-1, "Unexpected EOF")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001050 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001051 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001052 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001053 elif error == _lib.SSL_ERROR_NONE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001054 pass
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001055 else:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001056 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001057
1058
1059 def get_context(self):
1060 """
1061 Get session context
1062 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001063 return self._context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001064
1065
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001066 def set_context(self, context):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001067 """
1068 Switch this connection to a new session context
1069
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001070 :param context: A :py:class:`Context` instance giving the new session
1071 context to use.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001072 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001073 if not isinstance(context, Context):
1074 raise TypeError("context must be a Context instance")
1075
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001076 _lib.SSL_set_SSL_CTX(self._ssl, context._context)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001077 self._context = context
1078
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001079
1080 def get_servername(self):
1081 """
1082 Retrieve the servername extension value if provided in the client hello
1083 message, or None if there wasn't one.
1084
1085 :return: A byte string giving the server name or :py:data:`None`.
1086 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001087 name = _lib.SSL_get_servername(self._ssl, _lib.TLSEXT_NAMETYPE_host_name)
1088 if name == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001089 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001090
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001091 return _ffi.string(name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001092
1093
1094 def set_tlsext_host_name(self, name):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001095 """
1096 Set the value of the servername extension to send in the client hello.
1097
1098 :param name: A byte string giving the name.
1099 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001100 if not isinstance(name, bytes):
1101 raise TypeError("name must be a byte string")
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001102 elif b"\0" in name:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001103 raise TypeError("name must not contain NUL byte")
1104
1105 # XXX I guess this can fail sometimes?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001106 _lib.SSL_set_tlsext_host_name(self._ssl, name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001107
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001108
1109 def pending(self):
1110 """
1111 Get the number of bytes that can be safely read from the connection
1112
1113 :return: The number of bytes available in the receive buffer.
1114 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001115 return _lib.SSL_pending(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001116
1117
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001118 def send(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001119 """
1120 Send data on the connection. NOTE: If you get one of the WantRead,
1121 WantWrite or WantX509Lookup exceptions on this, you have to call the
1122 method again with the SAME buffer.
1123
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001124 :param buf: The string, buffer or memoryview to send
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001125 :param flags: (optional) Included for compatibility with the socket
1126 API, the value is ignored
1127 :return: The number of bytes written
1128 """
Abraham Martine82326c2015-02-04 10:18:10 +00001129 # Backward compatibility
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001130 buf = _warn_text("buf", buf)
Abraham Martine82326c2015-02-04 10:18:10 +00001131
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -05001132 if isinstance(buf, _memoryview):
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -08001133 buf = buf.tobytes()
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001134 if isinstance(buf, _buffer):
1135 buf = str(buf)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001136 if not isinstance(buf, bytes):
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001137 raise TypeError("data must be a memoryview, buffer or byte string")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001138
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001139 result = _lib.SSL_write(self._ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001140 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001141 return result
1142 write = send
1143
1144
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001145 def sendall(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001146 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001147 Send "all" data on the connection. This calls send() repeatedly until
1148 all data is sent. If an error occurs, it's impossible to tell how much
1149 data has been sent.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001150
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001151 :param buf: The string, buffer or memoryview to send
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001152 :param flags: (optional) Included for compatibility with the socket
1153 API, the value is ignored
1154 :return: The number of bytes written
1155 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001156 buf = _warn_text("buf", buf)
Abraham Martine82326c2015-02-04 10:18:10 +00001157
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -05001158 if isinstance(buf, _memoryview):
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -08001159 buf = buf.tobytes()
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001160 if isinstance(buf, _buffer):
1161 buf = str(buf)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001162 if not isinstance(buf, bytes):
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02001163 raise TypeError("buf must be a memoryview, buffer or byte string")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001164
1165 left_to_send = len(buf)
1166 total_sent = 0
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001167 data = _ffi.new("char[]", buf)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001168
1169 while left_to_send:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001170 result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001171 self._raise_ssl_error(self._ssl, result)
1172 total_sent += result
1173 left_to_send -= result
1174
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001175
1176 def recv(self, bufsiz, flags=None):
1177 """
1178 Receive data on the connection. NOTE: If you get one of the WantRead,
1179 WantWrite or WantX509Lookup exceptions on this, you have to call the
1180 method again with the SAME buffer.
1181
1182 :param bufsiz: The maximum number of bytes to read
1183 :param flags: (optional) Included for compatibility with the socket
1184 API, the value is ignored
1185 :return: The string read from the Connection
1186 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001187 buf = _ffi.new("char[]", bufsiz)
1188 result = _lib.SSL_read(self._ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001189 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001190 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001191 read = recv
1192
1193
Cory Benfield62d10332014-06-15 10:03:41 +01001194 def recv_into(self, buffer, nbytes=None, flags=None):
1195 """
1196 Receive data on the connection and store the data into a buffer rather
1197 than creating a new string.
1198
1199 :param buffer: The buffer to copy into.
1200 :param nbytes: (optional) The maximum number of bytes to read into the
1201 buffer. If not present, defaults to the size of the buffer. If
1202 larger than the size of the buffer, is reduced to the size of the
1203 buffer.
1204 :param flags: (optional) Included for compatibility with the socket
1205 API, the value is ignored.
1206 :return: The number of bytes read into the buffer.
1207 """
1208 if nbytes is None:
1209 nbytes = len(buffer)
1210 else:
1211 nbytes = min(nbytes, len(buffer))
1212
1213 # We need to create a temporary buffer. This is annoying, it would be
1214 # better if we could pass memoryviews straight into the SSL_read call,
1215 # but right now we can't. Revisit this if CFFI gets that ability.
1216 buf = _ffi.new("char[]", nbytes)
1217 result = _lib.SSL_read(self._ssl, buf, nbytes)
1218 self._raise_ssl_error(self._ssl, result)
1219
1220 # This strange line is all to avoid a memory copy. The buffer protocol
1221 # should allow us to assign a CFFI buffer to the LHS of this line, but
1222 # on CPython 3.3+ that segfaults. As a workaround, we can temporarily
1223 # wrap it in a memoryview, except on Python 2.6 which doesn't have a
1224 # memoryview type.
1225 try:
1226 buffer[:result] = memoryview(_ffi.buffer(buf, result))
1227 except NameError:
1228 buffer[:result] = _ffi.buffer(buf, result)
1229
1230 return result
1231
1232
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001233 def _handle_bio_errors(self, bio, result):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001234 if _lib.BIO_should_retry(bio):
1235 if _lib.BIO_should_read(bio):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001236 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001237 elif _lib.BIO_should_write(bio):
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001238 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001239 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001240 elif _lib.BIO_should_io_special(bio):
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001241 # TODO: This is untested. I think io_special means the socket
1242 # BIO has a not-yet connected socket.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001243 raise ValueError("BIO_should_io_special")
1244 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001245 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001246 raise ValueError("unknown bio failure")
1247 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001248 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001249 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001250
1251
1252 def bio_read(self, bufsiz):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001253 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001254 When using non-socket connections this function reads the "dirty" data
1255 that would have traveled away on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001256
1257 :param bufsiz: The maximum number of bytes to read
1258 :return: The string read.
1259 """
Jean-Paul Calderone97e041d2013-03-05 21:03:12 -08001260 if self._from_ssl is None:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001261 raise TypeError("Connection sock was not None")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001262
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001263 if not isinstance(bufsiz, integer_types):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001264 raise TypeError("bufsiz must be an integer")
1265
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001266 buf = _ffi.new("char[]", bufsiz)
1267 result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001268 if result <= 0:
1269 self._handle_bio_errors(self._from_ssl, result)
1270
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001271 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001272
1273
1274 def bio_write(self, buf):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001275 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001276 When using non-socket connections this function sends "dirty" data that
1277 would have traveled in on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001278
1279 :param buf: The string to put into the memory BIO.
1280 :return: The number of bytes written
1281 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04001282 buf = _warn_text("buf", buf)
Abraham Martine82326c2015-02-04 10:18:10 +00001283
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001284 if self._into_ssl is None:
1285 raise TypeError("Connection sock was not None")
1286
1287 if not isinstance(buf, bytes):
1288 raise TypeError("buf must be a byte string")
1289
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001290 result = _lib.BIO_write(self._into_ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001291 if result <= 0:
1292 self._handle_bio_errors(self._into_ssl, result)
1293 return result
1294
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001295
1296 def renegotiate(self):
1297 """
1298 Renegotiate the session
1299
1300 :return: True if the renegotiation can be started, false otherwise
1301 """
1302
1303 def do_handshake(self):
1304 """
1305 Perform an SSL handshake (usually called after renegotiate() or one of
1306 set_*_state()). This can raise the same exceptions as send and recv.
1307
1308 :return: None.
1309 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001310 result = _lib.SSL_do_handshake(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001311 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001312
1313
1314 def renegotiate_pending(self):
1315 """
1316 Check if there's a renegotiation in progress, it will return false once
1317 a renegotiation is finished.
1318
1319 :return: Whether there's a renegotiation in progress
1320 """
1321
1322 def total_renegotiations(self):
1323 """
1324 Find out the total number of renegotiations.
1325
1326 :return: The number of renegotiations.
1327 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001328 return _lib.SSL_total_renegotiations(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001329
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001330
1331 def connect(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001332 """
1333 Connect to remote host and set up client-side SSL
1334
1335 :param addr: A remote address
1336 :return: What the socket's connect method returns
1337 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001338 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001339 return self._socket.connect(addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001340
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001341
1342 def connect_ex(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001343 """
1344 Connect to remote host and set up client-side SSL. Note that if the socket's
1345 connect_ex method doesn't return 0, SSL won't be initialized.
1346
1347 :param addr: A remove address
1348 :return: What the socket's connect_ex method returns
1349 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001350 connect_ex = self._socket.connect_ex
1351 self.set_connect_state()
1352 return connect_ex(addr)
1353
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001354
1355 def accept(self):
1356 """
1357 Accept incoming connection and set up SSL on it
1358
1359 :return: A (conn,addr) pair where conn is a Connection and addr is an
1360 address
1361 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001362 client, addr = self._socket.accept()
1363 conn = Connection(self._context, client)
1364 conn.set_accept_state()
1365 return (conn, addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001366
1367
1368 def bio_shutdown(self):
1369 """
1370 When using non-socket connections this function signals end of
1371 data on the input for this connection.
1372
1373 :return: None
1374 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001375 if self._from_ssl is None:
1376 raise TypeError("Connection sock was not None")
1377
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001378 _lib.BIO_set_mem_eof_return(self._into_ssl, 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001379
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001380
1381 def shutdown(self):
1382 """
1383 Send closure alert
1384
1385 :return: True if the shutdown completed successfully (i.e. both sides
1386 have sent closure alerts), false otherwise (i.e. you have to
1387 wait for a ZeroReturnError on a recv() method call
1388 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001389 result = _lib.SSL_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001390 if result < 0:
Paul Aurichbff1d1a2015-01-08 08:36:53 -08001391 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001392 elif result > 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001393 return True
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001394 else:
1395 return False
1396
1397
1398 def get_cipher_list(self):
1399 """
1400 Get the session cipher list
1401
1402 :return: A list of cipher strings
1403 """
1404 ciphers = []
1405 for i in count():
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001406 result = _lib.SSL_get_cipher_list(self._ssl, i)
1407 if result == _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001408 break
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001409 ciphers.append(_native(_ffi.string(result)))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001410 return ciphers
1411
1412
1413 def get_client_ca_list(self):
1414 """
1415 Get CAs whose certificates are suggested for client authentication.
1416
1417 :return: If this is a server connection, a list of X509Names representing
1418 the acceptable CAs as set by :py:meth:`OpenSSL.SSL.Context.set_client_ca_list` or
1419 :py:meth:`OpenSSL.SSL.Context.add_client_ca`. If this is a client connection,
1420 the list of such X509Names sent by the server, or an empty list if that
1421 has not yet happened.
1422 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001423 ca_names = _lib.SSL_get_client_CA_list(self._ssl)
1424 if ca_names == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001425 # TODO: This is untested.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001426 return []
1427
1428 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001429 for i in range(_lib.sk_X509_NAME_num(ca_names)):
1430 name = _lib.sk_X509_NAME_value(ca_names, i)
1431 copy = _lib.X509_NAME_dup(name)
1432 if copy == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001433 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001434 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001435
1436 pyname = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001437 pyname._name = _ffi.gc(copy, _lib.X509_NAME_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001438 result.append(pyname)
1439 return result
1440
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001441
1442 def makefile(self):
1443 """
1444 The makefile() method is not implemented, since there is no dup semantics
1445 for SSL connections
1446
Jean-Paul Calderone6749ec22014-04-17 16:30:21 -04001447 :raise: NotImplementedError
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001448 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001449 raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001450
1451
1452 def get_app_data(self):
1453 """
1454 Get application data
1455
1456 :return: The application data
1457 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001458 return self._app_data
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001459
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001460
1461 def set_app_data(self, data):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001462 """
1463 Set application data
1464
1465 :param data - The application data
1466 :return: None
1467 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001468 self._app_data = data
1469
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001470
1471 def get_shutdown(self):
1472 """
1473 Get shutdown state
1474
1475 :return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1476 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001477 return _lib.SSL_get_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001478
1479
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001480 def set_shutdown(self, state):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001481 """
1482 Set shutdown state
1483
1484 :param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1485 :return: None
1486 """
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001487 if not isinstance(state, integer_types):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001488 raise TypeError("state must be an integer")
1489
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001490 _lib.SSL_set_shutdown(self._ssl, state)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001491
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001492
1493 def state_string(self):
1494 """
1495 Get a verbose state description
1496
1497 :return: A string representing the state
1498 """
1499
1500 def server_random(self):
1501 """
1502 Get a copy of the server hello nonce.
1503
1504 :return: A string representing the state
1505 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001506 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001507 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001508 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001509 self._ssl.s3.server_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001510 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001511
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001512
1513 def client_random(self):
1514 """
1515 Get a copy of the client hello nonce.
1516
1517 :return: A string representing the state
1518 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001519 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001520 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001521 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001522 self._ssl.s3.client_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001523 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001524
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001525
1526 def master_key(self):
1527 """
1528 Get a copy of the master key.
1529
1530 :return: A string representing the state
1531 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001532 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001533 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001534 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001535 self._ssl.session.master_key,
1536 self._ssl.session.master_key_length)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001537
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001538
1539 def sock_shutdown(self, *args, **kwargs):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001540 """
1541 See shutdown(2)
1542
1543 :return: What the socket's shutdown() method returns
1544 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001545 return self._socket.shutdown(*args, **kwargs)
1546
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001547
1548 def get_peer_certificate(self):
1549 """
1550 Retrieve the other side's certificate (if any)
1551
1552 :return: The peer's certificate
1553 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001554 cert = _lib.SSL_get_peer_certificate(self._ssl)
1555 if cert != _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001556 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001557 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001558 return pycert
1559 return None
1560
1561
1562 def get_peer_cert_chain(self):
1563 """
1564 Retrieve the other side's certificate (if any)
1565
1566 :return: A list of X509 instances giving the peer's certificate chain,
1567 or None if it does not have one.
1568 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001569 cert_stack = _lib.SSL_get_peer_cert_chain(self._ssl)
1570 if cert_stack == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001571 return None
1572
1573 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001574 for i in range(_lib.sk_X509_num(cert_stack)):
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -08001575 # TODO could incref instead of dup here
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001576 cert = _lib.X509_dup(_lib.sk_X509_value(cert_stack, i))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001577 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001578 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001579 result.append(pycert)
1580 return result
1581
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001582
1583 def want_read(self):
1584 """
1585 Checks if more data has to be read from the transport layer to complete an
1586 operation.
1587
1588 :return: True iff more data has to be read
1589 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001590 return _lib.SSL_want_read(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001591
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001592
1593 def want_write(self):
1594 """
1595 Checks if there is data to write to the transport layer to complete an
1596 operation.
1597
1598 :return: True iff there is data to write
1599 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001600 return _lib.SSL_want_write(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001601
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001602
1603 def set_accept_state(self):
1604 """
1605 Set the connection to work in server mode. The handshake will be handled
1606 automatically by read/write.
1607
1608 :return: None
1609 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001610 _lib.SSL_set_accept_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001611
1612
1613 def set_connect_state(self):
1614 """
1615 Set the connection to work in client mode. The handshake will be handled
1616 automatically by read/write.
1617
1618 :return: None
1619 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001620 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001621
1622
1623 def get_session(self):
1624 """
1625 Returns the Session currently used.
1626
1627 @return: An instance of :py:class:`OpenSSL.SSL.Session` or :py:obj:`None` if
1628 no session exists.
1629 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001630 session = _lib.SSL_get1_session(self._ssl)
1631 if session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001632 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001633
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001634 pysession = Session.__new__(Session)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001635 pysession._session = _ffi.gc(session, _lib.SSL_SESSION_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001636 return pysession
1637
1638
1639 def set_session(self, session):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001640 """
1641 Set the session to be used when the TLS/SSL connection is established.
1642
1643 :param session: A Session instance representing the session to use.
1644 :returns: None
1645 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001646 if not isinstance(session, Session):
1647 raise TypeError("session must be a Session instance")
1648
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001649 result = _lib.SSL_set_session(self._ssl, session._session)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001650 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001651 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001652
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001653
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001654 def _get_finished_message(self, function):
1655 """
1656 Helper to implement :py:meth:`get_finished` and
1657 :py:meth:`get_peer_finished`.
1658
1659 :param function: Either :py:data:`SSL_get_finished`: or
1660 :py:data:`SSL_get_peer_finished`.
1661
1662 :return: :py:data:`None` if the desired message has not yet been
1663 received, otherwise the contents of the message.
1664 :rtype: :py:class:`bytes` or :py:class:`NoneType`
1665 """
Jean-Paul Calderone01af9042014-03-30 11:40:42 -04001666 # The OpenSSL documentation says nothing about what might happen if the
1667 # count argument given is zero. Specifically, it doesn't say whether
1668 # the output buffer may be NULL in that case or not. Inspection of the
1669 # implementation reveals that it calls memcpy() unconditionally.
1670 # Section 7.1.4, paragraph 1 of the C standard suggests that
1671 # memcpy(NULL, source, 0) is not guaranteed to produce defined (let
1672 # alone desirable) behavior (though it probably does on just about
1673 # every implementation...)
1674 #
1675 # Allocate a tiny buffer to pass in (instead of just passing NULL as
1676 # one might expect) for the initial call so as to be safe against this
1677 # potentially undefined behavior.
1678 empty = _ffi.new("char[]", 0)
1679 size = function(self._ssl, empty, 0)
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001680 if size == 0:
1681 # No Finished message so far.
1682 return None
1683
1684 buf = _ffi.new("char[]", size)
1685 function(self._ssl, buf, size)
1686 return _ffi.buffer(buf, size)[:]
1687
1688
Fedor Brunner5747b932014-03-05 14:22:34 +01001689 def get_finished(self):
1690 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001691 Obtain the latest `handshake finished` message sent to the peer.
Fedor Brunner5747b932014-03-05 14:22:34 +01001692
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001693 :return: The contents of the message or :py:obj:`None` if the TLS
1694 handshake has not yet completed.
1695 :rtype: :py:class:`bytes` or :py:class:`NoneType`
Fedor Brunner5747b932014-03-05 14:22:34 +01001696 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001697 return self._get_finished_message(_lib.SSL_get_finished)
1698
Fedor Brunner5747b932014-03-05 14:22:34 +01001699
1700 def get_peer_finished(self):
1701 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001702 Obtain the latest `handshake finished` message received from the peer.
Fedor Brunner5747b932014-03-05 14:22:34 +01001703
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001704 :return: The contents of the message or :py:obj:`None` if the TLS
1705 handshake has not yet completed.
1706 :rtype: :py:class:`bytes` or :py:class:`NoneType`
Fedor Brunner5747b932014-03-05 14:22:34 +01001707 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001708 return self._get_finished_message(_lib.SSL_get_peer_finished)
Fedor Brunner5747b932014-03-05 14:22:34 +01001709
Jean-Paul Calderone7c556ef2014-03-30 10:45:00 -04001710
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001711 def get_cipher_name(self):
1712 """
1713 Obtain the name of the currently used cipher.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001714
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001715 :returns: The name of the currently used cipher or :py:obj:`None`
1716 if no connection has been established.
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001717 :rtype: :py:class:`unicode` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001718 """
1719 cipher = _lib.SSL_get_current_cipher(self._ssl)
1720 if cipher == _ffi.NULL:
1721 return None
1722 else:
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001723 name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher))
1724 return name.decode("utf-8")
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001725
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001726
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001727 def get_cipher_bits(self):
1728 """
1729 Obtain the number of secret bits of the currently used cipher.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001730
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001731 :returns: The number of secret bits of the currently used cipher
1732 or :py:obj:`None` if no connection has been established.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001733 :rtype: :py:class:`int` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001734 """
1735 cipher = _lib.SSL_get_current_cipher(self._ssl)
1736 if cipher == _ffi.NULL:
1737 return None
1738 else:
1739 return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL)
1740
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001741
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001742 def get_cipher_version(self):
1743 """
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001744 Obtain the protocol version of the currently used cipher.
1745
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001746 :returns: The protocol name of the currently used cipher
1747 or :py:obj:`None` if no connection has been established.
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001748 :rtype: :py:class:`unicode` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001749 """
1750 cipher = _lib.SSL_get_current_cipher(self._ssl)
1751 if cipher == _ffi.NULL:
1752 return None
1753 else:
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001754 version =_ffi.string(_lib.SSL_CIPHER_get_version(cipher))
1755 return version.decode("utf-8")
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001756
Cory Benfield84a121e2014-03-31 20:30:25 +01001757 def get_next_proto_negotiated(self):
1758 """
1759 Get the protocol that was negotiated by NPN.
1760 """
1761 data = _ffi.new("unsigned char **")
1762 data_len = _ffi.new("unsigned int *")
1763
1764 _lib.SSL_get0_next_proto_negotiated(self._ssl, data, data_len)
1765
Cory Benfieldcd010f62014-05-15 19:00:27 +01001766 return _ffi.buffer(data[0], data_len[0])[:]
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001767
1768
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001769ConnectionType = Connection
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05001770
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05001771# This is similar to the initialization calls at the end of OpenSSL/crypto.py
1772# but is exercised mostly by the Context initializer.
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05001773_lib.SSL_library_init()