Commit: 1c7cabb2ca405e6763d7044015f9cb063941a838 Author: Tjerk Meesters <datib...@php.net> Mon, 23 Sep 2013 23:29:17 +0800 Parents: 2bfc5a253b4ee76f9930692f2d088371c38dd65f Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1c7cabb2ca405e6763d7044015f9cb063941a838 Log: add md5 and sha1 fingerprint tests Changed paths: M ext/openssl/openssl.c A ext/openssl/tests/openssl_peer_fingerprint.phpt Diff: diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 9da10fc..c8588e2 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1,4 +1,5 @@ /* + +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ @@ -1672,6 +1673,33 @@ PHP_FUNCTION(openssl_x509_export) } /* }}} */ +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; + int n; + + if (!(mdtype = EVP_get_digestbyname(method))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm"); + return 0; + } else if (!X509_digest(peer, mdtype, md, &n)) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not generate signature"); + return 0; + } + + if (raw) { + *out_len = n; + *out = estrndup(md, n); + } else { + *out_len = n * 2; + *out = emalloc(*out_len + 1); + + make_digest_ex(*out, md, n); + } + + return 1; +} + PHP_FUNCTION(openssl_x509_fingerprint) { X509 *cert; @@ -1681,9 +1709,8 @@ PHP_FUNCTION(openssl_x509_fingerprint) char *method = "sha1"; int method_len; - const EVP_MD *mdtype; - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int n; + char *fingerprint; + char *fingerprint_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|sb", &zcert, &method, &method_len, &raw_output) == FAILURE) { return; @@ -1695,23 +1722,10 @@ PHP_FUNCTION(openssl_x509_fingerprint) RETURN_FALSE; } - mdtype = EVP_get_digestbyname(method); - if (!mdtype) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm"); - RETVAL_FALSE; - } else if (!X509_digest(cert, mdtype, md, &n)) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory"); - RETVAL_FALSE; + if (php_openssl_x509_fingerprint(cert, method, raw_output, &fingerprint, &fingerprint_len)) { + RETVAL_STRINGL(fingerprint, fingerprint_len, 0); } else { - if (raw_output) { - RETVAL_STRINGL(md, n, 1); - } else { - int digest_str_len = n * 2; - char *digest_str = emalloc(digest_str_len + 1); - - make_digest_ex(digest_str, md, n); - RETVAL_STRINGL(digest_str, digest_str_len, 0); - } + RETVAL_FALSE; } if (certresource == -1 && cert) { @@ -4919,6 +4933,33 @@ 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)); + return FAILURE; + } + } + } + name = X509_get_subject_name(peer); /* Does the common name match ? (used primarily for https://) */ diff --git a/ext/openssl/tests/openssl_peer_fingerprint.phpt b/ext/openssl/tests/openssl_peer_fingerprint.phpt new file mode 100644 index 0000000..a6be676 --- /dev/null +++ b/ext/openssl/tests/openssl_peer_fingerprint.phpt @@ -0,0 +1,44 @@ +--TEST-- +Testing peer fingerprint on connection +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists('pcntl_fork')) die("skip no fork"); +--FILE-- +<?php +$context = stream_context_create(); + +stream_context_set_option($context, 'ssl', 'local_cert', __DIR__ . "/bug54992.pem"); +stream_context_set_option($context, 'ssl', 'allow_self_signed', true); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, + STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context); + + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + $contextC = stream_context_create( + array( + 'ssl' => array( + 'verify_peer' => true, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'capture_peer_cert' => true, + 'peer_fingerprint' => '81cafc260aa8d82956ebc6212a362ece', + ) + ) + ); + // should be: 81cafc260aa8d82956ebc6212a362ecc + 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); +} +--EXPECTF-- +Warning: stream_socket_client(): Peer fingerprint `81cafc260aa8d82956ebc6212a362ece` not matched 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) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php