@@ -4951,7 +4951,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */
4951
4951
}
4952
4952
/* }}} */
4953
4953
4954
- static zend_bool php_openssl_match_cn (const char * subjectname , const char * certname )
4954
+ static int matches_wildcard_name (const char * subjectname , const char * certname )
4955
4955
{
4956
4956
char * wildcard ;
4957
4957
int prefix_len , suffix_len , subject_len ;
@@ -4983,12 +4983,55 @@ static zend_bool php_openssl_match_cn(const char *subjectname, const char *certn
4983
4983
return 0 ;
4984
4984
}
4985
4985
4986
+ static int matches_san_list (X509 * peer , const char * subject_name )
4987
+ {
4988
+ int is_match , i ;
4989
+ unsigned char * cert_name ;
4990
+ GENERAL_NAMES * alt_names = X509_get_ext_d2i (peer , NID_subject_alt_name , 0 , 0 );
4991
+ int alt_name_count = sk_GENERAL_NAME_num (alt_names );
4992
+
4993
+ for (i = 0 ; i < alt_name_count ; i ++ ) {
4994
+ GENERAL_NAME * san = sk_GENERAL_NAME_value (alt_names , i );
4995
+
4996
+ if (GEN_DNS == san -> type ) {
4997
+ ASN1_STRING_to_UTF8 (& cert_name , san -> d .dNSName );
4998
+ is_match = matches_wildcard_name (subject_name , cert_name );
4999
+ OPENSSL_free (cert_name );
5000
+ }
5001
+
5002
+ if (is_match ) {
5003
+ break ;
5004
+ }
5005
+ }
5006
+
5007
+ return is_match ;
5008
+ }
5009
+
5010
+ static int matches_common_name (X509 * peer , const char * subject_name )
5011
+ {
5012
+ char buf [1024 ];
5013
+ X509_NAME * cert_name ;
5014
+ cert_name = X509_get_subject_name (peer );
5015
+ int cert_name_len = X509_NAME_get_text_by_NID (cert_name , NID_commonName , buf , sizeof (buf ));
5016
+
5017
+ if (cert_name_len == -1 ) {
5018
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to locate peer certificate CN" );
5019
+ return 0 ;
5020
+ } else if (cert_name_len != strlen (buf )) {
5021
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Peer certificate CN=`%.*s' is malformed" , cert_name_len , buf );
5022
+ return 0 ;
5023
+ } else if (matches_wildcard_name (subject_name , buf )) {
5024
+ return 1 ;
5025
+ } else {
5026
+ php_error_docref (NULL TSRMLS_CC , E_WARNING , "Peer certificate CN=`%.*s' did not match expected CN=`%s'" , cert_name_len , buf , subject_name );
5027
+ return 0 ;
5028
+ }
5029
+ }
5030
+
4986
5031
int php_openssl_apply_verification_policy (SSL * ssl , X509 * peer , php_stream * stream TSRMLS_DC ) /* {{{ */
4987
5032
{
4988
5033
zval * * val = NULL ;
4989
5034
char * cnmatch = NULL ;
4990
- X509_NAME * name ;
4991
- char buf [1024 ];
4992
5035
int err ;
4993
5036
4994
5037
/* verification is turned off */
@@ -5030,24 +5073,14 @@ int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
5030
5073
}
5031
5074
}
5032
5075
5033
- name = X509_get_subject_name (peer );
5034
-
5035
- /* Does the common name match ? (used primarily for https://) */
5036
5076
GET_VER_OPT_STRING ("CN_match" , cnmatch );
5037
- if (cnmatch ) {
5038
- int name_len = X509_NAME_get_text_by_NID (name , NID_commonName , buf , sizeof (buf ));
5039
5077
5040
- if (name_len == -1 ) {
5041
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Unable to locate peer certificate CN" );
5042
- return FAILURE ;
5043
- } else if (name_len != strlen (buf )) {
5044
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Peer certificate CN=`%.*s' is malformed" , name_len , buf );
5045
- return FAILURE ;
5046
- }
5047
-
5048
- if (!php_openssl_match_cn (cnmatch , buf )) {
5049
- /* didn't match */
5050
- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Peer certificate CN=`%.*s' did not match expected CN=`%s'" , name_len , buf , cnmatch );
5078
+ if (cnmatch ) {
5079
+ if (matches_san_list (peer , cnmatch )) {
5080
+ return SUCCESS ;
5081
+ } else if (matches_common_name (peer , cnmatch )) {
5082
+ return SUCCESS ;
5083
+ } else {
5051
5084
return FAILURE ;
5052
5085
}
5053
5086
}
0 commit comments