]>
Commit | Line | Data |
---|---|---|
b16376f6 ER |
1 | From: Stanislav Malyshev <stas@php.net> |
2 | Date: Wed, 14 Aug 2013 05:20:33 +0000 (-0700) | |
3 | Subject: Fix CVE-2013-4073 - handling of certs with null bytes | |
4 | X-Git-Tag: php-5.3.28~3 | |
5 | X-Git-Url: http://git.php.net/?p=php-src.git;a=commitdiff;h=dcea4ec698dcae39b7bba6f6aa08933cbfee6755 | |
6 | ||
7 | Fix CVE-2013-4073 - handling of certs with null bytes | |
8 | --- | |
9 | ||
10 | - Openssl: | |
11 | . Fixed handling null bytes in subjectAltName (CVE-2013-4073). | |
12 | (Christian Heimes) | |
13 | diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c | |
14 | index 15696be..c7a9f5c 100644 | |
15 | --- a/ext/openssl/openssl.c | |
16 | +++ b/ext/openssl/openssl.c | |
17 | @@ -1326,6 +1326,74 @@ PHP_FUNCTION(openssl_x509_check_private_key) | |
18 | } | |
19 | /* }}} */ | |
20 | ||
21 | +/* Special handling of subjectAltName, see CVE-2013-4073 | |
22 | + * Christian Heimes | |
23 | + */ | |
24 | + | |
25 | +static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) | |
26 | +{ | |
27 | + GENERAL_NAMES *names; | |
28 | + const X509V3_EXT_METHOD *method = NULL; | |
29 | + long i, length, num; | |
30 | + const unsigned char *p; | |
31 | + | |
32 | + method = X509V3_EXT_get(extension); | |
33 | + if (method == NULL) { | |
34 | + return -1; | |
35 | + } | |
36 | + | |
37 | + p = extension->value->data; | |
38 | + length = extension->value->length; | |
39 | + if (method->it) { | |
40 | + names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length, | |
41 | + ASN1_ITEM_ptr(method->it))); | |
42 | + } else { | |
43 | + names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length)); | |
44 | + } | |
45 | + if (names == NULL) { | |
46 | + return -1; | |
47 | + } | |
48 | + | |
49 | + num = sk_GENERAL_NAME_num(names); | |
50 | + for (i = 0; i < num; i++) { | |
51 | + GENERAL_NAME *name; | |
52 | + ASN1_STRING *as; | |
53 | + name = sk_GENERAL_NAME_value(names, i); | |
54 | + switch (name->type) { | |
55 | + case GEN_EMAIL: | |
56 | + BIO_puts(bio, "email:"); | |
57 | + as = name->d.rfc822Name; | |
58 | + BIO_write(bio, ASN1_STRING_data(as), | |
59 | + ASN1_STRING_length(as)); | |
60 | + break; | |
61 | + case GEN_DNS: | |
62 | + BIO_puts(bio, "DNS:"); | |
63 | + as = name->d.dNSName; | |
64 | + BIO_write(bio, ASN1_STRING_data(as), | |
65 | + ASN1_STRING_length(as)); | |
66 | + break; | |
67 | + case GEN_URI: | |
68 | + BIO_puts(bio, "URI:"); | |
69 | + as = name->d.uniformResourceIdentifier; | |
70 | + BIO_write(bio, ASN1_STRING_data(as), | |
71 | + ASN1_STRING_length(as)); | |
72 | + break; | |
73 | + default: | |
74 | + /* use builtin print for GEN_OTHERNAME, GEN_X400, | |
75 | + * GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID | |
76 | + */ | |
77 | + GENERAL_NAME_print(bio, name); | |
78 | + } | |
79 | + /* trailing ', ' except for last element */ | |
80 | + if (i < (num - 1)) { | |
81 | + BIO_puts(bio, ", "); | |
82 | + } | |
83 | + } | |
84 | + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); | |
85 | + | |
86 | + return 0; | |
87 | +} | |
88 | + | |
89 | /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true]) | |
90 | Returns an array of the fields/values of the CERT */ | |
91 | PHP_FUNCTION(openssl_x509_parse) | |
92 | @@ -1422,15 +1490,29 @@ PHP_FUNCTION(openssl_x509_parse) | |
93 | ||
94 | ||
95 | for (i = 0; i < X509_get_ext_count(cert); i++) { | |
96 | + int nid; | |
97 | extension = X509_get_ext(cert, i); | |
98 | - if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) { | |
99 | + nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension)); | |
100 | + if (nid != NID_undef) { | |
101 | extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension))); | |
102 | } else { | |
103 | OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1); | |
104 | extname = buf; | |
105 | } | |
106 | bio_out = BIO_new(BIO_s_mem()); | |
107 | - if (X509V3_EXT_print(bio_out, extension, 0, 0)) { | |
108 | + if (nid == NID_subject_alt_name) { | |
109 | + if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) { | |
110 | + add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); | |
111 | + } else { | |
112 | + zval_dtor(return_value); | |
113 | + if (certresource == -1 && cert) { | |
114 | + X509_free(cert); | |
115 | + } | |
116 | + BIO_free(bio_out); | |
117 | + RETURN_FALSE; | |
118 | + } | |
119 | + } | |
120 | + else if (X509V3_EXT_print(bio_out, extension, 0, 0)) { | |
121 | BIO_get_mem_ptr(bio_out, &bio_buf); | |
122 | add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); | |
123 | } else { | |
124 | diff --git a/ext/openssl/tests/cve2013_4073.pem b/ext/openssl/tests/cve2013_4073.pem | |
125 | new file mode 100644 | |
126 | index 0000000..7ebb994 | |
127 | --- /dev/null | |
128 | +++ b/ext/openssl/tests/cve2013_4073.pem | |
129 | @@ -0,0 +1,28 @@ | |
130 | +-----BEGIN CERTIFICATE----- | |
131 | +MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx | |
132 | +DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ | |
133 | +eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg | |
134 | +RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y | |
135 | +ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw | |
136 | +NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI | |
137 | +DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv | |
138 | +ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt | |
139 | +ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq | |
140 | +hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB | |
141 | +BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j | |
142 | +pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P | |
143 | +vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv | |
144 | +KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA | |
145 | +oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL | |
146 | +08LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV | |
147 | +HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E | |
148 | +BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu | |
149 | +Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251 | |
150 | +bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA | |
151 | +AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9 | |
152 | +i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j | |
153 | +HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk | |
154 | +kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx | |
155 | +VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW | |
156 | +RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ= | |
157 | +-----END CERTIFICATE----- | |
158 | diff --git a/ext/openssl/tests/cve2013_4073.phpt b/ext/openssl/tests/cve2013_4073.phpt | |
159 | new file mode 100644 | |
160 | index 0000000..e676ddf | |
161 | --- /dev/null | |
162 | +++ b/ext/openssl/tests/cve2013_4073.phpt | |
163 | @@ -0,0 +1,19 @@ | |
164 | +--TEST-- | |
165 | +CVE 2013-4073: Null-byte certificate handling | |
166 | +--SKIPIF-- | |
167 | +<?php | |
168 | +if (!extension_loaded("openssl")) die("skip"); | |
169 | +--FILE-- | |
170 | +<?php | |
171 | +$cert = file_get_contents(__DIR__ . '/cve2013_4073.pem'); | |
172 | +$info = openssl_x509_parse($cert); | |
173 | +var_export($info['extensions']); | |
174 | + | |
175 | +--EXPECTF-- | |
176 | +array ( | |
177 | + 'basicConstraints' => 'CA:FALSE', | |
178 | + 'subjectKeyIdentifier' => '88:5A:55:C0:52:FF:61:CD:52:A3:35:0F:EA:5A:9C:24:38:22:F7:5C', | |
179 | + 'keyUsage' => 'Digital Signature, Non Repudiation, Key Encipherment', | |
180 | + 'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, email:null@python.org' . "\0" . 'user@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 | |
181 | +', | |
182 | +) |