blob: e5ae0855232fb885a72f4b1f2af5ddec0d14d96f [file] [log] [blame]
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02001from sys import platform
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002from functools import wraps, partial
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08003from itertools import count
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
Jean-Paul Calderone63eab692014-01-18 10:19:56 -05009
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050010from OpenSSL._util import (
11 ffi as _ffi,
12 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050013 exception_from_error_queue as _exception_from_error_queue,
14 native as _native)
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080015
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080016from OpenSSL.crypto import (
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050017 FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080018
19_unspecified = object()
20
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -050021try:
22 _memoryview = memoryview
23except NameError:
24 class _memoryview(object):
25 pass
26
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050027OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
28SSLEAY_VERSION = _lib.SSLEAY_VERSION
29SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
30SSLEAY_PLATFORM = _lib.SSLEAY_PLATFORM
31SSLEAY_DIR = _lib.SSLEAY_DIR
32SSLEAY_BUILT_ON = _lib.SSLEAY_BUILT_ON
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080033
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050034SENT_SHUTDOWN = _lib.SSL_SENT_SHUTDOWN
35RECEIVED_SHUTDOWN = _lib.SSL_RECEIVED_SHUTDOWN
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080036
37SSLv2_METHOD = 1
38SSLv3_METHOD = 2
39SSLv23_METHOD = 3
40TLSv1_METHOD = 4
Jean-Paul Calderone56bff942013-11-03 11:30:43 -050041TLSv1_1_METHOD = 5
42TLSv1_2_METHOD = 6
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080043
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050044OP_NO_SSLv2 = _lib.SSL_OP_NO_SSLv2
45OP_NO_SSLv3 = _lib.SSL_OP_NO_SSLv3
46OP_NO_TLSv1 = _lib.SSL_OP_NO_TLSv1
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -050047
48OP_NO_TLSv1_1 = getattr(_lib, "SSL_OP_NO_TLSv1_1", 0)
49OP_NO_TLSv1_2 = getattr(_lib, "SSL_OP_NO_TLSv1_2", 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080050
Jean-Paul Calderone0d7e8a12014-01-08 16:54:13 -050051try:
52 MODE_RELEASE_BUFFERS = _lib.SSL_MODE_RELEASE_BUFFERS
53except AttributeError:
54 pass
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080055
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050056OP_SINGLE_DH_USE = _lib.SSL_OP_SINGLE_DH_USE
57OP_EPHEMERAL_RSA = _lib.SSL_OP_EPHEMERAL_RSA
58OP_MICROSOFT_SESS_ID_BUG = _lib.SSL_OP_MICROSOFT_SESS_ID_BUG
59OP_NETSCAPE_CHALLENGE_BUG = _lib.SSL_OP_NETSCAPE_CHALLENGE_BUG
60OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = _lib.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
61OP_SSLREF2_REUSE_CERT_TYPE_BUG = _lib.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
62OP_MICROSOFT_BIG_SSLV3_BUFFER = _lib.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
Jean-Paul Calderone0d7e8a12014-01-08 16:54:13 -050063try:
64 OP_MSIE_SSLV2_RSA_PADDING = _lib.SSL_OP_MSIE_SSLV2_RSA_PADDING
65except AttributeError:
66 pass
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050067OP_SSLEAY_080_CLIENT_DH_BUG = _lib.SSL_OP_SSLEAY_080_CLIENT_DH_BUG
68OP_TLS_D5_BUG = _lib.SSL_OP_TLS_D5_BUG
69OP_TLS_BLOCK_PADDING_BUG = _lib.SSL_OP_TLS_BLOCK_PADDING_BUG
70OP_DONT_INSERT_EMPTY_FRAGMENTS = _lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
71OP_CIPHER_SERVER_PREFERENCE = _lib.SSL_OP_CIPHER_SERVER_PREFERENCE
72OP_TLS_ROLLBACK_BUG = _lib.SSL_OP_TLS_ROLLBACK_BUG
73OP_PKCS1_CHECK_1 = _lib.SSL_OP_PKCS1_CHECK_1
74OP_PKCS1_CHECK_2 = _lib.SSL_OP_PKCS1_CHECK_2
75OP_NETSCAPE_CA_DN_BUG = _lib.SSL_OP_NETSCAPE_CA_DN_BUG
76OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG= _lib.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
Jean-Paul Calderonec1780342014-01-08 16:59:03 -050077try:
78 OP_NO_COMPRESSION = _lib.SSL_OP_NO_COMPRESSION
79except AttributeError:
80 pass
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080081
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050082OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
83OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
Arturo Filastò5f8c7a82014-03-09 20:01:25 +010084try:
85 OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
86except AttributeError:
87 pass
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080088
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050089OP_ALL = _lib.SSL_OP_ALL
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080090
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050091VERIFY_PEER = _lib.SSL_VERIFY_PEER
92VERIFY_FAIL_IF_NO_PEER_CERT = _lib.SSL_VERIFY_FAIL_IF_NO_PEER_CERT
93VERIFY_CLIENT_ONCE = _lib.SSL_VERIFY_CLIENT_ONCE
94VERIFY_NONE = _lib.SSL_VERIFY_NONE
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080095
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050096SESS_CACHE_OFF = _lib.SSL_SESS_CACHE_OFF
97SESS_CACHE_CLIENT = _lib.SSL_SESS_CACHE_CLIENT
98SESS_CACHE_SERVER = _lib.SSL_SESS_CACHE_SERVER
99SESS_CACHE_BOTH = _lib.SSL_SESS_CACHE_BOTH
100SESS_CACHE_NO_AUTO_CLEAR = _lib.SSL_SESS_CACHE_NO_AUTO_CLEAR
101SESS_CACHE_NO_INTERNAL_LOOKUP = _lib.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
102SESS_CACHE_NO_INTERNAL_STORE = _lib.SSL_SESS_CACHE_NO_INTERNAL_STORE
103SESS_CACHE_NO_INTERNAL = _lib.SSL_SESS_CACHE_NO_INTERNAL
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -0800104
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500105SSL_ST_CONNECT = _lib.SSL_ST_CONNECT
106SSL_ST_ACCEPT = _lib.SSL_ST_ACCEPT
107SSL_ST_MASK = _lib.SSL_ST_MASK
108SSL_ST_INIT = _lib.SSL_ST_INIT
109SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
110SSL_ST_OK = _lib.SSL_ST_OK
111SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800112
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500113SSL_CB_LOOP = _lib.SSL_CB_LOOP
114SSL_CB_EXIT = _lib.SSL_CB_EXIT
115SSL_CB_READ = _lib.SSL_CB_READ
116SSL_CB_WRITE = _lib.SSL_CB_WRITE
117SSL_CB_ALERT = _lib.SSL_CB_ALERT
118SSL_CB_READ_ALERT = _lib.SSL_CB_READ_ALERT
119SSL_CB_WRITE_ALERT = _lib.SSL_CB_WRITE_ALERT
120SSL_CB_ACCEPT_LOOP = _lib.SSL_CB_ACCEPT_LOOP
121SSL_CB_ACCEPT_EXIT = _lib.SSL_CB_ACCEPT_EXIT
122SSL_CB_CONNECT_LOOP = _lib.SSL_CB_CONNECT_LOOP
123SSL_CB_CONNECT_EXIT = _lib.SSL_CB_CONNECT_EXIT
124SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START
125SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800126
Jean-Paul Calderonef43678b2014-04-17 18:54:32 -0400127def _get_elliptic_curves(lib):
128 """
129 Load the names of the supported elliptic curves from OpenSSL.
130
131 :param lib: The OpenSSL library binding object.
132 :return: A set of :py:obj:`unicode` giving the names of the elliptic curves
133 the underlying library supports.
134 """
135 if lib.Cryptography_HAS_EC:
136 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
137 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
138 # The return value on this call should be num_curves again. We could
139 # check it to make sure but if it *isn't* then.. what could we do?
140 # Abort the whole process, I suppose...? -exarkun
141 lib.EC_get_builtin_curves(builtin_curves, num_curves)
142 return set(
143 _ffi.string(lib.OBJ_nid2sn(c.nid)).decode("ascii")
144 for c in builtin_curves)
145 else:
146 return set()
147
148ELLIPTIC_CURVES = _get_elliptic_curves()
149
Alex Gaynor12dc0842014-01-17 12:51:31 -0600150
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800151
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500152class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -0500153 """
154 An error occurred in an `OpenSSL.SSL` API.
155 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500156
157
158
159_raise_current_error = partial(_exception_from_error_queue, Error)
160
161
162class WantReadError(Error):
163 pass
164
165
166
167class WantWriteError(Error):
168 pass
169
170
171
172class WantX509LookupError(Error):
173 pass
174
175
176
177class ZeroReturnError(Error):
178 pass
179
180
181
182class SysCallError(Error):
183 pass
184
185
186
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800187class _VerifyHelper(object):
188 def __init__(self, connection, callback):
189 self._problems = []
190
191 @wraps(callback)
192 def wrapper(ok, store_ctx):
193 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500194 cert._x509 = _lib.X509_STORE_CTX_get_current_cert(store_ctx)
195 error_number = _lib.X509_STORE_CTX_get_error(store_ctx)
196 error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800197
198 try:
199 result = callback(connection, cert, error_number, error_depth, ok)
200 except Exception as e:
201 self._problems.append(e)
202 return 0
203 else:
204 if result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500205 _lib.X509_STORE_CTX_set_error(store_ctx, _lib.X509_V_OK)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800206 return 1
207 else:
208 return 0
209
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500210 self.callback = _ffi.callback(
211 "int (*)(int, X509_STORE_CTX *)", wrapper)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800212
213
214 def raise_if_problem(self):
215 if self._problems:
216 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500217 _raise_current_error()
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800218 except Error:
219 pass
220 raise self._problems.pop(0)
221
222
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800223
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800224def _asFileDescriptor(obj):
225 fd = None
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800226 if not isinstance(obj, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800227 meth = getattr(obj, "fileno", None)
228 if meth is not None:
229 obj = meth()
230
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800231 if isinstance(obj, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800232 fd = obj
233
Konstantinos Koukopoulosc8b13ea2014-01-28 00:21:50 -0800234 if not isinstance(fd, integer_types):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800235 raise TypeError("argument must be an int, or have a fileno() method.")
236 elif fd < 0:
237 raise ValueError(
238 "file descriptor cannot be a negative integer (%i)" % (fd,))
239
240 return fd
241
242
243
Andy Lutomirski61d7d392014-04-04 12:16:56 -0700244class ECNotAvailable(ValueError):
245 """
246 Raised if a request for an elliptic curve fails because OpenSSL
247 is compiled without elliptic curve support.
248 """
249 def __init__(self):
250 ValueError.__init__(self, "OpenSSL is compiled without EC support")
251
252
253
254class UnknownObject(ValueError):
255 """
256 Raised if OpenSSL does not recognize the requested object.
257 """
258 def __init__(self, sn):
259 ValueError.__init__(self, "OpenSSL does not recognize %r" % sn)
260 self.sn = sn
261
262
263
264class UnsupportedEllipticCurve(ValueError):
265 """
266 Raised if OpenSSL does not support the requested elliptic curve.
267 """
268 def __init__(self, sn):
269 ValueError.__init__(
270 self, "OpenSSL does not support the elliptic curve %r" % sn)
271 self.sn = sn
272
273
274
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -0800275def SSLeay_version(type):
276 """
277 Return a string describing the version of OpenSSL in use.
278
279 :param type: One of the SSLEAY_ constants defined in this module.
280 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500281 return _ffi.string(_lib.SSLeay_version(type))
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800282
283
284
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800285class Session(object):
286 pass
287
288
289
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800290class Context(object):
291 """
292 :py:obj:`OpenSSL.SSL.Context` instances define the parameters for setting up
293 new SSL connections.
294 """
295 _methods = {
Andrew Dunhamec84a0a2014-02-24 12:41:37 -0800296 SSLv2_METHOD: "SSLv2_method",
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500297 SSLv3_METHOD: "SSLv3_method",
298 SSLv23_METHOD: "SSLv23_method",
299 TLSv1_METHOD: "TLSv1_method",
300 TLSv1_1_METHOD: "TLSv1_1_method",
301 TLSv1_2_METHOD: "TLSv1_2_method",
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800302 }
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500303 _methods = dict(
304 (identifier, getattr(_lib, name))
305 for (identifier, name) in _methods.items()
306 if getattr(_lib, name, None) is not None)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800307
Jean-Paul Calderone63157872013-03-20 16:43:38 -0700308
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800309 def __init__(self, method):
310 """
311 :param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or
312 TLSv1_METHOD.
313 """
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500314 if not isinstance(method, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800315 raise TypeError("method must be an integer")
316
317 try:
318 method_func = self._methods[method]
319 except KeyError:
320 raise ValueError("No such protocol")
321
322 method_obj = method_func()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500323 if method_obj == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500324 # TODO: This is untested.
325 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800326
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500327 context = _lib.SSL_CTX_new(method_obj)
328 if context == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500329 # TODO: This is untested.
330 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500331 context = _ffi.gc(context, _lib.SSL_CTX_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800332
333 self._context = context
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800334 self._passphrase_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800335 self._passphrase_callback = None
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800336 self._passphrase_userdata = None
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800337 self._verify_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800338 self._verify_callback = None
339 self._info_callback = None
340 self._tlsext_servername_callback = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800341 self._app_data = None
342
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -0800343 # SSL_CTX_set_app_data(self->ctx, self);
344 # SSL_CTX_set_mode(self->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
345 # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
346 # SSL_MODE_AUTO_RETRY);
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500347 self.set_mode(_lib.SSL_MODE_ENABLE_PARTIAL_WRITE)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800348
349
350 def load_verify_locations(self, cafile, capath=None):
351 """
352 Let SSL know where we can find trusted certificates for the certificate
353 chain
354
355 :param cafile: In which file we can find the certificates
356 :param capath: In which directory we can find the certificates
357 :return: None
358 """
359 if cafile is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500360 cafile = _ffi.NULL
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800361 elif not isinstance(cafile, bytes):
362 raise TypeError("cafile must be None or a byte string")
363
364 if capath is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500365 capath = _ffi.NULL
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800366 elif not isinstance(capath, bytes):
367 raise TypeError("capath must be None or a byte string")
368
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500369 load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800370 if not load_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500371 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800372
373
374 def _wrap_callback(self, callback):
375 @wraps(callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800376 def wrapper(size, verify, userdata):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800377 return callback(size, verify, self._passphrase_userdata)
378 return _PassphraseHelper(
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800379 FILETYPE_PEM, wrapper, more_args=True, truncate=True)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800380
381
382 def set_passwd_cb(self, callback, userdata=None):
383 """
384 Set the passphrase callback
385
386 :param callback: The Python callback to use
387 :param userdata: (optional) A Python object which will be given as
388 argument to the callback
389 :return: None
390 """
391 if not callable(callback):
392 raise TypeError("callback must be callable")
393
394 self._passphrase_helper = self._wrap_callback(callback)
395 self._passphrase_callback = self._passphrase_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500396 _lib.SSL_CTX_set_default_passwd_cb(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800397 self._context, self._passphrase_callback)
398 self._passphrase_userdata = userdata
399
400
401 def set_default_verify_paths(self):
402 """
403 Use the platform-specific CA certificate locations
404
405 :return: None
406 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500407 set_result = _lib.SSL_CTX_set_default_verify_paths(self._context)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800408 if not set_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500409 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500410 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800411
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800412
413 def use_certificate_chain_file(self, certfile):
414 """
415 Load a certificate chain from a file
416
417 :param certfile: The name of the certificate chain file
418 :return: None
419 """
Jean-Paul Calderoned8607982014-01-18 10:30:55 -0500420 if isinstance(certfile, _text_type):
421 # Perhaps sys.getfilesystemencoding() could be better?
422 certfile = certfile.encode("utf-8")
423
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800424 if not isinstance(certfile, bytes):
Jean-Paul Calderoned8607982014-01-18 10:30:55 -0500425 raise TypeError("certfile must be bytes or unicode")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800426
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500427 result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800428 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500429 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800430
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800431
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800432 def use_certificate_file(self, certfile, filetype=FILETYPE_PEM):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800433 """
434 Load a certificate from a file
435
436 :param certfile: The name of the certificate file
437 :param filetype: (optional) The encoding of the file, default is PEM
438 :return: None
439 """
Jean-Paul Calderone684baf52014-01-18 10:31:19 -0500440 if isinstance(certfile, _text_type):
441 # Perhaps sys.getfilesystemencoding() could be better?
442 certfile = certfile.encode("utf-8")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800443 if not isinstance(certfile, bytes):
Jean-Paul Calderone684baf52014-01-18 10:31:19 -0500444 raise TypeError("certfile must be bytes or unicode")
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500445 if not isinstance(filetype, integer_types):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800446 raise TypeError("filetype must be an integer")
447
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500448 use_result = _lib.SSL_CTX_use_certificate_file(self._context, certfile, filetype)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800449 if not use_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500450 _raise_current_error()
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800451
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800452
453 def use_certificate(self, cert):
454 """
455 Load a certificate from a X509 object
456
457 :param cert: The X509 object
458 :return: None
459 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800460 if not isinstance(cert, X509):
461 raise TypeError("cert must be an X509 instance")
462
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500463 use_result = _lib.SSL_CTX_use_certificate(self._context, cert._x509)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800464 if not use_result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500465 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800466
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800467
468 def add_extra_chain_cert(self, certobj):
469 """
470 Add certificate to chain
471
472 :param certobj: The X509 certificate object to add to the chain
473 :return: None
474 """
475 if not isinstance(certobj, X509):
476 raise TypeError("certobj must be an X509 instance")
477
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500478 copy = _lib.X509_dup(certobj._x509)
479 add_result = _lib.SSL_CTX_add_extra_chain_cert(self._context, copy)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800480 if not add_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500481 # TODO: This is untested.
482 _lib.X509_free(copy)
483 _raise_current_error()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800484
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800485
486 def _raise_passphrase_exception(self):
487 if self._passphrase_helper is None:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500488 _raise_current_error()
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800489 exception = self._passphrase_helper.raise_if_problem(Error)
490 if exception is not None:
491 raise exception
492
493
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800494 def use_privatekey_file(self, keyfile, filetype=_unspecified):
495 """
496 Load a private key from a file
497
498 :param keyfile: The name of the key file
499 :param filetype: (optional) The encoding of the file, default is PEM
500 :return: None
501 """
Jean-Paul Calderone87e525a2014-01-18 10:31:51 -0500502 if isinstance(keyfile, _text_type):
503 # Perhaps sys.getfilesystemencoding() could be better?
504 keyfile = keyfile.encode("utf-8")
505
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800506 if not isinstance(keyfile, bytes):
507 raise TypeError("keyfile must be a byte string")
508
509 if filetype is _unspecified:
510 filetype = FILETYPE_PEM
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500511 elif not isinstance(filetype, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800512 raise TypeError("filetype must be an integer")
513
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500514 use_result = _lib.SSL_CTX_use_PrivateKey_file(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800515 self._context, keyfile, filetype)
516 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800517 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800518
519
520 def use_privatekey(self, pkey):
521 """
522 Load a private key from a PKey object
523
524 :param pkey: The PKey object
525 :return: None
526 """
527 if not isinstance(pkey, PKey):
528 raise TypeError("pkey must be a PKey instance")
529
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500530 use_result = _lib.SSL_CTX_use_PrivateKey(self._context, pkey._pkey)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800531 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800532 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800533
534
535 def check_privatekey(self):
536 """
537 Check that the private key and certificate match up
538
539 :return: None (raises an exception if something's wrong)
540 """
541
542 def load_client_ca(self, cafile):
543 """
544 Load the trusted certificates that will be sent to the client (basically
545 telling the client "These are the guys I trust"). Does not actually
546 imply any of the certificates are trusted; that must be configured
547 separately.
548
549 :param cafile: The name of the certificates file
550 :return: None
551 """
552
553 def set_session_id(self, buf):
554 """
555 Set the session identifier. This is needed if you want to do session
556 resumption.
557
558 :param buf: A Python object that can be safely converted to a string
559 :returns: None
560 """
561
562 def set_session_cache_mode(self, mode):
563 """
564 Enable/disable session caching and specify the mode used.
565
566 :param mode: One or more of the SESS_CACHE_* flags (combine using
567 bitwise or)
568 :returns: The previously set caching mode.
569 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500570 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800571 raise TypeError("mode must be an integer")
572
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500573 return _lib.SSL_CTX_set_session_cache_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800574
575
576 def get_session_cache_mode(self):
577 """
578 :returns: The currently used cache mode.
579 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500580 return _lib.SSL_CTX_get_session_cache_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800581
582
583 def set_verify(self, mode, callback):
584 """
585 Set the verify mode and verify callback
586
587 :param mode: The verify mode, this is either VERIFY_NONE or
588 VERIFY_PEER combined with possible other flags
589 :param callback: The Python callback to use
590 :return: None
591
592 See SSL_CTX_set_verify(3SSL) for further details.
593 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500594 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800595 raise TypeError("mode must be an integer")
596
597 if not callable(callback):
598 raise TypeError("callback must be callable")
599
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800600 self._verify_helper = _VerifyHelper(self, callback)
601 self._verify_callback = self._verify_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500602 _lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800603
604
605 def set_verify_depth(self, depth):
606 """
607 Set the verify depth
608
609 :param depth: An integer specifying the verify depth
610 :return: None
611 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500612 if not isinstance(depth, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800613 raise TypeError("depth must be an integer")
614
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500615 _lib.SSL_CTX_set_verify_depth(self._context, depth)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800616
617
618 def get_verify_mode(self):
619 """
620 Get the verify mode
621
622 :return: The verify mode
623 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500624 return _lib.SSL_CTX_get_verify_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800625
626
627 def get_verify_depth(self):
628 """
629 Get the verify depth
630
631 :return: The verify depth
632 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500633 return _lib.SSL_CTX_get_verify_depth(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800634
635
636 def load_tmp_dh(self, dhfile):
637 """
638 Load parameters for Ephemeral Diffie-Hellman
639
640 :param dhfile: The file to load EDH parameters from
641 :return: None
642 """
643 if not isinstance(dhfile, bytes):
644 raise TypeError("dhfile must be a byte string")
645
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500646 bio = _lib.BIO_new_file(dhfile, b"r")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500647 if bio == _ffi.NULL:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500648 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500649 bio = _ffi.gc(bio, _lib.BIO_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800650
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500651 dh = _lib.PEM_read_bio_DHparams(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
652 dh = _ffi.gc(dh, _lib.DH_free)
653 _lib.SSL_CTX_set_tmp_dh(self._context, dh)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800654
655
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -0400656 def _set_tmp_ecdh_curve_by_nid(self, name, nid):
Jean-Paul Calderonef11e3392014-04-17 16:30:12 -0400657 """
658 Select a curve to use by the OpenSSL NID associated with that curve.
659
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -0400660 :param name: The name of the curve identified by the NID.
661 :type name: str
662
Jean-Paul Calderonef11e3392014-04-17 16:30:12 -0400663 :param nid: The OpenSSL NID to use.
664 :type nid: int
665
666 :raise UnsupportedEllipticCurve: If the given NID does not identify a
667 supported curve.
668 """
669 ecdh = _lib.EC_KEY_new_by_curve_name(nid)
670 if ecdh == _ffi.NULL:
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -0400671 raise UnsupportedEllipticCurve(name)
Jean-Paul Calderonef11e3392014-04-17 16:30:12 -0400672 _lib.SSL_CTX_set_tmp_ecdh(self._context, ecdh)
673 _lib.EC_KEY_free(ecdh)
674
675
Andy Lutomirskif05a2732014-03-13 17:22:25 -0700676 def set_tmp_ecdh_curve(self, curve_name):
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600677 """
Andy Lutomirski76a61332014-03-12 15:02:56 -0700678 Select a curve to use for ECDHE key exchange.
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600679
Andy Lutomirskif05a2732014-03-13 17:22:25 -0700680 The valid values of *curve_name* are the keys in
681 :py:data:OpenSSL.SSL.ELLIPTIC_CURVE_DESCRIPTIONS.
682
Andy Lutomirski61d7d392014-04-04 12:16:56 -0700683 Raises a subclass of ``ValueError`` if the linked OpenSSL was
684 not compiled with elliptical curve support or the specified
685 curve is not available. You can check the specific subclass,
686 but, in general, you should just handle ``ValueError``.
Andy Lutomirskif05a2732014-03-13 17:22:25 -0700687
688 :param curve_name: The 'short name' of a curve, e.g. 'prime256v1'
689 :type curve_name: str
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600690 :return: None
691 """
692 if _lib.Cryptography_HAS_EC:
Andy Lutomirski5fb416a2014-04-04 12:19:52 -0700693 nid = _lib.OBJ_sn2nid(curve_name.encode('ascii'))
Andy Lutomirskif05a2732014-03-13 17:22:25 -0700694 if nid == _lib.NID_undef:
Andy Lutomirski61d7d392014-04-04 12:16:56 -0700695 raise UnknownObject(curve_name)
Jean-Paul Calderonec48cd812014-04-17 17:00:58 -0400696 return self._set_tmp_ecdh_curve_by_nid(curve_name, nid)
Jean-Paul Calderonef11e3392014-04-17 16:30:12 -0400697 raise ECNotAvailable()
Alex Gaynor7b8d57a2014-01-17 12:08:54 -0600698
699
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800700 def set_cipher_list(self, cipher_list):
701 """
702 Change the cipher list
703
704 :param cipher_list: A cipher list, see ciphers(1)
705 :return: None
706 """
Jean-Paul Calderone63eab692014-01-18 10:19:56 -0500707 if isinstance(cipher_list, _text_type):
708 cipher_list = cipher_list.encode("ascii")
709
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800710 if not isinstance(cipher_list, bytes):
Jean-Paul Calderone63eab692014-01-18 10:19:56 -0500711 raise TypeError("cipher_list must be bytes or unicode")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800712
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500713 result = _lib.SSL_CTX_set_cipher_list(self._context, cipher_list)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800714 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500715 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800716
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800717
718 def set_client_ca_list(self, certificate_authorities):
719 """
720 Set the list of preferred client certificate signers for this server context.
721
722 This list of certificate authorities will be sent to the client when the
723 server requests a client certificate.
724
725 :param certificate_authorities: a sequence of X509Names.
726 :return: None
727 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500728 name_stack = _lib.sk_X509_NAME_new_null()
729 if name_stack == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500730 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500731 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800732
733 try:
734 for ca_name in certificate_authorities:
735 if not isinstance(ca_name, X509Name):
736 raise TypeError(
737 "client CAs must be X509Name objects, not %s objects" % (
738 type(ca_name).__name__,))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500739 copy = _lib.X509_NAME_dup(ca_name._name)
740 if copy == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500741 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500742 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500743 push_result = _lib.sk_X509_NAME_push(name_stack, copy)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800744 if not push_result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500745 _lib.X509_NAME_free(copy)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500746 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800747 except:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 _lib.sk_X509_NAME_free(name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800749 raise
750
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500751 _lib.SSL_CTX_set_client_CA_list(self._context, name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800752
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800753
754 def add_client_ca(self, certificate_authority):
755 """
756 Add the CA certificate to the list of preferred signers for this context.
757
758 The list of certificate authorities will be sent to the client when the
759 server requests a client certificate.
760
761 :param certificate_authority: certificate authority's X509 certificate.
762 :return: None
763 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800764 if not isinstance(certificate_authority, X509):
765 raise TypeError("certificate_authority must be an X509 instance")
766
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500767 add_result = _lib.SSL_CTX_add_client_CA(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800768 self._context, certificate_authority._x509)
769 if not add_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500770 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500771 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800772
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800773
774 def set_timeout(self, timeout):
775 """
776 Set session timeout
777
778 :param timeout: The timeout in seconds
779 :return: The previous session timeout
780 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500781 if not isinstance(timeout, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800782 raise TypeError("timeout must be an integer")
783
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500784 return _lib.SSL_CTX_set_timeout(self._context, timeout)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800785
786
787 def get_timeout(self):
788 """
789 Get the session timeout
790
791 :return: The session timeout
792 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500793 return _lib.SSL_CTX_get_timeout(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800794
795
796 def set_info_callback(self, callback):
797 """
798 Set the info callback
799
800 :param callback: The Python callback to use
801 :return: None
802 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800803 @wraps(callback)
804 def wrapper(ssl, where, return_code):
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500805 callback(Connection._reverse_mapping[ssl], where, return_code)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500806 self._info_callback = _ffi.callback(
807 "void (*)(const SSL *, int, int)", wrapper)
808 _lib.SSL_CTX_set_info_callback(self._context, self._info_callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800809
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800810
811 def get_app_data(self):
812 """
813 Get the application data (supplied via set_app_data())
814
815 :return: The application data
816 """
817 return self._app_data
818
819
820 def set_app_data(self, data):
821 """
822 Set the application data (will be returned from get_app_data())
823
824 :param data: Any Python object
825 :return: None
826 """
827 self._app_data = data
828
829
830 def get_cert_store(self):
831 """
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500832 Get the certificate store for the context.
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800833
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500834 :return: A X509Store object or None if it does not have one.
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800835 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500836 store = _lib.SSL_CTX_get_cert_store(self._context)
837 if store == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500838 # TODO: This is untested.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800839 return None
840
841 pystore = X509Store.__new__(X509Store)
842 pystore._store = store
843 return pystore
844
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800845
846 def set_options(self, options):
847 """
848 Add options. Options set before are not cleared!
849
850 :param options: The options to add.
851 :return: The new option bitmask.
852 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500853 if not isinstance(options, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800854 raise TypeError("options must be an integer")
855
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500856 return _lib.SSL_CTX_set_options(self._context, options)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800857
858
859 def set_mode(self, mode):
860 """
861 Add modes via bitmask. Modes set before are not cleared!
862
863 :param mode: The mode to add.
864 :return: The new mode bitmask.
865 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500866 if not isinstance(mode, integer_types):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800867 raise TypeError("mode must be an integer")
868
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500869 return _lib.SSL_CTX_set_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800870
871
872 def set_tlsext_servername_callback(self, callback):
873 """
874 Specify a callback function to be called when clients specify a server name.
875
876 :param callback: The callback function. It will be invoked with one
877 argument, the Connection instance.
878 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800879 @wraps(callback)
880 def wrapper(ssl, alert, arg):
881 callback(Connection._reverse_mapping[ssl])
882 return 0
883
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500884 self._tlsext_servername_callback = _ffi.callback(
885 "int (*)(const SSL *, int *, void *)", wrapper)
886 _lib.SSL_CTX_set_tlsext_servername_callback(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800887 self._context, self._tlsext_servername_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800888
889ContextType = Context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800890
891
892
893class Connection(object):
894 """
895 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800896 _reverse_mapping = WeakValueDictionary()
897
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800898 def __init__(self, context, socket=None):
899 """
900 Create a new Connection object, using the given OpenSSL.SSL.Context
901 instance and socket.
902
903 :param context: An SSL Context to use for this connection
904 :param socket: The socket to use for transport layer
905 """
906 if not isinstance(context, Context):
907 raise TypeError("context must be a Context instance")
908
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 ssl = _lib.SSL_new(context._context)
910 self._ssl = _ffi.gc(ssl, _lib.SSL_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800911 self._context = context
912
913 self._reverse_mapping[self._ssl] = self
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800914
915 if socket is None:
916 self._socket = None
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -0800917 # Don't set up any gc for these, SSL_free will take care of them.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500918 self._into_ssl = _lib.BIO_new(_lib.BIO_s_mem())
919 self._from_ssl = _lib.BIO_new(_lib.BIO_s_mem())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800920
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500921 if self._into_ssl == _ffi.NULL or self._from_ssl == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500922 # TODO: This is untested.
923 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800924
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500925 _lib.SSL_set_bio(self._ssl, self._into_ssl, self._from_ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800926 else:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800927 self._into_ssl = None
928 self._from_ssl = None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800929 self._socket = socket
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500930 set_result = _lib.SSL_set_fd(self._ssl, _asFileDescriptor(self._socket))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800931 if not set_result:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500932 # TODO: This is untested.
933 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800934
935
936 def __getattr__(self, name):
937 """
938 Look up attributes on the wrapped socket object if they are not found on
939 the Connection object.
940 """
941 return getattr(self._socket, name)
942
943
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800944 def _raise_ssl_error(self, ssl, result):
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800945 if self._context._verify_helper is not None:
946 self._context._verify_helper.raise_if_problem()
947
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500948 error = _lib.SSL_get_error(ssl, result)
949 if error == _lib.SSL_ERROR_WANT_READ:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800950 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500951 elif error == _lib.SSL_ERROR_WANT_WRITE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700952 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500953 elif error == _lib.SSL_ERROR_ZERO_RETURN:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800954 raise ZeroReturnError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500955 elif error == _lib.SSL_ERROR_WANT_X509_LOOKUP:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500956 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700957 raise WantX509LookupError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500958 elif error == _lib.SSL_ERROR_SYSCALL:
959 if _lib.ERR_peek_error() == 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800960 if result < 0:
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +0200961 if platform == "win32":
962 errno = _ffi.getwinerror()[0]
963 else:
964 errno = _ffi.errno
965 raise SysCallError(errno, errorcode[errno])
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800966 else:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700967 raise SysCallError(-1, "Unexpected EOF")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800968 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -0500969 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500970 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500971 elif error == _lib.SSL_ERROR_NONE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700972 pass
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800973 else:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500974 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800975
976
977 def get_context(self):
978 """
979 Get session context
980 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800981 return self._context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800982
983
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800984 def set_context(self, context):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800985 """
986 Switch this connection to a new session context
987
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800988 :param context: A :py:class:`Context` instance giving the new session
989 context to use.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800990 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800991 if not isinstance(context, Context):
992 raise TypeError("context must be a Context instance")
993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500994 _lib.SSL_set_SSL_CTX(self._ssl, context._context)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800995 self._context = context
996
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800997
998 def get_servername(self):
999 """
1000 Retrieve the servername extension value if provided in the client hello
1001 message, or None if there wasn't one.
1002
1003 :return: A byte string giving the server name or :py:data:`None`.
1004 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001005 name = _lib.SSL_get_servername(self._ssl, _lib.TLSEXT_NAMETYPE_host_name)
1006 if name == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001007 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001008
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001009 return _ffi.string(name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001010
1011
1012 def set_tlsext_host_name(self, name):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001013 """
1014 Set the value of the servername extension to send in the client hello.
1015
1016 :param name: A byte string giving the name.
1017 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001018 if not isinstance(name, bytes):
1019 raise TypeError("name must be a byte string")
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001020 elif b"\0" in name:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001021 raise TypeError("name must not contain NUL byte")
1022
1023 # XXX I guess this can fail sometimes?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001024 _lib.SSL_set_tlsext_host_name(self._ssl, name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001025
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001026
1027 def pending(self):
1028 """
1029 Get the number of bytes that can be safely read from the connection
1030
1031 :return: The number of bytes available in the receive buffer.
1032 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001033 return _lib.SSL_pending(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001034
1035
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001036 def send(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001037 """
1038 Send data on the connection. NOTE: If you get one of the WantRead,
1039 WantWrite or WantX509Lookup exceptions on this, you have to call the
1040 method again with the SAME buffer.
1041
1042 :param buf: The string to send
1043 :param flags: (optional) Included for compatibility with the socket
1044 API, the value is ignored
1045 :return: The number of bytes written
1046 """
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -05001047 if isinstance(buf, _memoryview):
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -08001048 buf = buf.tobytes()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001049 if not isinstance(buf, bytes):
1050 raise TypeError("data must be a byte string")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001051
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001052 result = _lib.SSL_write(self._ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001053 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001054 return result
1055 write = send
1056
1057
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001058 def sendall(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001059 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001060 Send "all" data on the connection. This calls send() repeatedly until
1061 all data is sent. If an error occurs, it's impossible to tell how much
1062 data has been sent.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001063
1064 :param buf: The string to send
1065 :param flags: (optional) Included for compatibility with the socket
1066 API, the value is ignored
1067 :return: The number of bytes written
1068 """
Jean-Paul Calderone8fb53182013-12-30 08:35:49 -05001069 if isinstance(buf, _memoryview):
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -08001070 buf = buf.tobytes()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001071 if not isinstance(buf, bytes):
1072 raise TypeError("buf must be a byte string")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001073
1074 left_to_send = len(buf)
1075 total_sent = 0
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001076 data = _ffi.new("char[]", buf)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001077
1078 while left_to_send:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001079 result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001080 self._raise_ssl_error(self._ssl, result)
1081 total_sent += result
1082 left_to_send -= result
1083
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001084
1085 def recv(self, bufsiz, flags=None):
1086 """
1087 Receive data on the connection. NOTE: If you get one of the WantRead,
1088 WantWrite or WantX509Lookup exceptions on this, you have to call the
1089 method again with the SAME buffer.
1090
1091 :param bufsiz: The maximum number of bytes to read
1092 :param flags: (optional) Included for compatibility with the socket
1093 API, the value is ignored
1094 :return: The string read from the Connection
1095 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001096 buf = _ffi.new("char[]", bufsiz)
1097 result = _lib.SSL_read(self._ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001098 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001099 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001100 read = recv
1101
1102
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001103 def _handle_bio_errors(self, bio, result):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001104 if _lib.BIO_should_retry(bio):
1105 if _lib.BIO_should_read(bio):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001106 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001107 elif _lib.BIO_should_write(bio):
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001108 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001109 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001110 elif _lib.BIO_should_io_special(bio):
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001111 # TODO: This is untested. I think io_special means the socket
1112 # BIO has a not-yet connected socket.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001113 raise ValueError("BIO_should_io_special")
1114 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001115 # TODO: This is untested.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001116 raise ValueError("unknown bio failure")
1117 else:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001118 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001119 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001120
1121
1122 def bio_read(self, bufsiz):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001123 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001124 When using non-socket connections this function reads the "dirty" data
1125 that would have traveled away on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001126
1127 :param bufsiz: The maximum number of bytes to read
1128 :return: The string read.
1129 """
Jean-Paul Calderone97e041d2013-03-05 21:03:12 -08001130 if self._from_ssl is None:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001131 raise TypeError("Connection sock was not None")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001132
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001133 if not isinstance(bufsiz, integer_types):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001134 raise TypeError("bufsiz must be an integer")
1135
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001136 buf = _ffi.new("char[]", bufsiz)
1137 result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001138 if result <= 0:
1139 self._handle_bio_errors(self._from_ssl, result)
1140
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001141 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001142
1143
1144 def bio_write(self, buf):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001145 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001146 When using non-socket connections this function sends "dirty" data that
1147 would have traveled in on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001148
1149 :param buf: The string to put into the memory BIO.
1150 :return: The number of bytes written
1151 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001152 if self._into_ssl is None:
1153 raise TypeError("Connection sock was not None")
1154
1155 if not isinstance(buf, bytes):
1156 raise TypeError("buf must be a byte string")
1157
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001158 result = _lib.BIO_write(self._into_ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001159 if result <= 0:
1160 self._handle_bio_errors(self._into_ssl, result)
1161 return result
1162
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001163
1164 def renegotiate(self):
1165 """
1166 Renegotiate the session
1167
1168 :return: True if the renegotiation can be started, false otherwise
1169 """
1170
1171 def do_handshake(self):
1172 """
1173 Perform an SSL handshake (usually called after renegotiate() or one of
1174 set_*_state()). This can raise the same exceptions as send and recv.
1175
1176 :return: None.
1177 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001178 result = _lib.SSL_do_handshake(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001179 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001180
1181
1182 def renegotiate_pending(self):
1183 """
1184 Check if there's a renegotiation in progress, it will return false once
1185 a renegotiation is finished.
1186
1187 :return: Whether there's a renegotiation in progress
1188 """
1189
1190 def total_renegotiations(self):
1191 """
1192 Find out the total number of renegotiations.
1193
1194 :return: The number of renegotiations.
1195 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001196 return _lib.SSL_total_renegotiations(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001197
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001198
1199 def connect(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001200 """
1201 Connect to remote host and set up client-side SSL
1202
1203 :param addr: A remote address
1204 :return: What the socket's connect method returns
1205 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001206 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001207 return self._socket.connect(addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001208
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001209
1210 def connect_ex(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001211 """
1212 Connect to remote host and set up client-side SSL. Note that if the socket's
1213 connect_ex method doesn't return 0, SSL won't be initialized.
1214
1215 :param addr: A remove address
1216 :return: What the socket's connect_ex method returns
1217 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001218 connect_ex = self._socket.connect_ex
1219 self.set_connect_state()
1220 return connect_ex(addr)
1221
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001222
1223 def accept(self):
1224 """
1225 Accept incoming connection and set up SSL on it
1226
1227 :return: A (conn,addr) pair where conn is a Connection and addr is an
1228 address
1229 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001230 client, addr = self._socket.accept()
1231 conn = Connection(self._context, client)
1232 conn.set_accept_state()
1233 return (conn, addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001234
1235
1236 def bio_shutdown(self):
1237 """
1238 When using non-socket connections this function signals end of
1239 data on the input for this connection.
1240
1241 :return: None
1242 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001243 if self._from_ssl is None:
1244 raise TypeError("Connection sock was not None")
1245
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001246 _lib.BIO_set_mem_eof_return(self._into_ssl, 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001247
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001248
1249 def shutdown(self):
1250 """
1251 Send closure alert
1252
1253 :return: True if the shutdown completed successfully (i.e. both sides
1254 have sent closure alerts), false otherwise (i.e. you have to
1255 wait for a ZeroReturnError on a recv() method call
1256 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001257 result = _lib.SSL_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001258 if result < 0:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001259 # TODO: This is untested.
1260 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001261 elif result > 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001262 return True
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001263 else:
1264 return False
1265
1266
1267 def get_cipher_list(self):
1268 """
1269 Get the session cipher list
1270
1271 :return: A list of cipher strings
1272 """
1273 ciphers = []
1274 for i in count():
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001275 result = _lib.SSL_get_cipher_list(self._ssl, i)
1276 if result == _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001277 break
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001278 ciphers.append(_native(_ffi.string(result)))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001279 return ciphers
1280
1281
1282 def get_client_ca_list(self):
1283 """
1284 Get CAs whose certificates are suggested for client authentication.
1285
1286 :return: If this is a server connection, a list of X509Names representing
1287 the acceptable CAs as set by :py:meth:`OpenSSL.SSL.Context.set_client_ca_list` or
1288 :py:meth:`OpenSSL.SSL.Context.add_client_ca`. If this is a client connection,
1289 the list of such X509Names sent by the server, or an empty list if that
1290 has not yet happened.
1291 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001292 ca_names = _lib.SSL_get_client_CA_list(self._ssl)
1293 if ca_names == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001294 # TODO: This is untested.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001295 return []
1296
1297 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001298 for i in range(_lib.sk_X509_NAME_num(ca_names)):
1299 name = _lib.sk_X509_NAME_value(ca_names, i)
1300 copy = _lib.X509_NAME_dup(name)
1301 if copy == _ffi.NULL:
Jean-Paul Calderonea9f84ad2013-12-29 17:06:11 -05001302 # TODO: This is untested.
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001303 _raise_current_error()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001304
1305 pyname = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001306 pyname._name = _ffi.gc(copy, _lib.X509_NAME_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001307 result.append(pyname)
1308 return result
1309
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001310
1311 def makefile(self):
1312 """
1313 The makefile() method is not implemented, since there is no dup semantics
1314 for SSL connections
1315
Jean-Paul Calderone6749ec22014-04-17 16:30:21 -04001316 :raise: NotImplementedError
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001317 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001318 raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001319
1320
1321 def get_app_data(self):
1322 """
1323 Get application data
1324
1325 :return: The application data
1326 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001327 return self._app_data
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001328
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001329
1330 def set_app_data(self, data):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001331 """
1332 Set application data
1333
1334 :param data - The application data
1335 :return: None
1336 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001337 self._app_data = data
1338
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001339
1340 def get_shutdown(self):
1341 """
1342 Get shutdown state
1343
1344 :return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1345 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001346 return _lib.SSL_get_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001347
1348
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001349 def set_shutdown(self, state):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001350 """
1351 Set shutdown state
1352
1353 :param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1354 :return: None
1355 """
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05001356 if not isinstance(state, integer_types):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001357 raise TypeError("state must be an integer")
1358
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001359 _lib.SSL_set_shutdown(self._ssl, state)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001360
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001361
1362 def state_string(self):
1363 """
1364 Get a verbose state description
1365
1366 :return: A string representing the state
1367 """
1368
1369 def server_random(self):
1370 """
1371 Get a copy of the server hello nonce.
1372
1373 :return: A string representing the state
1374 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001375 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001376 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001377 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001378 self._ssl.s3.server_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001379 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001380
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001381
1382 def client_random(self):
1383 """
1384 Get a copy of the client hello nonce.
1385
1386 :return: A string representing the state
1387 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001388 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001389 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001390 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001391 self._ssl.s3.client_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001392 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001393
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001394
1395 def master_key(self):
1396 """
1397 Get a copy of the master key.
1398
1399 :return: A string representing the state
1400 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001401 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001402 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001403 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001404 self._ssl.session.master_key,
1405 self._ssl.session.master_key_length)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001407
1408 def sock_shutdown(self, *args, **kwargs):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001409 """
1410 See shutdown(2)
1411
1412 :return: What the socket's shutdown() method returns
1413 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001414 return self._socket.shutdown(*args, **kwargs)
1415
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001416
1417 def get_peer_certificate(self):
1418 """
1419 Retrieve the other side's certificate (if any)
1420
1421 :return: The peer's certificate
1422 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001423 cert = _lib.SSL_get_peer_certificate(self._ssl)
1424 if cert != _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001425 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001426 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001427 return pycert
1428 return None
1429
1430
1431 def get_peer_cert_chain(self):
1432 """
1433 Retrieve the other side's certificate (if any)
1434
1435 :return: A list of X509 instances giving the peer's certificate chain,
1436 or None if it does not have one.
1437 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001438 cert_stack = _lib.SSL_get_peer_cert_chain(self._ssl)
1439 if cert_stack == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001440 return None
1441
1442 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001443 for i in range(_lib.sk_X509_num(cert_stack)):
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -08001444 # TODO could incref instead of dup here
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001445 cert = _lib.X509_dup(_lib.sk_X509_value(cert_stack, i))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001446 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001447 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001448 result.append(pycert)
1449 return result
1450
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001451
1452 def want_read(self):
1453 """
1454 Checks if more data has to be read from the transport layer to complete an
1455 operation.
1456
1457 :return: True iff more data has to be read
1458 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001459 return _lib.SSL_want_read(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001460
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001461
1462 def want_write(self):
1463 """
1464 Checks if there is data to write to the transport layer to complete an
1465 operation.
1466
1467 :return: True iff there is data to write
1468 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001469 return _lib.SSL_want_write(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001470
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001471
1472 def set_accept_state(self):
1473 """
1474 Set the connection to work in server mode. The handshake will be handled
1475 automatically by read/write.
1476
1477 :return: None
1478 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001479 _lib.SSL_set_accept_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001480
1481
1482 def set_connect_state(self):
1483 """
1484 Set the connection to work in client mode. The handshake will be handled
1485 automatically by read/write.
1486
1487 :return: None
1488 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001489 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001490
1491
1492 def get_session(self):
1493 """
1494 Returns the Session currently used.
1495
1496 @return: An instance of :py:class:`OpenSSL.SSL.Session` or :py:obj:`None` if
1497 no session exists.
1498 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001499 session = _lib.SSL_get1_session(self._ssl)
1500 if session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001501 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001502
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001503 pysession = Session.__new__(Session)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001504 pysession._session = _ffi.gc(session, _lib.SSL_SESSION_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001505 return pysession
1506
1507
1508 def set_session(self, session):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001509 """
1510 Set the session to be used when the TLS/SSL connection is established.
1511
1512 :param session: A Session instance representing the session to use.
1513 :returns: None
1514 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001515 if not isinstance(session, Session):
1516 raise TypeError("session must be a Session instance")
1517
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001518 result = _lib.SSL_set_session(self._ssl, session._session)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001519 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001520 _raise_current_error()
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001521
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001522
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001523 def _get_finished_message(self, function):
1524 """
1525 Helper to implement :py:meth:`get_finished` and
1526 :py:meth:`get_peer_finished`.
1527
1528 :param function: Either :py:data:`SSL_get_finished`: or
1529 :py:data:`SSL_get_peer_finished`.
1530
1531 :return: :py:data:`None` if the desired message has not yet been
1532 received, otherwise the contents of the message.
1533 :rtype: :py:class:`bytes` or :py:class:`NoneType`
1534 """
Jean-Paul Calderone01af9042014-03-30 11:40:42 -04001535 # The OpenSSL documentation says nothing about what might happen if the
1536 # count argument given is zero. Specifically, it doesn't say whether
1537 # the output buffer may be NULL in that case or not. Inspection of the
1538 # implementation reveals that it calls memcpy() unconditionally.
1539 # Section 7.1.4, paragraph 1 of the C standard suggests that
1540 # memcpy(NULL, source, 0) is not guaranteed to produce defined (let
1541 # alone desirable) behavior (though it probably does on just about
1542 # every implementation...)
1543 #
1544 # Allocate a tiny buffer to pass in (instead of just passing NULL as
1545 # one might expect) for the initial call so as to be safe against this
1546 # potentially undefined behavior.
1547 empty = _ffi.new("char[]", 0)
1548 size = function(self._ssl, empty, 0)
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001549 if size == 0:
1550 # No Finished message so far.
1551 return None
1552
1553 buf = _ffi.new("char[]", size)
1554 function(self._ssl, buf, size)
1555 return _ffi.buffer(buf, size)[:]
1556
1557
Fedor Brunner5747b932014-03-05 14:22:34 +01001558 def get_finished(self):
1559 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001560 Obtain the latest `handshake finished` message sent to the peer.
Fedor Brunner5747b932014-03-05 14:22:34 +01001561
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001562 :return: The contents of the message or :py:obj:`None` if the TLS
1563 handshake has not yet completed.
1564 :rtype: :py:class:`bytes` or :py:class:`NoneType`
Fedor Brunner5747b932014-03-05 14:22:34 +01001565 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001566 return self._get_finished_message(_lib.SSL_get_finished)
1567
Fedor Brunner5747b932014-03-05 14:22:34 +01001568
1569 def get_peer_finished(self):
1570 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001571 Obtain the latest `handshake finished` message received from the peer.
Fedor Brunner5747b932014-03-05 14:22:34 +01001572
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001573 :return: The contents of the message or :py:obj:`None` if the TLS
1574 handshake has not yet completed.
1575 :rtype: :py:class:`bytes` or :py:class:`NoneType`
Fedor Brunner5747b932014-03-05 14:22:34 +01001576 """
Jean-Paul Calderoneac209562014-03-30 11:26:32 -04001577 return self._get_finished_message(_lib.SSL_get_peer_finished)
Fedor Brunner5747b932014-03-05 14:22:34 +01001578
Jean-Paul Calderone7c556ef2014-03-30 10:45:00 -04001579
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001580 def get_cipher_name(self):
1581 """
1582 Obtain the name of the currently used cipher.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001583
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001584 :returns: The name of the currently used cipher or :py:obj:`None`
1585 if no connection has been established.
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001586 :rtype: :py:class:`unicode` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001587 """
1588 cipher = _lib.SSL_get_current_cipher(self._ssl)
1589 if cipher == _ffi.NULL:
1590 return None
1591 else:
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001592 name = _ffi.string(_lib.SSL_CIPHER_get_name(cipher))
1593 return name.decode("utf-8")
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001594
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001595
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001596 def get_cipher_bits(self):
1597 """
1598 Obtain the number of secret bits of the currently used cipher.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001599
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001600 :returns: The number of secret bits of the currently used cipher
1601 or :py:obj:`None` if no connection has been established.
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001602 :rtype: :py:class:`int` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001603 """
1604 cipher = _lib.SSL_get_current_cipher(self._ssl)
1605 if cipher == _ffi.NULL:
1606 return None
1607 else:
1608 return _lib.SSL_CIPHER_get_bits(cipher, _ffi.NULL)
1609
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04001610
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001611 def get_cipher_version(self):
1612 """
Jean-Paul Calderone9e3ccd42014-03-29 18:13:36 -04001613 Obtain the protocol version of the currently used cipher.
1614
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001615 :returns: The protocol name of the currently used cipher
1616 or :py:obj:`None` if no connection has been established.
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001617 :rtype: :py:class:`unicode` or :py:class:`NoneType`
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001618 """
1619 cipher = _lib.SSL_get_current_cipher(self._ssl)
1620 if cipher == _ffi.NULL:
1621 return None
1622 else:
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04001623 version =_ffi.string(_lib.SSL_CIPHER_get_version(cipher))
1624 return version.decode("utf-8")
Fedor Brunnerd95014a2014-03-03 17:34:41 +01001625
1626
1627
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001628ConnectionType = Connection
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05001629
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05001630# This is similar to the initialization calls at the end of OpenSSL/crypto.py
1631# but is exercised mostly by the Context initializer.
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05001632_lib.SSL_library_init()