Commit:    edd93f34520b550c4c42877fe9e03112cad005ba
Author:    datibbaw <datib...@php.net>         Fri, 27 Sep 2013 14:13:11 +0800
Parents:   69bdc5aca8f14515556bb6fc8f86becf55ef30bf
Branches:  master

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

Log:
Support string and array for peer fingerprint matching

Changed paths:
  M  ext/openssl/openssl.c
  M  ext/openssl/tests/openssl_peer_fingerprint.phpt


Diff:
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index a6ddd14..c0d1b0b 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1672,7 +1672,7 @@ PHP_FUNCTION(openssl_x509_export)
 }
 /* }}} */
 
-int php_openssl_x509_fingerprint(X509 *peer, const char *method, int raw, char 
**out, int *out_len)
+static int php_openssl_x509_fingerprint(X509 *peer, const char *method, int 
raw, char **out, int *out_len)
 {
        unsigned char md[EVP_MAX_MD_SIZE];
        const EVP_MD *mdtype;
@@ -1699,6 +1699,61 @@ int php_openssl_x509_fingerprint(X509 *peer, const char 
*method, int raw, char *
        return 1;
 }
 
+static int php_x509_fingerprint_cmp(X509 *peer, const char *method, const char 
*expected)
+{
+       char *fingerprint;
+       int fingerprint_len;
+       int result = -1;
+
+       if (php_openssl_x509_fingerprint(peer, method, 0, &fingerprint, 
&fingerprint_len)) {
+               result = strcmp(expected, fingerprint);
+               efree(fingerprint);
+       }
+
+       return result;
+}
+
+static int php_x509_fingerprint_match(X509 *peer, zval **val)
+{
+       if (Z_TYPE_PP(val) == IS_STRING) {
+               const char *method = NULL;
+
+               switch (Z_STRLEN_PP(val)) {
+                       case 32:
+                               method = "md5";
+                               break;
+
+                       case 40:
+                               method = "sha1";
+                               break;
+               }
+
+               return method && php_x509_fingerprint_cmp(peer, method, 
Z_STRVAL_PP(val)) == 0;
+       } else if (Z_TYPE_PP(val) == IS_ARRAY) {
+               HashPosition pos;
+               zval **current;
+               char *key;
+               uint key_len;
+               ulong key_index;
+
+               for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(val), 
&pos);
+                       zend_hash_get_current_data_ex(Z_ARRVAL_PP(val), (void 
**)&current, &pos) == SUCCESS;
+                       zend_hash_move_forward_ex(Z_ARRVAL_PP(val), &pos)
+               ) {
+                       int key_type = 
zend_hash_get_current_key_ex(Z_ARRVAL_PP(val), &key, &key_len, &key_index, 0, 
&pos);
+
+                       if (key_type == HASH_KEY_IS_STRING 
+                               && Z_TYPE_PP(current) == IS_STRING
+                               && php_x509_fingerprint_cmp(peer, key, 
Z_STRVAL_PP(current)) != 0
+                       ) {
+                               return 0;
+                       }
+               }
+               return 1;
+       }
+       return 0;
+}
+
 PHP_FUNCTION(openssl_x509_fingerprint)
 {
        X509 *cert;
@@ -1709,7 +1764,7 @@ PHP_FUNCTION(openssl_x509_fingerprint)
        int method_len;
 
        char *fingerprint;
-       char *fingerprint_len;
+       int fingerprint_len;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|sb", &zcert, 
&method, &method_len, &raw_output) == FAILURE) {
                return;
@@ -4932,30 +4987,14 @@ int php_openssl_apply_verification_policy(SSL *ssl, 
X509 *peer, php_stream *stre
 
        /* if the cert passed the usual checks, apply our own local policies 
now */
 
-       if (GET_VER_OPT("peer_fingerprint") && Z_TYPE_PP(val) == IS_STRING) {
-               char *fingerprint;
-               int fingerprint_len;
-               const char *method = NULL;
-
-               switch (Z_STRLEN_PP(val)) {
-                       case 32:
-                               method = "md5";
-                               break;
-
-                       case 40:
-                               method = "sha1";
-                               break;
-               }
-
-               if (method && php_openssl_x509_fingerprint(peer, method, 0, 
&fingerprint, &fingerprint_len)) {
-                       int match = strcmp(Z_STRVAL_PP(val), fingerprint) == 0;
-
-                       efree(fingerprint);
-
-                       if (!match) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Peer fingerprint `%s` not matched", Z_STRVAL_PP(val));
+       if (GET_VER_OPT("peer_fingerprint")) {
+               if (Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_ARRAY) {
+                       if (!php_x509_fingerprint_match(peer, val)) {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, 
"Peer fingerprint doesn't match");
                                return FAILURE;
                        }
+               } else {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected 
peer fingerprint must be a string or an array");
                }
        }
 
diff --git a/ext/openssl/tests/openssl_peer_fingerprint.phpt 
b/ext/openssl/tests/openssl_peer_fingerprint.phpt
index a6be676..2960dff 100644
--- a/ext/openssl/tests/openssl_peer_fingerprint.phpt
+++ b/ext/openssl/tests/openssl_peer_fingerprint.phpt
@@ -31,14 +31,32 @@ if ($pid == -1) {
        // should be: 81cafc260aa8d82956ebc6212a362ecc
        var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 
1,
                STREAM_CLIENT_CONNECT, $contextC));
+
+       $contextC = stream_context_create(
+               array(
+                       'ssl' => array(
+                               'verify_peer'           => true,
+                               'cafile'                => __DIR__ . 
'/bug54992-ca.pem',
+                               'capture_peer_cert'     => true,
+                               'peer_fingerprint'      => array(
+                                       'sha256' => 
'78ea579f2c3b439359dec5dac9d445108772927427c4780037e87df3799a0aa0',
+                               ),
+                       )
+               )
+       );
+
+       var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 
1,
+               STREAM_CLIENT_CONNECT, $contextC));
 } else {
        @pcntl_wait($status);
        @stream_socket_accept($server, 1);
+       @stream_socket_accept($server, 1);
 }
 --EXPECTF--
-Warning: stream_socket_client(): Peer fingerprint 
`81cafc260aa8d82956ebc6212a362ece` not matched in %s on line %d
+Warning: stream_socket_client(): Peer fingerprint doesn't match in %s on line 
%d
 
 Warning: stream_socket_client(): Failed to enable crypto in %s on line %d
 
 Warning: stream_socket_client(): unable to connect to ssl://127.0.0.1:64321 
(Unknown error) in %s on line %d
 bool(false)
+resource(9) of type (stream)


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

Reply via email to