com php-src: Support string and array for peer fingerprint matching: ext/openssl/openssl.c ext/openssl/tests/openssl_peer_finger print.phpt
| From: | Michael Wallner | Date: | Fri, 27 Sep 2013 06:13:11 +0000 |
| Subject: | com php-src: Support string and array for peer fingerprint matching: ext/openssl/openssl.c ext/openssl/tests/openssl_peer_finger print.phpt | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-73379@lists.php.net to get a copy of this message | ||
Commit: edd93f34520b550c4c42877fe9e03112cad005ba
Author: datibbaw <datibbaw@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 **)¤t, &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)