]> granicus.if.org Git - php/commitdiff
Fix Bug #65538 (cafile now supports stream wrappers)
authorDaniel Lowrey <rdlowrey@php.net>
Sat, 15 Feb 2014 21:31:40 +0000 (14:31 -0700)
committerDaniel Lowrey <rdlowrey@php.net>
Sun, 16 Feb 2014 15:47:37 +0000 (08:47 -0700)
ext/openssl/openssl.c

index 43682a67d6913bd4f52c8eaf2e4e10aa1d2091cf..cf1a4c5464147b0b75ee16bcbc7545193871b1c6 100644 (file)
@@ -695,7 +695,7 @@ static time_t asn1_time_to_time_t(ASN1_UTCTIME * timestr TSRMLS_DC) /* {{{ */
                return (time_t)-1;
        }
 
-       if (ASN1_STRING_length(timestr) != strlen(ASN1_STRING_data(timestr))) {
+       if (ASN1_STRING_length(timestr) != strlen((const char*)ASN1_STRING_data(timestr))) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal length in timestamp");
                return (time_t)-1;
        }
@@ -5042,10 +5042,10 @@ static zend_bool matches_san_list(X509 *peer, const char *subject_name TSRMLS_DC
                ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
 
                /* prevent null byte poisoning */
-               if (san_name_len != strlen(cert_name)) {
+               if (san_name_len != strlen((const char*)cert_name)) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer SAN entry is malformed");
                } else {
-                       is_match = strcasecmp(subject_name, cert_name) == 0;
+                       is_match = strcasecmp(subject_name, (const char*)cert_name) == 0;
                }
 
                OPENSSL_free(cert_name);
@@ -5190,6 +5190,110 @@ static int passwd_callback(char *buf, int num, int verify, void *data) /* {{{ */
 }
 /* }}} */
 
+static long load_stream_cafile(X509_STORE *cert_store, const char *cafile TSRMLS_DC) /* {{{ */
+{
+       php_stream *stream;
+       X509 *cert;
+       BIO *buffer;
+       int buffer_active;
+       char *line;
+       size_t line_len;
+       long certs_added = 0;
+       const char *begin_line = "-----BEGIN CERTIFICATE-----\n";
+       const char *end_line = "-----END CERTIFICATE-----\n";
+
+       stream = php_stream_open_wrapper(cafile, "rb", 0, NULL);
+
+       if (stream == NULL) {
+               php_error(E_WARNING, "failed loading cafile stream: `%s'", cafile);
+               return 0;
+       } else if (stream->wrapper->is_url) {
+               php_stream_close(stream);
+               php_error(E_WARNING, "remote cafile streams are disabled for security purposes");
+               return 0;
+       }
+
+       cert_start: {
+               line = php_stream_get_line(stream, NULL, 0, &line_len);
+               if (line == NULL) {
+                       goto stream_complete;
+               } else if (strcmp(line, begin_line)) {
+                       efree(line);
+                       goto cert_start;
+               } else {
+                       buffer = BIO_new(BIO_s_mem());
+                       buffer_active = 1;
+               }
+       }
+
+       cert_line: {
+               BIO_puts(buffer, line);
+               efree(line);
+               line = php_stream_get_line(stream, NULL, 0, &line_len);
+               if (line == NULL) {
+                       goto stream_complete;
+               } else if (strcmp(line, end_line)) {
+                       goto cert_line;
+               } else {
+                       goto add_cert;
+               }
+       }
+
+       add_cert: {
+               BIO_puts(buffer, line);
+               efree(line);
+               cert = PEM_read_bio_X509(buffer, NULL, 0, NULL);
+               BIO_free(buffer);
+               buffer_active = 0;
+               if (cert && X509_STORE_add_cert(cert_store, cert)) {
+                       ++certs_added;
+               }
+               goto cert_start;
+       }
+
+       stream_complete: {
+               php_stream_close(stream);
+               if (buffer_active) {
+                       BIO_free(buffer);
+               }
+       }
+       
+       return certs_added;
+}
+/* }}} */
+
+static int load_verify_locations(SSL_CTX *ctx, php_stream *stream, char *cafile, char *capath TSRMLS_DC) /* {{{ */
+{
+       if (!cafile) {
+               cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0);
+               cafile = strlen(cafile) ? cafile : NULL;
+       }
+
+       if (!capath) {
+               capath = zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0);
+               capath = strlen(capath) ? capath : NULL;
+       }
+
+       if (cafile || capath) {
+               if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
+                       if (cafile && !load_stream_cafile(SSL_CTX_get_cert_store(ctx), cafile TSRMLS_CC)) {
+                               return 0;
+                       }
+               }
+       } else {
+               php_openssl_netstream_data_t *sslsock;
+               sslsock = (php_openssl_netstream_data_t*)stream->abstract;
+               if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                               "Unable to set default verify locations and no CA settings specified");
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+/* }}} */
+
 SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */
 {
        zval **val = NULL;
@@ -5213,29 +5317,8 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{
                GET_VER_OPT_STRING("cafile", cafile);
                GET_VER_OPT_STRING("capath", capath);
 
-               if (!cafile) {
-                       zend_bool exists = 1;
-                       cafile = zend_ini_string_ex("openssl.cafile", sizeof("openssl.cafile"), 0, &exists);
-               }
-
-               if (!capath) {
-                       zend_bool exists = 1;
-                       capath = zend_ini_string_ex("openssl.capath", sizeof("openssl.capath"), 0, &exists);
-               }
-
-               if (cafile || capath) {
-                       if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath);
-                               return NULL;
-                       }
-               } else {
-                       php_openssl_netstream_data_t *sslsock;
-                       sslsock = (php_openssl_netstream_data_t*)stream->abstract;
-                       if (sslsock->is_client && !SSL_CTX_set_default_verify_paths(ctx)) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING,
-                                       "Unable to set default verify locations and no CA settings specified");
-                               return NULL;
-                       }
+               if (!load_verify_locations(ctx, stream, cafile, capath TSRMLS_CC)) {
+                       return NULL;
                }
 
                if (GET_VER_OPT("verify_depth")) {