Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 4572751..d1f7900 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -52,6 +52,14 @@
#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"
@@ -87,6 +95,10 @@
/* 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
*/
@@ -110,6 +122,70 @@
# define HAVE_ALPN
#endif
+#ifndef INVALID_SOCKET /* MS defines this */
+#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 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,
@@ -140,7 +216,7 @@
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,
@@ -681,7 +757,7 @@
/* 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);
@@ -698,7 +774,7 @@
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);
@@ -801,18 +877,18 @@
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 */
@@ -1021,13 +1097,11 @@
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;
@@ -1443,9 +1517,9 @@
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 PyBytes_FromString(short_name);
@@ -1994,7 +2068,7 @@
{
char *kwlist[] = {"protocol", NULL};
PySSLContext *self;
- int proto_version = PY_SSL_VERSION_SSL23;
+ int proto_version = PY_SSL_VERSION_TLS;
long options;
SSL_CTX *ctx = NULL;
@@ -2020,8 +2094,8 @@
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
@@ -2067,8 +2141,9 @@
#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
{
@@ -2336,10 +2411,12 @@
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);
}
@@ -2347,22 +2424,24 @@
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;
}
@@ -2537,8 +2616,8 @@
char *kwlist[] = {"certfile", "keyfile", "password", NULL};
PyObject *keyfile = NULL, *keyfile_bytes = NULL, *password = NULL;
char *certfile_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;
@@ -2674,8 +2753,9 @@
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;
@@ -3160,25 +3240,24 @@
cert_store_stats(PySSLContext *self)
{
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
@@ -3204,6 +3283,7 @@
char *kwlist[] = {"binary_form", NULL};
X509_STORE *store;
PyObject *ci = NULL, *rlist = NULL, *py_binary_mode = Py_False;
+ STACK_OF(X509_OBJECT) *objs;
int i;
int binary_mode = 0;
@@ -3221,17 +3301,18 @@
}
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;
}
@@ -3842,10 +3923,12 @@
};
-#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;
@@ -3926,7 +4009,7 @@
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\
@@ -3979,11 +4062,16 @@
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;
}
+#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 */
@@ -4136,7 +4224,9 @@
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