@@ -2646,63 +2646,101 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
26462646static int ssl_verify_server_cert (Vio * vio , const char * server_hostname , const char * * errptr )
26472647{
26482648 SSL * ssl ;
2649- X509 * server_cert ;
2650- char * cp1 , * cp2 ;
2651- char buf [256 ];
2649+ X509 * server_cert = NULL ;
2650+ char * cn = NULL ;
2651+ int cn_loc = -1 ;
2652+ ASN1_STRING * cn_asn1 = NULL ;
2653+ X509_NAME_ENTRY * cn_entry = NULL ;
2654+ X509_NAME * subject = NULL ;
2655+ int ret_validation = 1 ;
2656+
26522657 DBUG_ENTER ("ssl_verify_server_cert" );
26532658 DBUG_PRINT ("enter" , ("server_hostname: %s" , server_hostname ));
26542659
26552660 if (!(ssl = (SSL * )vio -> ssl_arg ))
26562661 {
26572662 * errptr = "No SSL pointer found" ;
2658- DBUG_RETURN ( 1 ) ;
2663+ goto error ;
26592664 }
26602665
26612666 if (!server_hostname )
26622667 {
26632668 * errptr = "No server hostname supplied" ;
2664- DBUG_RETURN ( 1 ) ;
2669+ goto error ;
26652670 }
26662671
26672672 if (!(server_cert = SSL_get_peer_certificate (ssl )))
26682673 {
26692674 * errptr = "Could not get server certificate" ;
2670- DBUG_RETURN ( 1 ) ;
2675+ goto error ;
26712676 }
26722677
26732678 if (X509_V_OK != SSL_get_verify_result (ssl ))
26742679 {
26752680 * errptr = "Failed to verify the server certificate" ;
2676- X509_free (server_cert );
2677- DBUG_RETURN (1 );
2681+ goto error ;
26782682 }
26792683 /*
26802684 We already know that the certificate exchanged was valid; the SSL library
26812685 handled that. Now we need to verify that the contents of the certificate
26822686 are what we expect.
26832687 */
26842688
2685- X509_NAME_oneline (X509_get_subject_name (server_cert ), buf , sizeof (buf ));
2686- X509_free (server_cert );
2689+ /*
2690+ Some notes for future development
2691+ We should check host name in alternative name first and then if needed check in common name.
2692+ Currently yssl doesn't support alternative name.
2693+ openssl 1.0.2 support X509_check_host method for host name validation, we may need to start using
2694+ X509_check_host in the future.
2695+ */
26872696
2688- DBUG_PRINT ("info" , ("hostname in cert: %s" , buf ));
2689- cp1 = strstr (buf , "/CN=" );
2690- if (cp1 )
2697+ subject = X509_get_subject_name ((X509 * ) server_cert );
2698+ // Find the CN location in the subject
2699+ cn_loc = X509_NAME_get_index_by_NID (subject , NID_commonName , -1 );
2700+ if (cn_loc < 0 )
26912701 {
2692- cp1 += 4 ; /* Skip the "/CN=" that we found */
2693- /* Search for next / which might be the delimiter for email */
2694- cp2 = strchr (cp1 , '/' );
2695- if (cp2 )
2696- * cp2 = '\0' ;
2697- DBUG_PRINT ("info" , ("Server hostname in cert: %s" , cp1 ));
2698- if (!strcmp (cp1 , server_hostname ))
2699- {
2700- /* Success */
2701- DBUG_RETURN (0 );
2702- }
2702+ * errptr = "Failed to get CN location in the certificate subject" ;
2703+ goto error ;
2704+ }
2705+
2706+ // Get the CN entry for given location
2707+ cn_entry = X509_NAME_get_entry (subject , cn_loc );
2708+ if (cn_entry == NULL )
2709+ {
2710+ * errptr = "Failed to get CN entry using CN location" ;
2711+ goto error ;
27032712 }
2713+
2714+ // Get CN from common name entry
2715+ cn_asn1 = X509_NAME_ENTRY_get_data (cn_entry );
2716+ if (cn_asn1 == NULL )
2717+ {
2718+ * errptr = "Failed to get CN from CN entry" ;
2719+ goto error ;
2720+ }
2721+
2722+ cn = (char * ) ASN1_STRING_data (cn_asn1 );
2723+
2724+ // There should not be any NULL embedded in the CN
2725+ if ((size_t )ASN1_STRING_length (cn_asn1 ) != strlen (cn ))
2726+ {
2727+ * errptr = "NULL embedded in the certificate CN" ;
2728+ goto error ;
2729+ }
2730+
2731+ DBUG_PRINT ("info" , ("Server hostname in cert: %s" , cn ));
2732+ if (!strcmp (cn , server_hostname ))
2733+ {
2734+ /* Success */
2735+ ret_validation = 0 ;
2736+ }
2737+
27042738 * errptr = "SSL certificate validation failure" ;
2705- DBUG_RETURN (1 );
2739+
2740+ error :
2741+ if (server_cert != NULL )
2742+ X509_free (server_cert );
2743+ DBUG_RETURN (ret_validation );
27062744}
27072745
27082746#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
0 commit comments