@@ -2646,63 +2646,101 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
2646
2646
static int ssl_verify_server_cert (Vio * vio , const char * server_hostname , const char * * errptr )
2647
2647
{
2648
2648
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
+
2652
2657
DBUG_ENTER ("ssl_verify_server_cert" );
2653
2658
DBUG_PRINT ("enter" , ("server_hostname: %s" , server_hostname ));
2654
2659
2655
2660
if (!(ssl = (SSL * )vio -> ssl_arg ))
2656
2661
{
2657
2662
* errptr = "No SSL pointer found" ;
2658
- DBUG_RETURN ( 1 ) ;
2663
+ goto error ;
2659
2664
}
2660
2665
2661
2666
if (!server_hostname )
2662
2667
{
2663
2668
* errptr = "No server hostname supplied" ;
2664
- DBUG_RETURN ( 1 ) ;
2669
+ goto error ;
2665
2670
}
2666
2671
2667
2672
if (!(server_cert = SSL_get_peer_certificate (ssl )))
2668
2673
{
2669
2674
* errptr = "Could not get server certificate" ;
2670
- DBUG_RETURN ( 1 ) ;
2675
+ goto error ;
2671
2676
}
2672
2677
2673
2678
if (X509_V_OK != SSL_get_verify_result (ssl ))
2674
2679
{
2675
2680
* errptr = "Failed to verify the server certificate" ;
2676
- X509_free (server_cert );
2677
- DBUG_RETURN (1 );
2681
+ goto error ;
2678
2682
}
2679
2683
/*
2680
2684
We already know that the certificate exchanged was valid; the SSL library
2681
2685
handled that. Now we need to verify that the contents of the certificate
2682
2686
are what we expect.
2683
2687
*/
2684
2688
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
+ */
2687
2696
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 )
2691
2701
{
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 ;
2703
2712
}
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
+
2704
2738
* 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 );
2706
2744
}
2707
2745
2708
2746
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
0 commit comments