@@ -370,40 +370,51 @@ static zend_bool matches_wildcard_name(const char *subjectname, const char *cert
370370}
371371/* }}} */
372372
373- static zend_bool matches_san_list (X509 * peer , const char * subject_name TSRMLS_DC ) /* {{{ */
373+ static zend_bool matches_san_list (X509 * peer , const char * subject_name ) /* {{{ */
374374{
375- int i , san_name_len ;
376- zend_bool is_match = 0 ;
375+ int i ;
377376 unsigned char * cert_name = NULL ;
377+ char ipbuffer [64 ];
378378
379379 GENERAL_NAMES * alt_names = X509_get_ext_d2i (peer , NID_subject_alt_name , 0 , 0 );
380380 int alt_name_count = sk_GENERAL_NAME_num (alt_names );
381381
382382 for (i = 0 ; i < alt_name_count ; i ++ ) {
383383 GENERAL_NAME * san = sk_GENERAL_NAME_value (alt_names , i );
384- if (san -> type != GEN_DNS ) {
385- /* we only care about DNS names */
386- continue ;
387- }
388-
389- san_name_len = ASN1_STRING_length (san -> d .dNSName );
390- ASN1_STRING_to_UTF8 (& cert_name , san -> d .dNSName );
391-
392- /* prevent null byte poisoning */
393- if (san_name_len != strlen ((const char * )cert_name )) {
394- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Peer SAN entry is malformed" );
395- } else {
396- is_match = matches_wildcard_name (subject_name , (const char * )cert_name );
397- }
398384
399- OPENSSL_free (cert_name );
385+ if (san -> type == GEN_DNS ) {
386+ ASN1_STRING_to_UTF8 (& cert_name , san -> d .dNSName );
387+ if (ASN1_STRING_length (san -> d .dNSName ) != strlen ((const char * )cert_name )) {
388+ OPENSSL_free (cert_name );
389+ /* prevent null-byte poisoning*/
390+ continue ;
391+ }
400392
401- if (is_match ) {
402- break ;
393+ if (matches_wildcard_name (subject_name , (const char * )cert_name )) {
394+ OPENSSL_free (cert_name );
395+ return 1 ;
396+ }
397+ OPENSSL_free (cert_name );
398+ } else if (san -> type == GEN_IPADD ) {
399+ if (san -> d .iPAddress -> length == 4 ) {
400+ sprintf (ipbuffer , "%d.%d.%d.%d" ,
401+ san -> d .iPAddress -> data [0 ],
402+ san -> d .iPAddress -> data [1 ],
403+ san -> d .iPAddress -> data [2 ],
404+ san -> d .iPAddress -> data [3 ]
405+ );
406+ if (strcasecmp (subject_name , (const char * )ipbuffer ) == 0 ) {
407+ return 1 ;
408+ }
409+ }
410+ /* No, we aren't bothering to check IPv6 addresses. Why?
411+ * Because IP SAN names are officially deprecated and are
412+ * not allowed by CAs starting in 2015. Deal with it.
413+ */
403414 }
404415 }
405416
406- return is_match ;
417+ return 0 ;
407418}
408419/* }}} */
409420
@@ -515,7 +526,7 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
515526 }
516527
517528 if (peer_name ) {
518- if (matches_san_list (peer , peer_name TSRMLS_CC )) {
529+ if (matches_san_list (peer , peer_name )) {
519530 return SUCCESS ;
520531 } else if (matches_common_name (peer , peer_name TSRMLS_CC )) {
521532 return SUCCESS ;
0 commit comments