Merge lp:~heimes/pyopenssl/pyopenssl into lp:~exarkun/pyopenssl/trunk

Proposed by Christian Heimes
Status: Needs review
Proposed branch: lp:~heimes/pyopenssl/pyopenssl
Merge into: lp:~exarkun/pyopenssl/trunk
Diff against target: 207 lines (+144/-2)
4 files modified
ChangeLog (+6/-0)
OpenSSL/crypto/x509.c (+1/-0)
OpenSSL/crypto/x509ext.c (+78/-2)
OpenSSL/test/test_crypto.py (+59/-0)
To merge this branch: bzr merge lp:~heimes/pyopenssl/pyopenssl
Reviewer Review Type Date Requested Status
Jean-Paul Calderone Pending
Review via email: mp+179673@code.launchpad.net

Description of the change

To post a comment you must log in.

Unmerged revisions

170. By Christian Heimes

Fix handling of NULL bytes inside subjectAltName general names, CVE-2013-4073.

169. By Christian Heimes

Fix memory leak in get_extension().

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'ChangeLog'
--- ChangeLog 2012-04-03 19:25:07 +0000
+++ ChangeLog 2013-08-12 11:40:45 +0000
@@ -1,3 +1,9 @@
12013-08-11 Christian Heimes <christian@python.org>
2
3 * OpenSSL/crypto/x509ext.c: Fix handling of NULL bytes inside
4 subjectAltName general names, CVE-2013-4073.
5 * OpenSSL/crypto/x509.c: Fix memory leak in get_extension().
6
12012-04-03 Jean-Paul Calderone <exarkun@twistedmatrix.com>72012-04-03 Jean-Paul Calderone <exarkun@twistedmatrix.com>
28
3 * OpenSSL/crypto/pkey.c: Release the GIL around RSA and DSA key9 * OpenSSL/crypto/pkey.c: Release the GIL around RSA and DSA key
410
=== modified file 'OpenSSL/crypto/x509.c'
--- OpenSSL/crypto/x509.c 2011-07-16 05:22:14 +0000
+++ OpenSSL/crypto/x509.c 2013-08-12 11:40:45 +0000
@@ -758,6 +758,7 @@
758758
759 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);759 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
760 extobj->x509_extension = X509_EXTENSION_dup(ext);760 extobj->x509_extension = X509_EXTENSION_dup(ext);
761 extobj->dealloc = 1;
761762
762 return (PyObject*)extobj;763 return (PyObject*)extobj;
763}764}
764765
=== modified file 'OpenSSL/crypto/x509ext.c'
--- OpenSSL/crypto/x509ext.c 2011-07-16 05:14:58 +0000
+++ OpenSSL/crypto/x509ext.c 2013-08-12 11:40:45 +0000
@@ -16,7 +16,7 @@
16static char crypto_X509Extension_get_critical_doc[] = "\n\16static char crypto_X509Extension_get_critical_doc[] = "\n\
17Returns the critical field of the X509Extension\n\17Returns the critical field of the X509Extension\n\
18\n\18\n\
19:return: The critical field.\n\19// :return: The critical field.\n\
20";20";
2121
22static PyObject *22static PyObject *
@@ -236,6 +236,75 @@
236 PyObject_Del(self);236 PyObject_Del(self);
237}237}
238238
239
240/* Special handling of subjectAltName, see CVE-2013-4073 */
241
242int
243crypto_X509Extension_str_san(crypto_X509ExtensionObj *self, BIO *bio)
244{
245 GENERAL_NAMES *names;
246 const X509V3_EXT_METHOD *method = NULL;
247 long i, length, num;
248 const unsigned char *p;
249
250 method = X509V3_EXT_get(self->x509_extension);
251 if (method == NULL) {
252 return -1;
253 }
254
255 p = self->x509_extension->value->data;
256 length = self->x509_extension->value->length;
257 if (method->it) {
258 names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length,
259 ASN1_ITEM_ptr(method->it)));
260 }
261 else {
262 names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length));
263 }
264 if (names == NULL) {
265 return -1;
266 }
267
268 num = sk_GENERAL_NAME_num(names);
269 for (i = 0; i < num; i++) {
270 GENERAL_NAME *name;
271 ASN1_STRING *as;
272 name = sk_GENERAL_NAME_value(names, i);
273 switch (name->type) {
274 case GEN_EMAIL:
275 BIO_puts(bio, "email:");
276 as = name->d.rfc822Name;
277 BIO_write(bio, ASN1_STRING_data(as),
278 ASN1_STRING_length(as));
279 break;
280 case GEN_DNS:
281 BIO_puts(bio, "DNS:");
282 as = name->d.dNSName;
283 BIO_write(bio, ASN1_STRING_data(as),
284 ASN1_STRING_length(as));
285 break;
286 case GEN_URI:
287 BIO_puts(bio, "URI:");
288 as = name->d.uniformResourceIdentifier;
289 BIO_write(bio, ASN1_STRING_data(as),
290 ASN1_STRING_length(as));
291 break;
292 default:
293 /* use builtin print for GEN_OTHERNAME, GEN_X400,
294 * GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID
295 */
296 GENERAL_NAME_print(bio, name);
297 }
298 /* trailing ', ' except for last element */
299 if (i < (num - 1)) {
300 BIO_puts(bio, ", ");
301 }
302 }
303 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
304
305 return 0;
306}
307
239/*308/*
240 * Print a nice text representation of the certificate request.309 * Print a nice text representation of the certificate request.
241 */310 */
@@ -247,7 +316,14 @@
247 PyObject *str;316 PyObject *str;
248 BIO *bio = BIO_new(BIO_s_mem());317 BIO *bio = BIO_new(BIO_s_mem());
249318
250 if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))319 if (OBJ_obj2nid(self->x509_extension->object) == NID_subject_alt_name) {
320 if (crypto_X509Extension_str_san(self, bio) == -1) {
321 BIO_free(bio);
322 exception_from_error_queue(crypto_Error);
323 return NULL;
324 }
325 }
326 else if (!X509V3_EXT_print(bio, self->x509_extension, 0, 0))
251 {327 {
252 BIO_free(bio);328 BIO_free(bio);
253 exception_from_error_queue(crypto_Error);329 exception_from_error_queue(crypto_Error);
254330
=== modified file 'OpenSSL/test/test_crypto.py'
--- OpenSSL/test/test_crypto.py 2012-03-09 22:58:00 +0000
+++ OpenSSL/test/test_crypto.py 2013-08-12 11:40:45 +0000
@@ -265,6 +265,37 @@
265-----END RSA PRIVATE KEY-----265-----END RSA PRIVATE KEY-----
266""")266""")
267267
268# certificate with NULL bytes in subjectAltName and common name
269
270nullbyte_san_PEM = b("""-----BEGIN CERTIFICATE-----
271MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
272DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
273eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
274RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
275ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
276NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
277DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
278ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
279ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
280hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
281BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
282pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
283vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
284KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
285oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
28608LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
287HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
288BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
289Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
290bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
291AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
292i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
293HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
294kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
295VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
296RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
297-----END CERTIFICATE-----""")
298
268299
269class X509ExtTests(TestCase):300class X509ExtTests(TestCase):
270 """301 """
@@ -1398,6 +1429,34 @@
1398 self.assertRaises(IndexError, cert.get_extension, 4)1429 self.assertRaises(IndexError, cert.get_extension, 4)
1399 self.assertRaises(TypeError, cert.get_extension, "hello")1430 self.assertRaises(TypeError, cert.get_extension, "hello")
14001431
1432 def test_nullbyte_san(self):
1433 """
1434 Test correct handling of CN and SAN with NULL bytes
1435
1436 see CVE-2013-4073
1437 """
1438 cert = load_certificate(FILETYPE_PEM, nullbyte_san_PEM)
1439 subject = cert.get_subject()
1440 self.assertEqual(subject.CN, 'null.python.org\x00example.org')
1441 issuer = cert.get_issuer()
1442 self.assertEqual(issuer.CN, 'null.python.org\x00example.org')
1443
1444 ext = cert.get_extension(0)
1445 self.assertEqual(ext.get_short_name(), b('basicConstraints'))
1446
1447 ext = cert.get_extension(1)
1448 self.assertEqual(ext.get_short_name(), b('subjectKeyIdentifier'))
1449
1450 ext = cert.get_extension(2)
1451 self.assertEqual(ext.get_short_name(), b('keyUsage'))
1452
1453 ext = cert.get_extension(3)
1454 self.assertEqual(ext.get_short_name(), b('subjectAltName'))
1455 self.assertEqual(str(ext),
1456 'DNS:altnull.python.org\x00example.com, '
1457 'email:null@python.org\x00user@example.org, '
1458 'URI:http://null.python.org\x00http://example.org, '
1459 'IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1\n')
14011460
1402 def test_invalid_digest_algorithm(self):1461 def test_invalid_digest_algorithm(self):
1403 """1462 """

Subscribers

People subscribed via source and target branches

to status/vote changes: