diff options
Diffstat (limited to 'ext/openssl/xp_ssl.c')
-rw-r--r-- | ext/openssl/xp_ssl.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index ba35c8828a..1eed2eb485 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -75,7 +75,7 @@ #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i))) extern php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl); -extern zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC); +extern int php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw, char **out, int *out_len TSRMLS_DC); extern int php_openssl_get_ssl_stream_data_index(); extern int php_openssl_get_x509_list_id(void); @@ -265,6 +265,61 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ } /* }}} */ +static int php_x509_fingerprint_cmp(X509 *peer, const char *method, const char *expected TSRMLS_DC) +{ + char *fingerprint; + int fingerprint_len; + int result = -1; + + if (php_openssl_x509_fingerprint(peer, method, 0, &fingerprint, &fingerprint_len TSRMLS_CC) == SUCCESS) { + result = strcmp(expected, fingerprint); + efree(fingerprint); + } + + return result; +} + +static zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC) +{ + if (Z_TYPE_P(val) == IS_STRING) { + const char *method = NULL; + + switch (Z_STRLEN_P(val)) { + case 32: + method = "md5"; + break; + + case 40: + method = "sha1"; + break; + } + + return method && php_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val) TSRMLS_CC) == 0; + } else if (Z_TYPE_P(val) == IS_ARRAY) { + HashPosition pos; + zval **current; + char *key; + uint key_len; + ulong key_index; + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(val), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(val), (void **)¤t, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(val), &pos) + ) { + int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(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) TSRMLS_CC) != 0 + ) { + return 0; + } + } + return 1; + } + return 0; +} + static zend_bool matches_wildcard_name(const char *subjectname, const char *certname) /* {{{ */ { char *wildcard = NULL; |