-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Description
Python's ssl module uses ssl.SSLContext objects are central configuration objects for all TLS related options. The C code behind the SSLContext object is mostly a wrapper of SSL_CTX.
A while ago I added a setter/getter for X509_CHECK_FLAG_NEVER_CHECK_SUBJECT flag.
@property
def hostname_checks_common_name(self):
ncs = self._host_flags & _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT
return ncs != _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT
@hostname_checks_common_name.setter
def hostname_checks_common_name(self, value):
if value:
self._host_flags &= ~_ssl.HOSTFLAG_NEVER_CHECK_SUBJECT
else:
self._host_flags |= _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT```static int
set_host_flags(PySSLContext *self, PyObject *arg, void *c)
{
X509_VERIFY_PARAM *param;
unsigned int new_flags = 0;
if (!PyArg_Parse(arg, "I", &new_flags))
return -1;
param = SSL_CTX_get0_param(self->ctx);
self->hostflags = new_flags;
X509_VERIFY_PARAM_set_hostflags(param, new_flags);
return 0;
}The code correctly sets ctx->params->hostflags to value 36 (X509_CHECK_FLAG_NEVER_CHECK_SUBJECT|X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS). However it doesn't have any affect on SSLSocket ssl->params->hostflags is always 0 and TLS handshake accepts certificate with just a subject CN and no SAN DNS entries. It took me a while to realize that hostflags are not copied from SSL_CTX to SSL. X509_VERIFY_PARAM_inherit() ignores the hostflags when there is no verify hosts configured. Python's ssl module uses X509_VERIFY_PARAM_set1_host() only on connection objects, never on the context itself. ctx->params->hosts is always NULL.
openssl/crypto/x509/x509_vpm.c
Lines 202 to 213 in 081a706
| /* Copy the host flags if and only if we're copying the host list */ | |
| if (test_x509_verify_param_copy(hosts, NULL)) { | |
| sk_OPENSSL_STRING_pop_free(dest->hosts, str_free); | |
| dest->hosts = NULL; | |
| if (src->hosts) { | |
| dest->hosts = | |
| sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); | |
| if (dest->hosts == NULL) | |
| return 0; | |
| dest->hostflags = src->hostflags; | |
| } | |
| } |
This behavior is surprising. I assumed that hostflags behave like any other flag. I don't see the special case documented at https://www.openssl.org/docs/man1.1.1/man3/X509_VERIFY_PARAM_set_flags.html either.
Version: OpenSSL 1.1.1j
Python upstream bug: https://bugs.python.org/issue43522
workaround PR: python/cpython#24899