diff options
author | Barry Warsaw <barry@python.org> | 2013-08-23 17:26:49 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 2013-08-23 17:26:49 (GMT) |
commit | 82f88283171933127f20f866a7f98694b29cca56 (patch) | |
tree | 85f872fa42b336a9f739035e25007978d777f9ba /Modules | |
parent | f880e5d5eaef3233fb1cd2f747c8f0ba59c7f086 (diff) | |
download | cpython-82f88283171933127f20f866a7f98694b29cca56.zip cpython-82f88283171933127f20f866a7f98694b29cca56.tar.gz cpython-82f88283171933127f20f866a7f98694b29cca56.tar.bz2 |
- Issue #18709: Fix CVE-2013-4238. The SSL module now handles NULL bytes
inside subjectAltName correctly. Formerly the module has used OpenSSL's
GENERAL_NAME_print() function to get the string represention of ASN.1
strings for `rfc822Name` (email), `dNSName` (DNS) and
`uniformResourceIdentifier` (URI).
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ssl.c | 64 |
1 files changed, 61 insertions, 3 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 46f71e8..a045be4 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -302,8 +302,10 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ +#ifndef OPENSSL_NO_SSL2 else if (proto_version == PY_SSL_VERSION_SSL2) self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ +#endif else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -718,8 +720,13 @@ _get_peer_alt_names (X509 *certificate) { /* get a rendering of each name in the set of names */ + int gntype; + ASN1_STRING *as = NULL; + name = sk_GENERAL_NAME_value(names, j); - if (name->type == GEN_DIRNAME) { + gntype = name-> type; + switch (gntype) { + case GEN_DIRNAME: /* we special-case DirName as a tuple of tuples of attributes */ @@ -741,11 +748,61 @@ _get_peer_alt_names (X509 *certificate) { goto fail; } PyTuple_SET_ITEM(t, 1, v); + break; - } else { + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + /* GENERAL_NAME_print() doesn't handle NUL bytes in ASN1_string + correctly. */ + t = PyTuple_New(2); + if (t == NULL) + goto fail; + switch (gntype) { + case GEN_EMAIL: + v = PyUnicode_FromString("email"); + as = name->d.rfc822Name; + break; + case GEN_DNS: + v = PyUnicode_FromString("DNS"); + as = name->d.dNSName; + break; + case GEN_URI: + v = PyUnicode_FromString("URI"); + as = name->d.uniformResourceIdentifier; + break; + } + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 0, v); + v = PyString_FromStringAndSize((char *)ASN1_STRING_data(as), + ASN1_STRING_length(as)); + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 1, v); + break; + default: /* for everything else, we use the OpenSSL print form */ - + switch (gntype) { + /* check for new general name type */ + case GEN_OTHERNAME: + case GEN_X400: + case GEN_EDIPARTY: + case GEN_IPADD: + case GEN_RID: + break; + default: + if (PyErr_Warn(PyExc_RuntimeWarning, + "Unknown general name type") == -1) { + goto fail; + } + break; + } (void) BIO_reset(biobuf); GENERAL_NAME_print(biobuf, name); len = BIO_gets(biobuf, buf, sizeof(buf)-1); @@ -771,6 +828,7 @@ _get_peer_alt_names (X509 *certificate) { goto fail; } PyTuple_SET_ITEM(t, 1, v); + break; } /* and add that rendering to the list */ |