]> granicus.if.org Git - php/commitdiff
Prevent invalid SAN peer verification on null byte prefix attack
authorDaniel Lowrey <rdlowrey@php.net>
Mon, 27 Jan 2014 21:51:22 +0000 (14:51 -0700)
committerDaniel Lowrey <rdlowrey@php.net>
Mon, 27 Jan 2014 21:51:22 +0000 (14:51 -0700)
ext/openssl/openssl.c

index fd4b22076a6434b7c4b252290cea13c09354ac97..b38dd6d206c89e7883dd1d6ecbc736e436881762 100644 (file)
@@ -4999,9 +4999,9 @@ static zend_bool matches_wildcard_name(const char *subjectname, const char *cert
        return 0;
 }
 
-static zend_bool matches_san_list(X509 *peer, const char *subject_name)
+static zend_bool matches_san_list(X509 *peer, const char *subject_name TSRMLS_DC)
 {
-       int i;
+       int i, san_name_len;
        zend_bool is_match = 0;
        unsigned char *cert_name;
 
@@ -5010,13 +5010,23 @@ static zend_bool matches_san_list(X509 *peer, const char *subject_name)
 
        for (i = 0; i < alt_name_count; i++) {
                GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
+               if (san->type != GEN_DNS) {
+                       /* we only care about DNS names */
+                       continue;
+               }
+
+               san_name_len = ASN1_STRING_length(san->d.dNSName);
+               ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
 
-               if (GEN_DNS == san->type) {
-                       ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
-                       is_match = matches_wildcard_name(subject_name, (char *) cert_name);
-                       OPENSSL_free(cert_name);
+               /* prevent null byte poisoning */
+               if (san_name_len != strlen(cert_name)) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer SAN entry is malformed");
+               } else {
+                       is_match = strcasecmp(subject_name, cert_name) == 0;
                }
 
+               OPENSSL_free(cert_name);
+
                if (is_match) {
                        break;
                }
@@ -5096,7 +5106,7 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
        GET_VER_OPT_STRING("CN_match", cnmatch);
 
        if (cnmatch) {
-               if (matches_san_list(peer, cnmatch)) {
+               if (matches_san_list(peer, cnmatch TSRMLS_CC)) {
                        return SUCCESS;
                } else if (matches_common_name(peer, cnmatch TSRMLS_CC)) {
                        return SUCCESS;
@@ -5655,3 +5665,4 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
  * vim600: sw=4 ts=4 fdm=marker
  * vim<600: sw=4 ts=4
  */
+