[Python-ideas] Expose reasons for SSL/TLS cert verification failures
Chi Hsuan Yen
yan12125 at gmail.com
Fri Sep 9 06:23:48 EDT 2016
Hi Python enthusiasts,
Currently _ssl.c always reports CERTIFICATE_VERIFY_FAILED for any
certification verification errors. In OpenSSL, it's possible to tell from
different reasons that lead to CERTIFICATE_VERIFY_FAILED. For example,
https://expired.badssl.com/ reports X509_V_ERR_CERT_HAS_EXPIRED, and
https://self-signed.badssl.com/ reports
X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT. Seems CPython does not expose such
information yet? I hope it can be added to CPython. For example, creating a
new exception class SSLCertificateError, which is a subclass of SSLError,
that provides error codes like X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT. Any
ideas?
The attachment is a naive try to printf some information about a
verification failure. It's just a proof-of-concept and does not provide any
practical advantage :)
Best,
Yen Chi Hsuan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160909/f43afa28/attachment.html>
-------------- next part --------------
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -2770,16 +2770,24 @@ get_verify_mode(PySSLContext *self, void
case SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT:
return PyLong_FromLong(PY_SSL_CERT_REQUIRED);
}
PyErr_SetString(PySSLErrorObject,
"invalid return value from SSL_CTX_get_verify_mode");
return NULL;
}
+static int verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+ long x509_err = X509_STORE_CTX_get_error(ctx);
+ printf("ok = %d, err = %ld, errstr = %s\n", ok, x509_err,
+ X509_verify_cert_error_string(x509_err));
+ return ok;
+}
+
static int
set_verify_mode(PySSLContext *self, PyObject *arg, void *c)
{
int n, mode;
if (!PyArg_Parse(arg, "i", &n))
return -1;
if (n == PY_SSL_CERT_NONE)
mode = SSL_VERIFY_NONE;
@@ -2794,16 +2802,22 @@ set_verify_mode(PySSLContext *self, PyOb
}
if (mode == SSL_VERIFY_NONE && self->check_hostname) {
PyErr_SetString(PyExc_ValueError,
"Cannot set verify_mode to CERT_NONE when "
"check_hostname is enabled.");
return -1;
}
SSL_CTX_set_verify(self->ctx, mode, NULL);
+
+ {
+ X509_STORE *store = SSL_CTX_get_cert_store(self->ctx);
+ X509_STORE_set_verify_cb(store, verify_cb);
+ }
+
return 0;
}
static PyObject *
get_verify_flags(PySSLContext *self, void *c)
{
X509_STORE *store;
X509_VERIFY_PARAM *param;
More information about the Python-ideas
mailing list