blob: 48c822745a298bd933a75887204e6e9cbcd2a049 [file] [log] [blame]
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -08001
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002from functools import wraps
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 Calderone6037d072013-12-28 18:04:00 -05007from cryptography.hazmat.backends.openssl import backend
8_ffi = backend.ffi
9_lib = backend.lib
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080010
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080011from OpenSSL.crypto import (
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080012 FILETYPE_PEM, _PassphraseHelper, PKey, X509Name, X509, X509Store,
13
14 _raise_current_error, _new_mem_buf)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -080015
16_unspecified = object()
17
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050018OPENSSL_VERSION_NUMBER = _lib.OPENSSL_VERSION_NUMBER
19SSLEAY_VERSION = _lib.SSLEAY_VERSION
20SSLEAY_CFLAGS = _lib.SSLEAY_CFLAGS
21SSLEAY_PLATFORM = _lib.SSLEAY_PLATFORM
22SSLEAY_DIR = _lib.SSLEAY_DIR
23SSLEAY_BUILT_ON = _lib.SSLEAY_BUILT_ON
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080024
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050025SENT_SHUTDOWN = _lib.SSL_SENT_SHUTDOWN
26RECEIVED_SHUTDOWN = _lib.SSL_RECEIVED_SHUTDOWN
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080027
28SSLv2_METHOD = 1
29SSLv3_METHOD = 2
30SSLv23_METHOD = 3
31TLSv1_METHOD = 4
Jean-Paul Calderone56bff942013-11-03 11:30:43 -050032TLSv1_1_METHOD = 5
33TLSv1_2_METHOD = 6
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080034
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050035OP_NO_SSLv2 = _lib.SSL_OP_NO_SSLv2
36OP_NO_SSLv3 = _lib.SSL_OP_NO_SSLv3
37OP_NO_TLSv1 = _lib.SSL_OP_NO_TLSv1
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -050038
39OP_NO_TLSv1_1 = getattr(_lib, "SSL_OP_NO_TLSv1_1", 0)
40OP_NO_TLSv1_2 = getattr(_lib, "SSL_OP_NO_TLSv1_2", 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080041
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050042MODE_RELEASE_BUFFERS = _lib.SSL_MODE_RELEASE_BUFFERS
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080043
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050044OP_SINGLE_DH_USE = _lib.SSL_OP_SINGLE_DH_USE
45OP_EPHEMERAL_RSA = _lib.SSL_OP_EPHEMERAL_RSA
46OP_MICROSOFT_SESS_ID_BUG = _lib.SSL_OP_MICROSOFT_SESS_ID_BUG
47OP_NETSCAPE_CHALLENGE_BUG = _lib.SSL_OP_NETSCAPE_CHALLENGE_BUG
48OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = _lib.SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
49OP_SSLREF2_REUSE_CERT_TYPE_BUG = _lib.SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
50OP_MICROSOFT_BIG_SSLV3_BUFFER = _lib.SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
51OP_MSIE_SSLV2_RSA_PADDING = getattr(_lib, "SSL_OP_MSIE_SSLV2_RSA_PADDING", 0)
52OP_SSLEAY_080_CLIENT_DH_BUG = _lib.SSL_OP_SSLEAY_080_CLIENT_DH_BUG
53OP_TLS_D5_BUG = _lib.SSL_OP_TLS_D5_BUG
54OP_TLS_BLOCK_PADDING_BUG = _lib.SSL_OP_TLS_BLOCK_PADDING_BUG
55OP_DONT_INSERT_EMPTY_FRAGMENTS = _lib.SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
56OP_CIPHER_SERVER_PREFERENCE = _lib.SSL_OP_CIPHER_SERVER_PREFERENCE
57OP_TLS_ROLLBACK_BUG = _lib.SSL_OP_TLS_ROLLBACK_BUG
58OP_PKCS1_CHECK_1 = _lib.SSL_OP_PKCS1_CHECK_1
59OP_PKCS1_CHECK_2 = _lib.SSL_OP_PKCS1_CHECK_2
60OP_NETSCAPE_CA_DN_BUG = _lib.SSL_OP_NETSCAPE_CA_DN_BUG
61OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG= _lib.SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
62OP_NO_COMPRESSION = _lib.SSL_OP_NO_COMPRESSION
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080063
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050064OP_NO_QUERY_MTU = _lib.SSL_OP_NO_QUERY_MTU
65OP_COOKIE_EXCHANGE = _lib.SSL_OP_COOKIE_EXCHANGE
66OP_NO_TICKET = _lib.SSL_OP_NO_TICKET
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080067
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050068OP_ALL = _lib.SSL_OP_ALL
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080069
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050070VERIFY_PEER = _lib.SSL_VERIFY_PEER
71VERIFY_FAIL_IF_NO_PEER_CERT = _lib.SSL_VERIFY_FAIL_IF_NO_PEER_CERT
72VERIFY_CLIENT_ONCE = _lib.SSL_VERIFY_CLIENT_ONCE
73VERIFY_NONE = _lib.SSL_VERIFY_NONE
Jean-Paul Calderone935d2da2013-03-04 08:11:19 -080074
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050075SESS_CACHE_OFF = _lib.SSL_SESS_CACHE_OFF
76SESS_CACHE_CLIENT = _lib.SSL_SESS_CACHE_CLIENT
77SESS_CACHE_SERVER = _lib.SSL_SESS_CACHE_SERVER
78SESS_CACHE_BOTH = _lib.SSL_SESS_CACHE_BOTH
79SESS_CACHE_NO_AUTO_CLEAR = _lib.SSL_SESS_CACHE_NO_AUTO_CLEAR
80SESS_CACHE_NO_INTERNAL_LOOKUP = _lib.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
81SESS_CACHE_NO_INTERNAL_STORE = _lib.SSL_SESS_CACHE_NO_INTERNAL_STORE
82SESS_CACHE_NO_INTERNAL = _lib.SSL_SESS_CACHE_NO_INTERNAL
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -080083
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050084SSL_ST_CONNECT = _lib.SSL_ST_CONNECT
85SSL_ST_ACCEPT = _lib.SSL_ST_ACCEPT
86SSL_ST_MASK = _lib.SSL_ST_MASK
87SSL_ST_INIT = _lib.SSL_ST_INIT
88SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
89SSL_ST_OK = _lib.SSL_ST_OK
90SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080091
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050092SSL_CB_LOOP = _lib.SSL_CB_LOOP
93SSL_CB_EXIT = _lib.SSL_CB_EXIT
94SSL_CB_READ = _lib.SSL_CB_READ
95SSL_CB_WRITE = _lib.SSL_CB_WRITE
96SSL_CB_ALERT = _lib.SSL_CB_ALERT
97SSL_CB_READ_ALERT = _lib.SSL_CB_READ_ALERT
98SSL_CB_WRITE_ALERT = _lib.SSL_CB_WRITE_ALERT
99SSL_CB_ACCEPT_LOOP = _lib.SSL_CB_ACCEPT_LOOP
100SSL_CB_ACCEPT_EXIT = _lib.SSL_CB_ACCEPT_EXIT
101SSL_CB_CONNECT_LOOP = _lib.SSL_CB_CONNECT_LOOP
102SSL_CB_CONNECT_EXIT = _lib.SSL_CB_CONNECT_EXIT
103SSL_CB_HANDSHAKE_START = _lib.SSL_CB_HANDSHAKE_START
104SSL_CB_HANDSHAKE_DONE = _lib.SSL_CB_HANDSHAKE_DONE
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800105
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800106
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800107class _VerifyHelper(object):
108 def __init__(self, connection, callback):
109 self._problems = []
110
111 @wraps(callback)
112 def wrapper(ok, store_ctx):
113 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500114 cert._x509 = _lib.X509_STORE_CTX_get_current_cert(store_ctx)
115 error_number = _lib.X509_STORE_CTX_get_error(store_ctx)
116 error_depth = _lib.X509_STORE_CTX_get_error_depth(store_ctx)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800117
118 try:
119 result = callback(connection, cert, error_number, error_depth, ok)
120 except Exception as e:
121 self._problems.append(e)
122 return 0
123 else:
124 if result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500125 _lib.X509_STORE_CTX_set_error(store_ctx, _lib.X509_V_OK)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800126 return 1
127 else:
128 return 0
129
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500130 self.callback = _ffi.callback(
131 "int (*)(int, X509_STORE_CTX *)", wrapper)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800132
133
134 def raise_if_problem(self):
135 if self._problems:
136 try:
137 _raise_current_error(Error)
138 except Error:
139 pass
140 raise self._problems.pop(0)
141
142
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800143
144class Error(Exception):
145 pass
146
147
148
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800149class WantReadError(Error):
150 pass
151
152
153
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700154class WantWriteError(Error):
155 pass
156
157
158
159class WantX509LookupError(Error):
160 pass
161
162
163
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800164class ZeroReturnError(Error):
165 pass
166
167
168class SysCallError(Error):
169 pass
170
171
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800172def _asFileDescriptor(obj):
173 fd = None
174
175 if not isinstance(obj, int):
176 meth = getattr(obj, "fileno", None)
177 if meth is not None:
178 obj = meth()
179
180 if isinstance(obj, int):
181 fd = obj
182
183 if not isinstance(fd, int):
184 raise TypeError("argument must be an int, or have a fileno() method.")
185 elif fd < 0:
186 raise ValueError(
187 "file descriptor cannot be a negative integer (%i)" % (fd,))
188
189 return fd
190
191
192
Jean-Paul Calderoned39a3f62013-03-04 12:23:51 -0800193def SSLeay_version(type):
194 """
195 Return a string describing the version of OpenSSL in use.
196
197 :param type: One of the SSLEAY_ constants defined in this module.
198 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500199 return _ffi.string(_lib.SSLeay_version(type))
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800200
201
202
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800203class Session(object):
204 pass
205
206
207
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800208class Context(object):
209 """
210 :py:obj:`OpenSSL.SSL.Context` instances define the parameters for setting up
211 new SSL connections.
212 """
213 _methods = {
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500214 SSLv3_METHOD: "SSLv3_method",
215 SSLv23_METHOD: "SSLv23_method",
216 TLSv1_METHOD: "TLSv1_method",
217 TLSv1_1_METHOD: "TLSv1_1_method",
218 TLSv1_2_METHOD: "TLSv1_2_method",
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800219 }
Jean-Paul Calderonebe2bb422013-12-29 07:34:08 -0500220 _methods = dict(
221 (identifier, getattr(_lib, name))
222 for (identifier, name) in _methods.items()
223 if getattr(_lib, name, None) is not None)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800224
Jean-Paul Calderone63157872013-03-20 16:43:38 -0700225
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800226 def __init__(self, method):
227 """
228 :param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or
229 TLSv1_METHOD.
230 """
231 if not isinstance(method, int):
232 raise TypeError("method must be an integer")
233
234 try:
235 method_func = self._methods[method]
236 except KeyError:
237 raise ValueError("No such protocol")
238
239 method_obj = method_func()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500240 if method_obj == _ffi.NULL:
Jean-Paul Calderone63157872013-03-20 16:43:38 -0700241 # XXX TODO what :(
242 1/0
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800243
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500244 context = _lib.SSL_CTX_new(method_obj)
245 if context == _ffi.NULL:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800246 1/0
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500247 context = _ffi.gc(context, _lib.SSL_CTX_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800248
249 self._context = context
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800250 self._passphrase_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800251 self._passphrase_callback = None
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800252 self._passphrase_userdata = None
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800253 self._verify_helper = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800254 self._verify_callback = None
255 self._info_callback = None
256 self._tlsext_servername_callback = None
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800257 self._app_data = None
258
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -0800259 # SSL_CTX_set_app_data(self->ctx, self);
260 # SSL_CTX_set_mode(self->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |
261 # SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
262 # SSL_MODE_AUTO_RETRY);
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500263 self.set_mode(_lib.SSL_MODE_ENABLE_PARTIAL_WRITE)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800264
265
266 def load_verify_locations(self, cafile, capath=None):
267 """
268 Let SSL know where we can find trusted certificates for the certificate
269 chain
270
271 :param cafile: In which file we can find the certificates
272 :param capath: In which directory we can find the certificates
273 :return: None
274 """
275 if cafile is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500276 cafile = _ffi.NULL
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800277 elif not isinstance(cafile, bytes):
278 raise TypeError("cafile must be None or a byte string")
279
280 if capath is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500281 capath = _ffi.NULL
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800282 elif not isinstance(capath, bytes):
283 raise TypeError("capath must be None or a byte string")
284
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500285 load_result = _lib.SSL_CTX_load_verify_locations(self._context, cafile, capath)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800286 if not load_result:
287 _raise_current_error(Error)
288
289
290 def _wrap_callback(self, callback):
291 @wraps(callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800292 def wrapper(size, verify, userdata):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800293 return callback(size, verify, self._passphrase_userdata)
294 return _PassphraseHelper(
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800295 FILETYPE_PEM, wrapper, more_args=True, truncate=True)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800296
297
298 def set_passwd_cb(self, callback, userdata=None):
299 """
300 Set the passphrase callback
301
302 :param callback: The Python callback to use
303 :param userdata: (optional) A Python object which will be given as
304 argument to the callback
305 :return: None
306 """
307 if not callable(callback):
308 raise TypeError("callback must be callable")
309
310 self._passphrase_helper = self._wrap_callback(callback)
311 self._passphrase_callback = self._passphrase_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500312 _lib.SSL_CTX_set_default_passwd_cb(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800313 self._context, self._passphrase_callback)
314 self._passphrase_userdata = userdata
315
316
317 def set_default_verify_paths(self):
318 """
319 Use the platform-specific CA certificate locations
320
321 :return: None
322 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500323 set_result = _lib.SSL_CTX_set_default_verify_paths(self._context)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800324 if not set_result:
325 1/0
326 _raise_current_error(Error)
327
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800328
329 def use_certificate_chain_file(self, certfile):
330 """
331 Load a certificate chain from a file
332
333 :param certfile: The name of the certificate chain file
334 :return: None
335 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800336 if not isinstance(certfile, bytes):
337 raise TypeError("certfile must be a byte string")
338
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500339 result = _lib.SSL_CTX_use_certificate_chain_file(self._context, certfile)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800340 if not result:
341 _raise_current_error(Error)
342
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800343
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800344 def use_certificate_file(self, certfile, filetype=FILETYPE_PEM):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800345 """
346 Load a certificate from a file
347
348 :param certfile: The name of the certificate file
349 :param filetype: (optional) The encoding of the file, default is PEM
350 :return: None
351 """
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800352 if not isinstance(certfile, bytes):
353 raise TypeError("certfile must be a byte string")
354 if not isinstance(filetype, int):
355 raise TypeError("filetype must be an integer")
356
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500357 use_result = _lib.SSL_CTX_use_certificate_file(self._context, certfile, filetype)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800358 if not use_result:
359 _raise_current_error(Error)
360
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800361
362 def use_certificate(self, cert):
363 """
364 Load a certificate from a X509 object
365
366 :param cert: The X509 object
367 :return: None
368 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800369 if not isinstance(cert, X509):
370 raise TypeError("cert must be an X509 instance")
371
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500372 use_result = _lib.SSL_CTX_use_certificate(self._context, cert._x509)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800373 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800374 _raise_current_error(Error)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800375
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800376
377 def add_extra_chain_cert(self, certobj):
378 """
379 Add certificate to chain
380
381 :param certobj: The X509 certificate object to add to the chain
382 :return: None
383 """
384 if not isinstance(certobj, X509):
385 raise TypeError("certobj must be an X509 instance")
386
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500387 copy = _lib.X509_dup(certobj._x509)
388 add_result = _lib.SSL_CTX_add_extra_chain_cert(self._context, copy)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800389 if not add_result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500390 # _lib.X509_free(copy)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800391 # _raise_current_error(Error)
392 1/0
393
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800394
395 def _raise_passphrase_exception(self):
396 if self._passphrase_helper is None:
397 _raise_current_error(Error)
398 exception = self._passphrase_helper.raise_if_problem(Error)
399 if exception is not None:
400 raise exception
401
402
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800403 def use_privatekey_file(self, keyfile, filetype=_unspecified):
404 """
405 Load a private key from a file
406
407 :param keyfile: The name of the key file
408 :param filetype: (optional) The encoding of the file, default is PEM
409 :return: None
410 """
411 if not isinstance(keyfile, bytes):
412 raise TypeError("keyfile must be a byte string")
413
414 if filetype is _unspecified:
415 filetype = FILETYPE_PEM
416 elif not isinstance(filetype, int):
417 raise TypeError("filetype must be an integer")
418
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500419 use_result = _lib.SSL_CTX_use_PrivateKey_file(
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800420 self._context, keyfile, filetype)
421 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800422 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800423
424
425 def use_privatekey(self, pkey):
426 """
427 Load a private key from a PKey object
428
429 :param pkey: The PKey object
430 :return: None
431 """
432 if not isinstance(pkey, PKey):
433 raise TypeError("pkey must be a PKey instance")
434
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500435 use_result = _lib.SSL_CTX_use_PrivateKey(self._context, pkey._pkey)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800436 if not use_result:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800437 self._raise_passphrase_exception()
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800438
439
440 def check_privatekey(self):
441 """
442 Check that the private key and certificate match up
443
444 :return: None (raises an exception if something's wrong)
445 """
446
447 def load_client_ca(self, cafile):
448 """
449 Load the trusted certificates that will be sent to the client (basically
450 telling the client "These are the guys I trust"). Does not actually
451 imply any of the certificates are trusted; that must be configured
452 separately.
453
454 :param cafile: The name of the certificates file
455 :return: None
456 """
457
458 def set_session_id(self, buf):
459 """
460 Set the session identifier. This is needed if you want to do session
461 resumption.
462
463 :param buf: A Python object that can be safely converted to a string
464 :returns: None
465 """
466
467 def set_session_cache_mode(self, mode):
468 """
469 Enable/disable session caching and specify the mode used.
470
471 :param mode: One or more of the SESS_CACHE_* flags (combine using
472 bitwise or)
473 :returns: The previously set caching mode.
474 """
475 if not isinstance(mode, int):
476 raise TypeError("mode must be an integer")
477
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500478 return _lib.SSL_CTX_set_session_cache_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800479
480
481 def get_session_cache_mode(self):
482 """
483 :returns: The currently used cache mode.
484 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500485 return _lib.SSL_CTX_get_session_cache_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800486
487
488 def set_verify(self, mode, callback):
489 """
490 Set the verify mode and verify callback
491
492 :param mode: The verify mode, this is either VERIFY_NONE or
493 VERIFY_PEER combined with possible other flags
494 :param callback: The Python callback to use
495 :return: None
496
497 See SSL_CTX_set_verify(3SSL) for further details.
498 """
499 if not isinstance(mode, int):
500 raise TypeError("mode must be an integer")
501
502 if not callable(callback):
503 raise TypeError("callback must be callable")
504
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800505 self._verify_helper = _VerifyHelper(self, callback)
506 self._verify_callback = self._verify_helper.callback
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500507 _lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800508
509
510 def set_verify_depth(self, depth):
511 """
512 Set the verify depth
513
514 :param depth: An integer specifying the verify depth
515 :return: None
516 """
517 if not isinstance(depth, int):
518 raise TypeError("depth must be an integer")
519
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500520 _lib.SSL_CTX_set_verify_depth(self._context, depth)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800521
522
523 def get_verify_mode(self):
524 """
525 Get the verify mode
526
527 :return: The verify mode
528 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500529 return _lib.SSL_CTX_get_verify_mode(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800530
531
532 def get_verify_depth(self):
533 """
534 Get the verify depth
535
536 :return: The verify depth
537 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500538 return _lib.SSL_CTX_get_verify_depth(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800539
540
541 def load_tmp_dh(self, dhfile):
542 """
543 Load parameters for Ephemeral Diffie-Hellman
544
545 :param dhfile: The file to load EDH parameters from
546 :return: None
547 """
548 if not isinstance(dhfile, bytes):
549 raise TypeError("dhfile must be a byte string")
550
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500551 bio = _lib.BIO_new_file(dhfile, "r")
552 if bio == _ffi.NULL:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800553 _raise_current_error(Error)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500554 bio = _ffi.gc(bio, _lib.BIO_free)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800555
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500556 dh = _lib.PEM_read_bio_DHparams(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
557 dh = _ffi.gc(dh, _lib.DH_free)
558 _lib.SSL_CTX_set_tmp_dh(self._context, dh)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800559
560
561 def set_cipher_list(self, cipher_list):
562 """
563 Change the cipher list
564
565 :param cipher_list: A cipher list, see ciphers(1)
566 :return: None
567 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800568 if not isinstance(cipher_list, bytes):
569 raise TypeError("cipher_list must be a byte string")
570
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500571 result = _lib.SSL_CTX_set_cipher_list(self._context, cipher_list)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800572 if not result:
573 _raise_current_error(Error)
574
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800575
576 def set_client_ca_list(self, certificate_authorities):
577 """
578 Set the list of preferred client certificate signers for this server context.
579
580 This list of certificate authorities will be sent to the client when the
581 server requests a client certificate.
582
583 :param certificate_authorities: a sequence of X509Names.
584 :return: None
585 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500586 name_stack = _lib.sk_X509_NAME_new_null()
587 if name_stack == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800588 1/0
589 _raise_current_error(Error)
590
591 try:
592 for ca_name in certificate_authorities:
593 if not isinstance(ca_name, X509Name):
594 raise TypeError(
595 "client CAs must be X509Name objects, not %s objects" % (
596 type(ca_name).__name__,))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500597 copy = _lib.X509_NAME_dup(ca_name._name)
598 if copy == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800599 1/0
600 _raise_current_error(Error)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500601 push_result = _lib.sk_X509_NAME_push(name_stack, copy)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800602 if not push_result:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500603 _lib.X509_NAME_free(copy)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800604 _raise_current_error(Error)
605 except:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500606 _lib.sk_X509_NAME_free(name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800607 raise
608
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500609 _lib.SSL_CTX_set_client_CA_list(self._context, name_stack)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800610
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800611
612 def add_client_ca(self, certificate_authority):
613 """
614 Add the CA certificate to the list of preferred signers for this context.
615
616 The list of certificate authorities will be sent to the client when the
617 server requests a client certificate.
618
619 :param certificate_authority: certificate authority's X509 certificate.
620 :return: None
621 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800622 if not isinstance(certificate_authority, X509):
623 raise TypeError("certificate_authority must be an X509 instance")
624
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500625 add_result = _lib.SSL_CTX_add_client_CA(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800626 self._context, certificate_authority._x509)
627 if not add_result:
628 1/0
629 _raise_current_error(Error)
630
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800631
632 def set_timeout(self, timeout):
633 """
634 Set session timeout
635
636 :param timeout: The timeout in seconds
637 :return: The previous session timeout
638 """
639 if not isinstance(timeout, int):
640 raise TypeError("timeout must be an integer")
641
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500642 return _lib.SSL_CTX_set_timeout(self._context, timeout)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800643
644
645 def get_timeout(self):
646 """
647 Get the session timeout
648
649 :return: The session timeout
650 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500651 return _lib.SSL_CTX_get_timeout(self._context)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800652
653
654 def set_info_callback(self, callback):
655 """
656 Set the info callback
657
658 :param callback: The Python callback to use
659 :return: None
660 """
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800661 @wraps(callback)
662 def wrapper(ssl, where, return_code):
663 callback(self, where, return_code)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500664 self._info_callback = _ffi.callback(
665 "void (*)(const SSL *, int, int)", wrapper)
666 _lib.SSL_CTX_set_info_callback(self._context, self._info_callback)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800667
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800668
669 def get_app_data(self):
670 """
671 Get the application data (supplied via set_app_data())
672
673 :return: The application data
674 """
675 return self._app_data
676
677
678 def set_app_data(self, data):
679 """
680 Set the application data (will be returned from get_app_data())
681
682 :param data: Any Python object
683 :return: None
684 """
685 self._app_data = data
686
687
688 def get_cert_store(self):
689 """
690 Get the certificate store for the context
691
692 :return: A X509Store object
693 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500694 store = _lib.SSL_CTX_get_cert_store(self._context)
695 if store == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800696 1/0
697 return None
698
699 pystore = X509Store.__new__(X509Store)
700 pystore._store = store
701 return pystore
702
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800703
704 def set_options(self, options):
705 """
706 Add options. Options set before are not cleared!
707
708 :param options: The options to add.
709 :return: The new option bitmask.
710 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800711 if not isinstance(options, int):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800712 raise TypeError("options must be an integer")
713
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500714 return _lib.SSL_CTX_set_options(self._context, options)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800715
716
717 def set_mode(self, mode):
718 """
719 Add modes via bitmask. Modes set before are not cleared!
720
721 :param mode: The mode to add.
722 :return: The new mode bitmask.
723 """
724 if not isinstance(mode, int):
725 raise TypeError("mode must be an integer")
726
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500727 return _lib.SSL_CTX_set_mode(self._context, mode)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800728
729
730 def set_tlsext_servername_callback(self, callback):
731 """
732 Specify a callback function to be called when clients specify a server name.
733
734 :param callback: The callback function. It will be invoked with one
735 argument, the Connection instance.
736 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800737 @wraps(callback)
738 def wrapper(ssl, alert, arg):
739 callback(Connection._reverse_mapping[ssl])
740 return 0
741
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500742 self._tlsext_servername_callback = _ffi.callback(
743 "int (*)(const SSL *, int *, void *)", wrapper)
744 _lib.SSL_CTX_set_tlsext_servername_callback(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800745 self._context, self._tlsext_servername_callback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800746
747ContextType = Context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800748
749
750
751class Connection(object):
752 """
753 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800754 _reverse_mapping = WeakValueDictionary()
755
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800756 def __init__(self, context, socket=None):
757 """
758 Create a new Connection object, using the given OpenSSL.SSL.Context
759 instance and socket.
760
761 :param context: An SSL Context to use for this connection
762 :param socket: The socket to use for transport layer
763 """
764 if not isinstance(context, Context):
765 raise TypeError("context must be a Context instance")
766
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500767 ssl = _lib.SSL_new(context._context)
768 self._ssl = _ffi.gc(ssl, _lib.SSL_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800769 self._context = context
770
771 self._reverse_mapping[self._ssl] = self
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800772
773 if socket is None:
774 self._socket = None
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -0800775 # Don't set up any gc for these, SSL_free will take care of them.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500776 self._into_ssl = _lib.BIO_new(_lib.BIO_s_mem())
777 self._from_ssl = _lib.BIO_new(_lib.BIO_s_mem())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800778
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500779 if self._into_ssl == _ffi.NULL or self._from_ssl == _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800780 1/0
781
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500782 _lib.SSL_set_bio(self._ssl, self._into_ssl, self._from_ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800783 else:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800784 self._into_ssl = None
785 self._from_ssl = None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800786 self._socket = socket
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500787 set_result = _lib.SSL_set_fd(self._ssl, _asFileDescriptor(self._socket))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800788 if not set_result:
789 1/0
790
791
792 def __getattr__(self, name):
793 """
794 Look up attributes on the wrapped socket object if they are not found on
795 the Connection object.
796 """
797 return getattr(self._socket, name)
798
799
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800800 def _raise_ssl_error(self, ssl, result):
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800801 if self._context._verify_helper is not None:
802 self._context._verify_helper.raise_if_problem()
803
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500804 error = _lib.SSL_get_error(ssl, result)
805 if error == _lib.SSL_ERROR_WANT_READ:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800806 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500807 elif error == _lib.SSL_ERROR_WANT_WRITE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700808 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500809 elif error == _lib.SSL_ERROR_ZERO_RETURN:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800810 raise ZeroReturnError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500811 elif error == _lib.SSL_ERROR_WANT_X509_LOOKUP:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700812 # TODO Untested
813 1/0
814 raise WantX509LookupError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500815 elif error == _lib.SSL_ERROR_SYSCALL:
816 if _lib.ERR_peek_error() == 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800817 if result < 0:
818 raise SysCallError(
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500819 _ffi.errno, errorcode[_ffi.errno])
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800820 else:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700821 raise SysCallError(-1, "Unexpected EOF")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800822 else:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700823 # TODO Untested
824 1/0
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800825 _raise_current_error(Error)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500826 elif error == _lib.SSL_ERROR_NONE:
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700827 pass
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800828 else:
829 _raise_current_error(Error)
830
831
832 def get_context(self):
833 """
834 Get session context
835 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800836 return self._context
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800837
838
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800839 def set_context(self, context):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800840 """
841 Switch this connection to a new session context
842
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800843 :param context: A :py:class:`Context` instance giving the new session
844 context to use.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800845 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800846 if not isinstance(context, Context):
847 raise TypeError("context must be a Context instance")
848
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500849 _lib.SSL_set_SSL_CTX(self._ssl, context._context)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800850 self._context = context
851
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800852
853 def get_servername(self):
854 """
855 Retrieve the servername extension value if provided in the client hello
856 message, or None if there wasn't one.
857
858 :return: A byte string giving the server name or :py:data:`None`.
859 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500860 name = _lib.SSL_get_servername(self._ssl, _lib.TLSEXT_NAMETYPE_host_name)
861 if name == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800862 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800863
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500864 return _ffi.string(name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800865
866
867 def set_tlsext_host_name(self, name):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800868 """
869 Set the value of the servername extension to send in the client hello.
870
871 :param name: A byte string giving the name.
872 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800873 if not isinstance(name, bytes):
874 raise TypeError("name must be a byte string")
875 elif "\0" in name:
876 raise TypeError("name must not contain NUL byte")
877
878 # XXX I guess this can fail sometimes?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500879 _lib.SSL_set_tlsext_host_name(self._ssl, name)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800880
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800881
882 def pending(self):
883 """
884 Get the number of bytes that can be safely read from the connection
885
886 :return: The number of bytes available in the receive buffer.
887 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500888 return _lib.SSL_pending(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800889
890
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800891 def send(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800892 """
893 Send data on the connection. NOTE: If you get one of the WantRead,
894 WantWrite or WantX509Lookup exceptions on this, you have to call the
895 method again with the SAME buffer.
896
897 :param buf: The string to send
898 :param flags: (optional) Included for compatibility with the socket
899 API, the value is ignored
900 :return: The number of bytes written
901 """
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -0800902 if isinstance(buf, memoryview):
903 buf = buf.tobytes()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800904 if not isinstance(buf, bytes):
905 raise TypeError("data must be a byte string")
906 if not isinstance(flags, int):
907 raise TypeError("flags must be an integer")
908
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 result = _lib.SSL_write(self._ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800910 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800911 return result
912 write = send
913
914
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800915 def sendall(self, buf, flags=0):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800916 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800917 Send "all" data on the connection. This calls send() repeatedly until
918 all data is sent. If an error occurs, it's impossible to tell how much
919 data has been sent.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800920
921 :param buf: The string to send
922 :param flags: (optional) Included for compatibility with the socket
923 API, the value is ignored
924 :return: The number of bytes written
925 """
Jean-Paul Calderone1aba4162013-03-05 18:50:00 -0800926 if isinstance(buf, memoryview):
927 buf = buf.tobytes()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800928 if not isinstance(buf, bytes):
929 raise TypeError("buf must be a byte string")
930 if not isinstance(flags, int):
931 raise TypeError("flags must be an integer")
932
933 left_to_send = len(buf)
934 total_sent = 0
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500935 data = _ffi.new("char[]", buf)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800936
937 while left_to_send:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500938 result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800939 self._raise_ssl_error(self._ssl, result)
940 total_sent += result
941 left_to_send -= result
942
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800943
944 def recv(self, bufsiz, flags=None):
945 """
946 Receive data on the connection. NOTE: If you get one of the WantRead,
947 WantWrite or WantX509Lookup exceptions on this, you have to call the
948 method again with the SAME buffer.
949
950 :param bufsiz: The maximum number of bytes to read
951 :param flags: (optional) Included for compatibility with the socket
952 API, the value is ignored
953 :return: The string read from the Connection
954 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500955 buf = _ffi.new("char[]", bufsiz)
956 result = _lib.SSL_read(self._ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800957 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500958 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800959 read = recv
960
961
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800962 def _handle_bio_errors(self, bio, result):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500963 if _lib.BIO_should_retry(bio):
964 if _lib.BIO_should_read(bio):
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800965 raise WantReadError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500966 elif _lib.BIO_should_write(bio):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700967 # TODO Untested
968 1/0
969 raise WantWriteError()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500970 elif _lib.BIO_should_io_special(bio):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700971 1/0
972 # TODO Untested. I think io_special means the socket BIO has a
973 # not-yet connected socket.
974 raise ValueError("BIO_should_io_special")
975 else:
976 1/0
977 # TODO Untested
978 raise ValueError("unknown bio failure")
979 else:
980 1/0
981 # TODO Untested
982 _raise_current_error(Error)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800983
984
985 def bio_read(self, bufsiz):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800986 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800987 When using non-socket connections this function reads the "dirty" data
988 that would have traveled away on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800989
990 :param bufsiz: The maximum number of bytes to read
991 :return: The string read.
992 """
Jean-Paul Calderone97e041d2013-03-05 21:03:12 -0800993 if self._from_ssl is None:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800994 raise TypeError("Connection sock was not None")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800995
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800996 if not isinstance(bufsiz, int):
997 raise TypeError("bufsiz must be an integer")
998
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500999 buf = _ffi.new("char[]", bufsiz)
1000 result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001001 if result <= 0:
1002 self._handle_bio_errors(self._from_ssl, result)
1003
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001004 return _ffi.buffer(buf, result)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001005
1006
1007 def bio_write(self, buf):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001008 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001009 When using non-socket connections this function sends "dirty" data that
1010 would have traveled in on the network.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001011
1012 :param buf: The string to put into the memory BIO.
1013 :return: The number of bytes written
1014 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001015 if self._into_ssl is None:
1016 raise TypeError("Connection sock was not None")
1017
1018 if not isinstance(buf, bytes):
1019 raise TypeError("buf must be a byte string")
1020
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001021 result = _lib.BIO_write(self._into_ssl, buf, len(buf))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001022 if result <= 0:
1023 self._handle_bio_errors(self._into_ssl, result)
1024 return result
1025
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001026
1027 def renegotiate(self):
1028 """
1029 Renegotiate the session
1030
1031 :return: True if the renegotiation can be started, false otherwise
1032 """
1033
1034 def do_handshake(self):
1035 """
1036 Perform an SSL handshake (usually called after renegotiate() or one of
1037 set_*_state()). This can raise the same exceptions as send and recv.
1038
1039 :return: None.
1040 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001041 result = _lib.SSL_do_handshake(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001042 self._raise_ssl_error(self._ssl, result)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001043
1044
1045 def renegotiate_pending(self):
1046 """
1047 Check if there's a renegotiation in progress, it will return false once
1048 a renegotiation is finished.
1049
1050 :return: Whether there's a renegotiation in progress
1051 """
1052
1053 def total_renegotiations(self):
1054 """
1055 Find out the total number of renegotiations.
1056
1057 :return: The number of renegotiations.
1058 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001059 return _lib.SSL_total_renegotiations(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001060
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001061
1062 def connect(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001063 """
1064 Connect to remote host and set up client-side SSL
1065
1066 :param addr: A remote address
1067 :return: What the socket's connect method returns
1068 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001069 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001070 return self._socket.connect(addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001071
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001072
1073 def connect_ex(self, addr):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001074 """
1075 Connect to remote host and set up client-side SSL. Note that if the socket's
1076 connect_ex method doesn't return 0, SSL won't be initialized.
1077
1078 :param addr: A remove address
1079 :return: What the socket's connect_ex method returns
1080 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001081 connect_ex = self._socket.connect_ex
1082 self.set_connect_state()
1083 return connect_ex(addr)
1084
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001085
1086 def accept(self):
1087 """
1088 Accept incoming connection and set up SSL on it
1089
1090 :return: A (conn,addr) pair where conn is a Connection and addr is an
1091 address
1092 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001093 client, addr = self._socket.accept()
1094 conn = Connection(self._context, client)
1095 conn.set_accept_state()
1096 return (conn, addr)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001097
1098
1099 def bio_shutdown(self):
1100 """
1101 When using non-socket connections this function signals end of
1102 data on the input for this connection.
1103
1104 :return: None
1105 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001106 if self._from_ssl is None:
1107 raise TypeError("Connection sock was not None")
1108
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001109 _lib.BIO_set_mem_eof_return(self._into_ssl, 0)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001110
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001111
1112 def shutdown(self):
1113 """
1114 Send closure alert
1115
1116 :return: True if the shutdown completed successfully (i.e. both sides
1117 have sent closure alerts), false otherwise (i.e. you have to
1118 wait for a ZeroReturnError on a recv() method call
1119 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001120 result = _lib.SSL_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001121 if result < 0:
1122 1/0
1123 elif result > 0:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001124 return True
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001125 else:
1126 return False
1127
1128
1129 def get_cipher_list(self):
1130 """
1131 Get the session cipher list
1132
1133 :return: A list of cipher strings
1134 """
1135 ciphers = []
1136 for i in count():
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001137 result = _lib.SSL_get_cipher_list(self._ssl, i)
1138 if result == _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001139 break
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001140 ciphers.append(_ffi.string(result))
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001141 return ciphers
1142
1143
1144 def get_client_ca_list(self):
1145 """
1146 Get CAs whose certificates are suggested for client authentication.
1147
1148 :return: If this is a server connection, a list of X509Names representing
1149 the acceptable CAs as set by :py:meth:`OpenSSL.SSL.Context.set_client_ca_list` or
1150 :py:meth:`OpenSSL.SSL.Context.add_client_ca`. If this is a client connection,
1151 the list of such X509Names sent by the server, or an empty list if that
1152 has not yet happened.
1153 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001154 ca_names = _lib.SSL_get_client_CA_list(self._ssl)
1155 if ca_names == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001156 1/0
1157 return []
1158
1159 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001160 for i in range(_lib.sk_X509_NAME_num(ca_names)):
1161 name = _lib.sk_X509_NAME_value(ca_names, i)
1162 copy = _lib.X509_NAME_dup(name)
1163 if copy == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001164 1/0
1165 _raise_current_error(Error)
1166
1167 pyname = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001168 pyname._name = _ffi.gc(copy, _lib.X509_NAME_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001169 result.append(pyname)
1170 return result
1171
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001172
1173 def makefile(self):
1174 """
1175 The makefile() method is not implemented, since there is no dup semantics
1176 for SSL connections
1177
1178 :raise NotImplementedError
1179 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001180 raise NotImplementedError("Cannot make file object of OpenSSL.SSL.Connection")
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001181
1182
1183 def get_app_data(self):
1184 """
1185 Get application data
1186
1187 :return: The application data
1188 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001189 return self._app_data
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001190
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001191
1192 def set_app_data(self, data):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001193 """
1194 Set application data
1195
1196 :param data - The application data
1197 :return: None
1198 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001199 self._app_data = data
1200
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001201
1202 def get_shutdown(self):
1203 """
1204 Get shutdown state
1205
1206 :return: The shutdown state, a bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1207 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001208 return _lib.SSL_get_shutdown(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001209
1210
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001211 def set_shutdown(self, state):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001212 """
1213 Set shutdown state
1214
1215 :param state - bitvector of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.
1216 :return: None
1217 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001218 if not isinstance(state, int):
1219 raise TypeError("state must be an integer")
1220
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001221 _lib.SSL_set_shutdown(self._ssl, state)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001222
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001223
1224 def state_string(self):
1225 """
1226 Get a verbose state description
1227
1228 :return: A string representing the state
1229 """
1230
1231 def server_random(self):
1232 """
1233 Get a copy of the server hello nonce.
1234
1235 :return: A string representing the state
1236 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001237 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001238 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001239 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001240 self._ssl.s3.server_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001241 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001242
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001243
1244 def client_random(self):
1245 """
1246 Get a copy of the client hello nonce.
1247
1248 :return: A string representing the state
1249 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001250 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001251 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001252 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001253 self._ssl.s3.client_random,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001254 _lib.SSL3_RANDOM_SIZE)[:]
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001255
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001256
1257 def master_key(self):
1258 """
1259 Get a copy of the master key.
1260
1261 :return: A string representing the state
1262 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001263 if self._ssl.session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001264 return None
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001265 return _ffi.buffer(
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001266 self._ssl.session.master_key,
1267 self._ssl.session.master_key_length)[:]
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001268
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001269
1270 def sock_shutdown(self, *args, **kwargs):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001271 """
1272 See shutdown(2)
1273
1274 :return: What the socket's shutdown() method returns
1275 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001276 return self._socket.shutdown(*args, **kwargs)
1277
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001278
1279 def get_peer_certificate(self):
1280 """
1281 Retrieve the other side's certificate (if any)
1282
1283 :return: The peer's certificate
1284 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001285 cert = _lib.SSL_get_peer_certificate(self._ssl)
1286 if cert != _ffi.NULL:
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001287 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001288 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001289 return pycert
1290 return None
1291
1292
1293 def get_peer_cert_chain(self):
1294 """
1295 Retrieve the other side's certificate (if any)
1296
1297 :return: A list of X509 instances giving the peer's certificate chain,
1298 or None if it does not have one.
1299 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001300 cert_stack = _lib.SSL_get_peer_cert_chain(self._ssl)
1301 if cert_stack == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001302 return None
1303
1304 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001305 for i in range(_lib.sk_X509_num(cert_stack)):
Jean-Paul Calderone73b15c22013-03-05 18:30:39 -08001306 # TODO could incref instead of dup here
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001307 cert = _lib.X509_dup(_lib.sk_X509_value(cert_stack, i))
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001308 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001309 pycert._x509 = _ffi.gc(cert, _lib.X509_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001310 result.append(pycert)
1311 return result
1312
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001313
1314 def want_read(self):
1315 """
1316 Checks if more data has to be read from the transport layer to complete an
1317 operation.
1318
1319 :return: True iff more data has to be read
1320 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001321 return _lib.SSL_want_read(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001322
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001323
1324 def want_write(self):
1325 """
1326 Checks if there is data to write to the transport layer to complete an
1327 operation.
1328
1329 :return: True iff there is data to write
1330 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001331 return _lib.SSL_want_write(self._ssl)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001332
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001333
1334 def set_accept_state(self):
1335 """
1336 Set the connection to work in server mode. The handshake will be handled
1337 automatically by read/write.
1338
1339 :return: None
1340 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001341 _lib.SSL_set_accept_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001342
1343
1344 def set_connect_state(self):
1345 """
1346 Set the connection to work in client mode. The handshake will be handled
1347 automatically by read/write.
1348
1349 :return: None
1350 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001351 _lib.SSL_set_connect_state(self._ssl)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001352
1353
1354 def get_session(self):
1355 """
1356 Returns the Session currently used.
1357
1358 @return: An instance of :py:class:`OpenSSL.SSL.Session` or :py:obj:`None` if
1359 no session exists.
1360 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001361 session = _lib.SSL_get1_session(self._ssl)
1362 if session == _ffi.NULL:
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001363 return None
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001364
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001365 pysession = Session.__new__(Session)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001366 pysession._session = _ffi.gc(session, _lib.SSL_SESSION_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001367 return pysession
1368
1369
1370 def set_session(self, session):
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001371 """
1372 Set the session to be used when the TLS/SSL connection is established.
1373
1374 :param session: A Session instance representing the session to use.
1375 :returns: None
1376 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001377 if not isinstance(session, Session):
1378 raise TypeError("session must be a Session instance")
1379
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001380 result = _lib.SSL_set_session(self._ssl, session._session)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001381 if not result:
1382 _raise_current_error(Error)
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001383
1384ConnectionType = Connection