|
|
|
@ -55,6 +55,14 @@ static PySocketModule_APIObject PySocketModule; |
|
|
|
#include <sys/poll.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Don't warn about deprecated functions */ |
|
|
|
#ifdef __GNUC__ |
|
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
|
|
|
#endif |
|
|
|
#ifdef __clang__ |
|
|
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations" |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Include OpenSSL header files */ |
|
|
|
#include "openssl/rsa.h" |
|
|
|
#include "openssl/crypto.h" |
|
|
|
@ -91,6 +99,10 @@ struct py_ssl_library_code { |
|
|
|
/* Include generated data (error codes) */ |
|
|
|
#include "_ssl_data.h" |
|
|
|
|
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) |
|
|
|
# define OPENSSL_VERSION_1_1 1 |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Openssl comes with TLSv1.1 and TLSv1.2 between 1.0.0h and 1.0.1 |
|
|
|
http://www.openssl.org/news/changelog.html |
|
|
|
*/ |
|
|
|
@ -117,6 +129,72 @@ struct py_ssl_library_code { |
|
|
|
#define INVALID_SOCKET (-1) |
|
|
|
#endif |
|
|
|
|
|
|
|
#ifdef OPENSSL_VERSION_1_1 |
|
|
|
/* OpenSSL 1.1.0+ */ |
|
|
|
#ifndef OPENSSL_NO_SSL2 |
|
|
|
#define OPENSSL_NO_SSL2 |
|
|
|
#endif |
|
|
|
#else /* OpenSSL < 1.1.0 */ |
|
|
|
#if defined(WITH_THREAD) |
|
|
|
#define HAVE_OPENSSL_CRYPTO_LOCK |
|
|
|
#endif |
|
|
|
|
|
|
|
#define TLS_method SSLv23_method |
|
|
|
|
|
|
|
static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) |
|
|
|
{ |
|
|
|
return ne->set; |
|
|
|
} |
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_COMP |
|
|
|
static int COMP_get_type(const COMP_METHOD *meth) |
|
|
|
{ |
|
|
|
return meth->type; |
|
|
|
} |
|
|
|
|
|
|
|
static const char *COMP_get_name(const COMP_METHOD *meth) |
|
|
|
{ |
|
|
|
return meth->name; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) |
|
|
|
{ |
|
|
|
return ctx->default_passwd_callback; |
|
|
|
} |
|
|
|
|
|
|
|
static void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) |
|
|
|
{ |
|
|
|
return ctx->default_passwd_callback_userdata; |
|
|
|
} |
|
|
|
|
|
|
|
static int X509_OBJECT_get_type(X509_OBJECT *x) |
|
|
|
{ |
|
|
|
return x->type; |
|
|
|
} |
|
|
|
|
|
|
|
static X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) |
|
|
|
{ |
|
|
|
return x->data.x509; |
|
|
|
} |
|
|
|
|
|
|
|
static int BIO_up_ref(BIO *b) |
|
|
|
{ |
|
|
|
CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
static STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) { |
|
|
|
return store->objs; |
|
|
|
} |
|
|
|
|
|
|
|
static X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store) |
|
|
|
{ |
|
|
|
return store->param; |
|
|
|
} |
|
|
|
#endif /* OpenSSL < 1.1.0 or LibreSSL */ |
|
|
|
|
|
|
|
|
|
|
|
enum py_ssl_error { |
|
|
|
/* these mirror ssl.h */ |
|
|
|
PY_SSL_ERROR_NONE, |
|
|
|
@ -147,7 +225,7 @@ enum py_ssl_cert_requirements { |
|
|
|
enum py_ssl_version { |
|
|
|
PY_SSL_VERSION_SSL2, |
|
|
|
PY_SSL_VERSION_SSL3=1, |
|
|
|
PY_SSL_VERSION_SSL23, |
|
|
|
PY_SSL_VERSION_TLS, |
|
|
|
#if HAVE_TLSv1_2 |
|
|
|
PY_SSL_VERSION_TLS1, |
|
|
|
PY_SSL_VERSION_TLS1_1, |
|
|
|
@ -527,8 +605,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, |
|
|
|
/* BIOs are reference counted and SSL_set_bio borrows our reference. |
|
|
|
* To prevent a double free in memory_bio_dealloc() we need to take an |
|
|
|
* extra reference here. */ |
|
|
|
CRYPTO_add(&inbio->bio->references, 1, CRYPTO_LOCK_BIO); |
|
|
|
CRYPTO_add(&outbio->bio->references, 1, CRYPTO_LOCK_BIO); |
|
|
|
BIO_up_ref(inbio->bio); |
|
|
|
BIO_up_ref(outbio->bio); |
|
|
|
SSL_set_bio(self->ssl, inbio->bio, outbio->bio); |
|
|
|
} |
|
|
|
mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; |
|
|
|
@ -738,7 +816,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname) |
|
|
|
|
|
|
|
/* check to see if we've gotten to a new RDN */ |
|
|
|
if (rdn_level >= 0) { |
|
|
|
if (rdn_level != entry->set) { |
|
|
|
if (rdn_level != X509_NAME_ENTRY_set(entry)) { |
|
|
|
/* yes, new RDN */ |
|
|
|
/* add old RDN to DN */ |
|
|
|
rdnt = PyList_AsTuple(rdn); |
|
|
|
@ -755,7 +833,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname) |
|
|
|
goto fail0; |
|
|
|
} |
|
|
|
} |
|
|
|
rdn_level = entry->set; |
|
|
|
rdn_level = X509_NAME_ENTRY_set(entry); |
|
|
|
|
|
|
|
/* now add this attribute to the current RDN */ |
|
|
|
name = X509_NAME_ENTRY_get_object(entry); |
|
|
|
@ -853,18 +931,18 @@ _get_peer_alt_names (X509 *certificate) { |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
p = ext->value->data; |
|
|
|
p = X509_EXTENSION_get_data(ext)->data; |
|
|
|
if (method->it) |
|
|
|
names = (GENERAL_NAMES*) |
|
|
|
(ASN1_item_d2i(NULL, |
|
|
|
&p, |
|
|
|
ext->value->length, |
|
|
|
X509_EXTENSION_get_data(ext)->length, |
|
|
|
ASN1_ITEM_ptr(method->it))); |
|
|
|
else |
|
|
|
names = (GENERAL_NAMES*) |
|
|
|
(method->d2i(NULL, |
|
|
|
&p, |
|
|
|
ext->value->length)); |
|
|
|
X509_EXTENSION_get_data(ext)->length)); |
|
|
|
|
|
|
|
for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { |
|
|
|
/* get a rendering of each name in the set of names */ |
|
|
|
@ -1075,13 +1153,11 @@ _get_crl_dp(X509 *certificate) { |
|
|
|
int i, j; |
|
|
|
PyObject *lst, *res = NULL; |
|
|
|
|
|
|
|
#if OPENSSL_VERSION_NUMBER < 0x10001000L |
|
|
|
dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL); |
|
|
|
#else |
|
|
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L |
|
|
|
/* Calls x509v3_cache_extensions and sets up crldp */ |
|
|
|
X509_check_ca(certificate); |
|
|
|
dps = certificate->crldp; |
|
|
|
#endif |
|
|
|
dps = X509_get_ext_d2i(certificate, NID_crl_distribution_points, NULL, NULL); |
|
|
|
|
|
|
|
if (dps == NULL) |
|
|
|
return Py_None; |
|
|
|
@ -1451,14 +1527,13 @@ static PyObject * |
|
|
|
_ssl__SSLSocket_shared_ciphers_impl(PySSLSocket *self) |
|
|
|
/*[clinic end generated code: output=3d174ead2e42c4fd input=0bfe149da8fe6306]*/ |
|
|
|
{ |
|
|
|
SSL_SESSION *sess = SSL_get_session(self->ssl); |
|
|
|
STACK_OF(SSL_CIPHER) *ciphers; |
|
|
|
int i; |
|
|
|
PyObject *res; |
|
|
|
|
|
|
|
if (!sess || !sess->ciphers) |
|
|
|
ciphers = SSL_get_ciphers(self->ssl); |
|
|
|
if (!ciphers) |
|
|
|
Py_RETURN_NONE; |
|
|
|
ciphers = sess->ciphers; |
|
|
|
res = PyList_New(sk_SSL_CIPHER_num(ciphers)); |
|
|
|
if (!res) |
|
|
|
return NULL; |
|
|
|
@ -1567,9 +1642,9 @@ _ssl__SSLSocket_compression_impl(PySSLSocket *self) |
|
|
|
if (self->ssl == NULL) |
|
|
|
Py_RETURN_NONE; |
|
|
|
comp_method = SSL_get_current_compression(self->ssl); |
|
|
|
if (comp_method == NULL || comp_method->type == NID_undef) |
|
|
|
if (comp_method == NULL || COMP_get_type(comp_method) == NID_undef) |
|
|
|
Py_RETURN_NONE; |
|
|
|
short_name = OBJ_nid2sn(comp_method->type); |
|
|
|
short_name = COMP_get_name(comp_method); |
|
|
|
if (short_name == NULL) |
|
|
|
Py_RETURN_NONE; |
|
|
|
return PyUnicode_DecodeFSDefault(short_name); |
|
|
|
@ -2255,8 +2330,8 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) |
|
|
|
else if (proto_version == PY_SSL_VERSION_SSL2) |
|
|
|
ctx = SSL_CTX_new(SSLv2_method()); |
|
|
|
#endif |
|
|
|
else if (proto_version == PY_SSL_VERSION_SSL23) |
|
|
|
ctx = SSL_CTX_new(SSLv23_method()); |
|
|
|
else if (proto_version == PY_SSL_VERSION_TLS) |
|
|
|
ctx = SSL_CTX_new(TLS_method()); |
|
|
|
else |
|
|
|
proto_version = -1; |
|
|
|
PySSL_END_ALLOW_THREADS |
|
|
|
@ -2318,8 +2393,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) |
|
|
|
#ifndef OPENSSL_NO_ECDH |
|
|
|
/* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use |
|
|
|
prime256v1 by default. This is Apache mod_ssl's initialization |
|
|
|
policy, so we should be safe. */ |
|
|
|
#if defined(SSL_CTX_set_ecdh_auto) |
|
|
|
policy, so we should be safe. OpenSSL 1.1 has it enabled by default. |
|
|
|
*/ |
|
|
|
#if defined(SSL_CTX_set_ecdh_auto) && !defined(OPENSSL_VERSION_1_1) |
|
|
|
SSL_CTX_set_ecdh_auto(self->ctx, 1); |
|
|
|
#else |
|
|
|
{ |
|
|
|
@ -2586,10 +2662,12 @@ static PyObject * |
|
|
|
get_verify_flags(PySSLContext *self, void *c) |
|
|
|
{ |
|
|
|
X509_STORE *store; |
|
|
|
X509_VERIFY_PARAM *param; |
|
|
|
unsigned long flags; |
|
|
|
|
|
|
|
store = SSL_CTX_get_cert_store(self->ctx); |
|
|
|
flags = X509_VERIFY_PARAM_get_flags(store->param); |
|
|
|
param = X509_STORE_get0_param(store); |
|
|
|
flags = X509_VERIFY_PARAM_get_flags(param); |
|
|
|
return PyLong_FromUnsignedLong(flags); |
|
|
|
} |
|
|
|
|
|
|
|
@ -2597,22 +2675,24 @@ static int |
|
|
|
set_verify_flags(PySSLContext *self, PyObject *arg, void *c) |
|
|
|
{ |
|
|
|
X509_STORE *store; |
|
|
|
X509_VERIFY_PARAM *param; |
|
|
|
unsigned long new_flags, flags, set, clear; |
|
|
|
|
|
|
|
if (!PyArg_Parse(arg, "k", &new_flags)) |
|
|
|
return -1; |
|
|
|
store = SSL_CTX_get_cert_store(self->ctx); |
|
|
|
flags = X509_VERIFY_PARAM_get_flags(store->param); |
|
|
|
param = X509_STORE_get0_param(store); |
|
|
|
flags = X509_VERIFY_PARAM_get_flags(param); |
|
|
|
clear = flags & ~new_flags; |
|
|
|
set = ~flags & new_flags; |
|
|
|
if (clear) { |
|
|
|
if (!X509_VERIFY_PARAM_clear_flags(store->param, clear)) { |
|
|
|
if (!X509_VERIFY_PARAM_clear_flags(param, clear)) { |
|
|
|
_setSSLError(NULL, 0, __FILE__, __LINE__); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
if (set) { |
|
|
|
if (!X509_VERIFY_PARAM_set_flags(store->param, set)) { |
|
|
|
if (!X509_VERIFY_PARAM_set_flags(param, set)) { |
|
|
|
_setSSLError(NULL, 0, __FILE__, __LINE__); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
@ -2789,8 +2869,8 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, |
|
|
|
/*[clinic end generated code: output=9480bc1c380e2095 input=7cf9ac673cbee6fc]*/ |
|
|
|
{ |
|
|
|
PyObject *certfile_bytes = NULL, *keyfile_bytes = NULL; |
|
|
|
pem_password_cb *orig_passwd_cb = self->ctx->default_passwd_callback; |
|
|
|
void *orig_passwd_userdata = self->ctx->default_passwd_callback_userdata; |
|
|
|
pem_password_cb *orig_passwd_cb = SSL_CTX_get_default_passwd_cb(self->ctx); |
|
|
|
void *orig_passwd_userdata = SSL_CTX_get_default_passwd_cb_userdata(self->ctx); |
|
|
|
_PySSLPasswordInfo pw_info = { NULL, NULL, NULL, 0, 0 }; |
|
|
|
int r; |
|
|
|
|
|
|
|
@ -2917,8 +2997,9 @@ _add_ca_certs(PySSLContext *self, void *data, Py_ssize_t len, |
|
|
|
cert = d2i_X509_bio(biobuf, NULL); |
|
|
|
} else { |
|
|
|
cert = PEM_read_bio_X509(biobuf, NULL, |
|
|
|
self->ctx->default_passwd_callback, |
|
|
|
self->ctx->default_passwd_callback_userdata); |
|
|
|
SSL_CTX_get_default_passwd_cb(self->ctx), |
|
|
|
SSL_CTX_get_default_passwd_cb_userdata(self->ctx) |
|
|
|
); |
|
|
|
} |
|
|
|
if (cert == NULL) { |
|
|
|
break; |
|
|
|
@ -3444,25 +3525,24 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self) |
|
|
|
/*[clinic end generated code: output=5f356f4d9cca874d input=eb40dd0f6d0e40cf]*/ |
|
|
|
{ |
|
|
|
X509_STORE *store; |
|
|
|
STACK_OF(X509_OBJECT) *objs; |
|
|
|
X509_OBJECT *obj; |
|
|
|
int x509 = 0, crl = 0, pkey = 0, ca = 0, i; |
|
|
|
int x509 = 0, crl = 0, ca = 0, i; |
|
|
|
|
|
|
|
store = SSL_CTX_get_cert_store(self->ctx); |
|
|
|
for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { |
|
|
|
obj = sk_X509_OBJECT_value(store->objs, i); |
|
|
|
switch (obj->type) { |
|
|
|
objs = X509_STORE_get0_objects(store); |
|
|
|
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { |
|
|
|
obj = sk_X509_OBJECT_value(objs, i); |
|
|
|
switch (X509_OBJECT_get_type(obj)) { |
|
|
|
case X509_LU_X509: |
|
|
|
x509++; |
|
|
|
if (X509_check_ca(obj->data.x509)) { |
|
|
|
if (X509_check_ca(X509_OBJECT_get0_X509(obj))) { |
|
|
|
ca++; |
|
|
|
} |
|
|
|
break; |
|
|
|
case X509_LU_CRL: |
|
|
|
crl++; |
|
|
|
break; |
|
|
|
case X509_LU_PKEY: |
|
|
|
pkey++; |
|
|
|
break; |
|
|
|
default: |
|
|
|
/* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY. |
|
|
|
* As far as I can tell they are internal states and never |
|
|
|
@ -3492,6 +3572,7 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) |
|
|
|
/*[clinic end generated code: output=0d58f148f37e2938 input=6887b5a09b7f9076]*/ |
|
|
|
{ |
|
|
|
X509_STORE *store; |
|
|
|
STACK_OF(X509_OBJECT) *objs; |
|
|
|
PyObject *ci = NULL, *rlist = NULL; |
|
|
|
int i; |
|
|
|
|
|
|
|
@ -3500,17 +3581,18 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) |
|
|
|
} |
|
|
|
|
|
|
|
store = SSL_CTX_get_cert_store(self->ctx); |
|
|
|
for (i = 0; i < sk_X509_OBJECT_num(store->objs); i++) { |
|
|
|
objs = X509_STORE_get0_objects(store); |
|
|
|
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { |
|
|
|
X509_OBJECT *obj; |
|
|
|
X509 *cert; |
|
|
|
|
|
|
|
obj = sk_X509_OBJECT_value(store->objs, i); |
|
|
|
if (obj->type != X509_LU_X509) { |
|
|
|
obj = sk_X509_OBJECT_value(objs, i); |
|
|
|
if (X509_OBJECT_get_type(obj) != X509_LU_X509) { |
|
|
|
/* not a x509 cert */ |
|
|
|
continue; |
|
|
|
} |
|
|
|
/* CA for any purpose */ |
|
|
|
cert = obj->data.x509; |
|
|
|
cert = X509_OBJECT_get0_X509(obj); |
|
|
|
if (!X509_check_ca(cert)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
@ -4374,10 +4456,12 @@ static PyMethodDef PySSL_methods[] = { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_THREAD |
|
|
|
#ifdef HAVE_OPENSSL_CRYPTO_LOCK |
|
|
|
|
|
|
|
/* an implementation of OpenSSL threading operations in terms |
|
|
|
of the Python C thread library */ |
|
|
|
* of the Python C thread library |
|
|
|
* Only used up to 1.0.2. OpenSSL 1.1.0+ has its own locking code. |
|
|
|
*/ |
|
|
|
|
|
|
|
static PyThread_type_lock *_ssl_locks = NULL; |
|
|
|
|
|
|
|
@ -4458,7 +4542,7 @@ static int _setup_ssl_threads(void) { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
#endif /* def HAVE_THREAD */ |
|
|
|
#endif /* HAVE_OPENSSL_CRYPTO_LOCK for WITH_THREAD && OpenSSL < 1.1.0 */ |
|
|
|
|
|
|
|
PyDoc_STRVAR(module_doc, |
|
|
|
"Implementation module for SSL socket operations. See the socket module\n\ |
|
|
|
@ -4527,11 +4611,16 @@ PyInit__ssl(void) |
|
|
|
SSL_load_error_strings(); |
|
|
|
SSL_library_init(); |
|
|
|
#ifdef WITH_THREAD |
|
|
|
#ifdef HAVE_OPENSSL_CRYPTO_LOCK |
|
|
|
/* note that this will start threading if not already started */ |
|
|
|
if (!_setup_ssl_threads()) { |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
#elif OPENSSL_VERSION_1_1 && defined(OPENSSL_THREADS) |
|
|
|
/* OpenSSL 1.1.0 builtin thread support is enabled */ |
|
|
|
_ssl_locks_count++; |
|
|
|
#endif |
|
|
|
#endif /* WITH_THREAD */ |
|
|
|
OpenSSL_add_all_algorithms(); |
|
|
|
|
|
|
|
/* Add symbols to module dict */ |
|
|
|
@ -4678,7 +4767,9 @@ PyInit__ssl(void) |
|
|
|
PY_SSL_VERSION_SSL3); |
|
|
|
#endif |
|
|
|
PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", |
|
|
|
PY_SSL_VERSION_SSL23); |
|
|
|
PY_SSL_VERSION_TLS); |
|
|
|
PyModule_AddIntConstant(m, "PROTOCOL_TLS", |
|
|
|
PY_SSL_VERSION_TLS); |
|
|
|
PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", |
|
|
|
PY_SSL_VERSION_TLS1); |
|
|
|
#if HAVE_TLSv1_2 |
|
|
|
|