diff options
author | Georg Brandl <georg@python.org> | 2014-09-30 12:04:51 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2014-09-30 12:04:51 (GMT) |
commit | ec3c103520a5061e657581b388e2b8ba6f74602a (patch) | |
tree | c772344d220e21c83b181972a0e22e9caf8180ba /Modules | |
parent | 79690ac1d0b25c048768e9d3870b475e235f9e7a (diff) | |
download | cpython-ec3c103520a5061e657581b388e2b8ba6f74602a.zip cpython-ec3c103520a5061e657581b388e2b8ba6f74602a.tar.gz cpython-ec3c103520a5061e657581b388e2b8ba6f74602a.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 | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e9de8ca..e273c5c 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -561,7 +561,7 @@ _get_peer_alt_names (X509 *certificate) { int i, j; PyObject *peer_alt_names = Py_None; - PyObject *v, *t; + PyObject *v = NULL, *t; X509_EXTENSION *ext = NULL; GENERAL_NAMES *names = NULL; GENERAL_NAME *name; @@ -616,12 +616,14 @@ _get_peer_alt_names (X509 *certificate) { ext->value->length)); for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { - /* 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 */ @@ -643,11 +645,62 @@ _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 = PyUnicode_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_WarnFormat(PyExc_RuntimeWarning, 1, + "Unknown general name type %d", + gntype) == -1) { + goto fail; + } + break; + } (void) BIO_reset(biobuf); GENERAL_NAME_print(biobuf, name); len = BIO_gets(biobuf, buf, sizeof(buf)-1); @@ -674,6 +727,7 @@ _get_peer_alt_names (X509 *certificate) { goto fail; } PyTuple_SET_ITEM(t, 1, v); + break; } /* and add that rendering to the list */ |