summaryrefslogtreecommitdiff
path: root/lang/php53/patches/patch-ext_openssl_openssl.c
blob: 15d0e83bff0724353913e0d2c2ea78a8877e554e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
$NetBSD: patch-ext_openssl_openssl.c,v 1.2.2.2 2013/08/25 16:52:09 tron Exp $

Fix for CVE-2013-4248.

--- ext/openssl/openssl.c.orig	2013-07-10 17:43:08.000000000 +0000
+++ ext/openssl/openssl.c
@@ -1326,6 +1326,75 @@ PHP_FUNCTION(openssl_x509_check_private_
 }
 /* }}} */
 
+
+/* 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)
@@ -1422,15 +1491,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 {