Commit:    76af988fece55a6228d892bb736c76916b8f6864
Author:    Stanislav Malyshev <s...@php.net>         Tue, 13 Aug 2013 22:20:33 
-0700
Parents:   10b84a9015a29071df5f5f9d8e4368a38ffbb805
Branches:  PHP-5.4.18

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=76af988fece55a6228d892bb736c76916b8f6864

Log:
Fix CVE-2013-4073 - handling of certs with null bytes

Changed paths:
  M  ext/openssl/openssl.c
  A  ext/openssl/tests/cve2013_4073.pem
  A  ext/openssl/tests/cve2013_4073.phpt


Diff:
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index d7ac117..c32748c 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1398,6 +1398,74 @@ PHP_FUNCTION(openssl_x509_check_private_key)
 }
 /* }}} */
 
+/* Special handling of subjectAltName, see CVE-2013-4073
+ * Christian Heimes
+ */
+
+static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
+{
+       GENERAL_NAMES *names;
+       const X509V3_EXT_METHOD *method = NULL;
+       long i, length, num;
+       const unsigned char *p;
+
+       method = X509V3_EXT_get(extension);
+       if (method == NULL) {
+               return -1;
+       }
+
+       p = extension->value->data;
+       length = extension->value->length;
+       if (method->it) {
+               names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length,
+                                                      
ASN1_ITEM_ptr(method->it)));
+       } else {
+               names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length));
+       }
+       if (names == NULL) {
+               return -1;
+       }
+
+       num = sk_GENERAL_NAME_num(names);
+       for (i = 0; i < num; i++) {
+                       GENERAL_NAME *name;
+                       ASN1_STRING *as;
+                       name = sk_GENERAL_NAME_value(names, i);
+                       switch (name->type) {
+                               case GEN_EMAIL:
+                                       BIO_puts(bio, "email:");
+                                       as = name->d.rfc822Name;
+                                       BIO_write(bio, ASN1_STRING_data(as),
+                                                 ASN1_STRING_length(as));
+                                       break;
+                               case GEN_DNS:
+                                       BIO_puts(bio, "DNS:");
+                                       as = name->d.dNSName;
+                                       BIO_write(bio, ASN1_STRING_data(as),
+                                                 ASN1_STRING_length(as));
+                                       break;
+                               case GEN_URI:
+                                       BIO_puts(bio, "URI:");
+                                       as = name->d.uniformResourceIdentifier;
+                                       BIO_write(bio, ASN1_STRING_data(as),
+                                                 ASN1_STRING_length(as));
+                                       break;
+                               default:
+                                       /* use builtin print for GEN_OTHERNAME, 
GEN_X400,
+                                        * GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD 
and GEN_RID
+                                        */
+                                       GENERAL_NAME_print(bio, name);
+                       }
+                       /* trailing ', ' except for last element */
+                       if (i < (num - 1)) {
+                               BIO_puts(bio, ", ");
+                       }
+       }
+       sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
+
+       return 0;
+}
+
 /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true])
    Returns an array of the fields/values of the CERT */
 PHP_FUNCTION(openssl_x509_parse)
@@ -1494,15 +1562,29 @@ PHP_FUNCTION(openssl_x509_parse)
 
 
        for (i = 0; i < X509_get_ext_count(cert); i++) {
+               int nid;
                extension = X509_get_ext(cert, i);
-               if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != 
NID_undef) {
+               nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
+               if (nid != NID_undef) {
                        extname = (char 
*)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
                } else {
                        OBJ_obj2txt(buf, sizeof(buf)-1, 
X509_EXTENSION_get_object(extension), 1);
                        extname = buf;
                }
                bio_out = BIO_new(BIO_s_mem());
-               if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
+               if (nid == NID_subject_alt_name) {
+                       if (openssl_x509v3_subjectAltName(bio_out, extension) 
== 0) {
+                               add_assoc_stringl(subitem, extname, 
bio_buf->data, bio_buf->length, 1);
+                       } else {
+                               zval_dtor(return_value);
+                               if (certresource == -1 && cert) {
+                                       X509_free(cert);
+                               }
+                               BIO_free(bio_out);
+                               RETURN_FALSE;
+                       }
+               }
+               else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
                        BIO_get_mem_ptr(bio_out, &bio_buf);
                        add_assoc_stringl(subitem, extname, bio_buf->data, 
bio_buf->length, 1);
                } else {
diff --git a/ext/openssl/tests/cve2013_4073.pem 
b/ext/openssl/tests/cve2013_4073.pem
new file mode 100644
index 0000000..7ebb994
--- /dev/null
+++ b/ext/openssl/tests/cve2013_4073.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
+DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
+eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
+RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
+ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
+NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
+DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
+ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
+ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
+hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
+pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
+vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
+KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
+oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
+08LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
+HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
+BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
+Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
+bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
+AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
+i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
+HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
+kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
+VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
+RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
+-----END CERTIFICATE-----
diff --git a/ext/openssl/tests/cve2013_4073.phpt 
b/ext/openssl/tests/cve2013_4073.phpt
new file mode 100644
index 0000000..e676ddf
--- /dev/null
+++ b/ext/openssl/tests/cve2013_4073.phpt
@@ -0,0 +1,19 @@
+--TEST--
+CVE 2013-4073: Null-byte certificate handling
+--SKIPIF--
+<?php 
+if (!extension_loaded("openssl")) die("skip");
+--FILE--
+<?php
+$cert = file_get_contents(__DIR__ . '/cve2013_4073.pem');
+$info = openssl_x509_parse($cert);
+var_export($info['extensions']);
+
+--EXPECTF--
+array (
+  'basicConstraints' => 'CA:FALSE',
+  'subjectKeyIdentifier' => 
'88:5A:55:C0:52:FF:61:CD:52:A3:35:0F:EA:5A:9C:24:38:22:F7:5C',
+  'keyUsage' => 'Digital Signature, Non Repudiation, Key Encipherment',
+  'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, 
email:n...@python.org' . "\0" . 'u...@example.org, URI:http://null.python.org' 
. "\0" . 'http://example.org, IP Address:192.0.2.1, IP 
Address:2001:DB8:0:0:0:0:0:1
+',
+)


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to