mirror of
https://github.com/php/php-src.git
synced 2024-12-16 13:26:19 +08:00
Merge branch 'san_peer_matching' of https://github.com/rdlowrey/php-src
* 'san_peer_matching' of https://github.com/rdlowrey/php-src: Changed return types to zend_bool, renamed test Added SAN matching during peer verification
This commit is contained in:
commit
c85c50e35c
@ -4951,7 +4951,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool php_openssl_match_cn(const char *subjectname, const char *certname)
|
||||
static zend_bool matches_wildcard_name(const char *subjectname, const char *certname)
|
||||
{
|
||||
char *wildcard;
|
||||
int prefix_len, suffix_len, subject_len;
|
||||
@ -4983,12 +4983,58 @@ static zend_bool php_openssl_match_cn(const char *subjectname, const char *certn
|
||||
return 0;
|
||||
}
|
||||
|
||||
static zend_bool matches_san_list(X509 *peer, const char *subject_name)
|
||||
{
|
||||
int i;
|
||||
zend_bool is_match = 0;
|
||||
unsigned char *cert_name;
|
||||
|
||||
GENERAL_NAMES *alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, 0, 0);
|
||||
int alt_name_count = sk_GENERAL_NAME_num(alt_names);
|
||||
|
||||
for (i = 0; i < alt_name_count; i++) {
|
||||
GENERAL_NAME *san = sk_GENERAL_NAME_value(alt_names, i);
|
||||
|
||||
if (GEN_DNS == san->type) {
|
||||
ASN1_STRING_to_UTF8(&cert_name, san->d.dNSName);
|
||||
is_match = matches_wildcard_name(subject_name, cert_name);
|
||||
OPENSSL_free(cert_name);
|
||||
}
|
||||
|
||||
if (is_match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return is_match;
|
||||
}
|
||||
|
||||
static zend_bool matches_common_name(X509 *peer, const char *subject_name)
|
||||
{
|
||||
char buf[1024];
|
||||
X509_NAME *cert_name;
|
||||
zend_bool is_match = 0;
|
||||
|
||||
cert_name = X509_get_subject_name(peer);
|
||||
int cert_name_len = X509_NAME_get_text_by_NID(cert_name, NID_commonName, buf, sizeof(buf));
|
||||
|
||||
if (cert_name_len == -1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate peer certificate CN");
|
||||
} else if (cert_name_len != strlen(buf)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' is malformed", cert_name_len, buf);
|
||||
} else if (matches_wildcard_name(subject_name, buf)) {
|
||||
is_match = 1;
|
||||
} else {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", cert_name_len, buf, subject_name);
|
||||
}
|
||||
|
||||
return is_match;
|
||||
}
|
||||
|
||||
int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zval **val = NULL;
|
||||
char *cnmatch = NULL;
|
||||
X509_NAME *name;
|
||||
char buf[1024];
|
||||
int err;
|
||||
|
||||
/* verification is turned off */
|
||||
@ -5030,24 +5076,14 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
|
||||
}
|
||||
}
|
||||
|
||||
name = X509_get_subject_name(peer);
|
||||
|
||||
/* Does the common name match ? (used primarily for https://) */
|
||||
GET_VER_OPT_STRING("CN_match", cnmatch);
|
||||
|
||||
if (cnmatch) {
|
||||
int name_len = X509_NAME_get_text_by_NID(name, NID_commonName, buf, sizeof(buf));
|
||||
|
||||
if (name_len == -1) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate peer certificate CN");
|
||||
return FAILURE;
|
||||
} else if (name_len != strlen(buf)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' is malformed", name_len, buf);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (!php_openssl_match_cn(cnmatch, buf)) {
|
||||
/* didn't match */
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", name_len, buf, cnmatch);
|
||||
if (matches_san_list(peer, cnmatch)) {
|
||||
return SUCCESS;
|
||||
} else if (matches_common_name(peer, cnmatch)) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
15
ext/openssl/tests/san-ca.pem
Normal file
15
ext/openssl/tests/san-ca.pem
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV
|
||||
BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y
|
||||
MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE
|
||||
BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl
|
||||
ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m
|
||||
dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9
|
||||
clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3
|
||||
Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC
|
||||
D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF
|
||||
AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k
|
||||
rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X
|
||||
pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg==
|
||||
-----END CERTIFICATE-----
|
31
ext/openssl/tests/san-cert.pem
Normal file
31
ext/openssl/tests/san-cert.pem
Normal file
@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV
|
||||
BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y
|
||||
MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE
|
||||
BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl
|
||||
ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m
|
||||
dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9
|
||||
clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3
|
||||
Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC
|
||||
D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF
|
||||
AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k
|
||||
rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X
|
||||
pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALBRqn21P/A/io66
|
||||
EJeFzMrfZnXEj+4mbaqYTrvZ1WcWAAKn2qo/BZwv6cGFd01OmR53S00AJZcGE97E
|
||||
AUDzxpmUPXJUiDBC9NN7d6YuGVV5LbRulb6/mfTwXB4ZSi0O1jB55+KnLZZVl00q
|
||||
Mk0KZBExdxXN5qxuRt+wYaFJ6OzRAgMBAAECgYB11e5iWvqjPmQEZRdnnJU0VD8u
|
||||
n7ItT+Nk6qtb4gY8Abj6DWIW+01th5vqqJ8FvGyartFVYa69kuM+srG/zevAZWeu
|
||||
fGZtwiwZR4DRSyRcPp4rnNiksK3dkAZA6UewmRDPv8uyHJlXc5i+Ft1ILJ5Q5jgn
|
||||
UkC4z3EJP5Se9KZywQJBAOO4lRq42wLsYr2SDrQDSs4leie3FKc2bgvjF7Djosh1
|
||||
ZYbf55F5b9w1zgnccmni2HkqOnyFu4SKarmXyCsYxrkCQQDGNvnUh7/zZswrdWZ/
|
||||
PMp9zVDTh/5Oc2B4ByNLw1ERDwYhjchKgPRlQvn4cp3Pwf3UYPQ/8XGXzzEJey3A
|
||||
r0rZAkBf/tDEOgcBPXsGZQrTscuYCU5sbY5ESvqrAilbhSp7DJom+D5bIfEYyIm5
|
||||
uHd20Yzlzvpmwc1huyPwZt6X5FLpAkATDReoGMAXSesXxjnqwtIHk2NQYYLM0YQV
|
||||
JUJ8NrKk/Bevw+vbVVeoH+7ctU97t36JGiR/vNoZKD3jVmaIXZDJAkEA4wJbwzIo
|
||||
L32mu9VmZa7wjmfkraQEmXTPaA5D9lNC0AwRTgkj+x2Qe1vawNblNK9PPLBDdplQ
|
||||
L//53ADq/wv5rA==
|
||||
-----END PRIVATE KEY-----
|
60
ext/openssl/tests/san_peer_matching.phpt
Normal file
60
ext/openssl/tests/san_peer_matching.phpt
Normal file
@ -0,0 +1,60 @@
|
||||
--TEST--
|
||||
Peer verification matches SAN names
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("openssl")) die("skip");
|
||||
if (!function_exists('pcntl_fork')) die("skip no fork");
|
||||
--FILE--
|
||||
<?php
|
||||
$context = stream_context_create(array(
|
||||
'ssl' => array(
|
||||
'local_cert' => __DIR__ . '/san-cert.pem',
|
||||
'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__ . '/san-ca.pem',
|
||||
'CN_match' => 'example.org',
|
||||
)
|
||||
)
|
||||
);
|
||||
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__ . '/san-ca.pem',
|
||||
'CN_match' => 'moar.example.org',
|
||||
)
|
||||
));
|
||||
|
||||
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--
|
||||
resource(%d) of type (stream)
|
||||
|
||||
Warning: stream_socket_client(): Unable to locate peer certificate CN 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)
|
Loading…
Reference in New Issue
Block a user