Commit c1d64ccc authored by unknown's avatar unknown

Bug#17208 SSL: client does not verify server certificate

 - Add new function 'ssl_verify_server_cert' which is used if we are 
   connecting to the server with SSL. It will compare the hostname in 
   the server's cert against the hostname that we used when connecting 
   to the server. Will reject the connection if hostname does not match.
 - Add new option "OPT_SSL_VERIFY_SERVER_CERT" to be passed to mysql_options
   which will turn on checking of servers cert.
 - Add new argument "ssl-verify-server-cert" to all mysql* clients which 
   will activate the above option.
 - Generate a new server cert with 1024 bits that has "localhost" as the server name.


SSL/server-cert.pem:
  Generate a new server cert that has "localhost" as CN, so that we can test to verify the hostname we connected against with the hostname in the cert
client/client_priv.h:
  Add OPT_SSL_VERIFY_CERT
client/mysql.cc:
  Pass the variable "opt_ssl_verify_server_cert" to the mysql_options function. It's processed/included by include/sslopt*.h files
client/mysqladmin.cc:
  Pass the variable "opt_ssl_verify_server_cert" to the mysql_options function. It's processed/included by include/sslopt*.h files
client/mysqldump.c:
  Pass the variable "opt_ssl_verify_server_cert" to the mysql_options function. It's processed/included by include/sslopt*.h files
client/mysqlimport.c:
  Pass the variable "opt_ssl_verify_server_cert" to the mysql_options function. It's processed/included by include/sslopt*.h files
client/mysqlshow.c:
  Pass the variable "opt_ssl_verify_server_cert" to the mysql_options function. It's processed/included by include/sslopt*.h files
client/mysqltest.c:
  Always set opt_ssl_verify_server_cert on in mysqltest if we are using SSL
include/mysql.h:
  Add variable ssl_verify_cerver_cert
include/sslopt-longopts.h:
  Add ssl-verify-server-cert options to all clients.
include/sslopt-vars.h:
  Add opt_ssl_varify_server_cert to all clients.
sql-common/client.c:
  Add ssl_vertify_server_cert function which is executed if user has set the option ssl_verify_cerver_cert
vio/viosslfactories.c:
  Ask the SSL library to verify servers cert by setting the SSL_VERIFY_PEER flag
parent c3babee8
Certificate: Certificate:
Data: Data:
Version: 3 (0x2) Version: 3 (0x2)
Serial Number: 2 (0x2) Serial Number:
e9:07:d1:01:94:ee:66:ca
Signature Algorithm: md5WithRSAEncryption Signature Algorithm: md5WithRSAEncryption
Issuer: C=SE, L=Uppsala, O=MySQL AB, CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com Issuer: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com
Validity Validity
Not Before: Sep 12 16:22:06 2003 GMT Not Before: Apr 18 15:35:37 2006 GMT
Not After : Sep 9 16:22:06 2013 GMT Not After : Jan 12 15:35:37 2009 GMT
Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Server/Email=abstract.mysql.developer@mysql.com Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com
Subject Public Key Info: Subject Public Key Info:
Public Key Algorithm: rsaEncryption Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit) RSA Public Key: (1024 bit)
...@@ -23,45 +24,42 @@ Certificate: ...@@ -23,45 +24,42 @@ Certificate:
3d:0e:4d:2a:a8:b8:ca:99:8d 3d:0e:4d:2a:a8:b8:ca:99:8d
Exponent: 65537 (0x10001) Exponent: 65537 (0x10001)
X509v3 extensions: X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier: X509v3 Subject Key Identifier:
6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4 6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4
X509v3 Authority Key Identifier: X509v3 Authority Key Identifier:
keyid:88:98:65:D9:F3:F2:8B:03:1D:66:60:61:23:FA:AD:73:6D:D3:68:92 keyid:6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4
DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB/CN=localhost/emailAddress=abstract.mysql.developer@mysql.com
serial:00 serial:E9:07:D1:01:94:EE:66:CA
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: md5WithRSAEncryption Signature Algorithm: md5WithRSAEncryption
31:77:69:b9:bd:ab:29:f3:fc:5a:09:16:6f:5d:42:ea:ba:01: 1f:03:59:6e:ff:1f:9d:c7:19:9e:8e:b2:1a:c0:0b:9e:ee:94:
55:69:e3:75:cf:b8:d1:b7:b9:bf:da:63:85:8c:48:92:06:60: 35:77:2a:93:04:ea:d5:a8:fc:36:5a:5b:e3:1c:02:b8:cf:04:
76:97:e0:00:78:4b:ad:da:ab:6a:90:6d:8b:03:a8:b1:e9:09: 6e:21:b0:27:f6:96:6e:d6:8f:cd:02:cf:23:f3:e7:ff:6a:ee:
78:e1:29:98:56:12:60:6b:42:fe:e8:a7:c4:f8:d6:15:07:e8: a9:09:c5:c9:07:81:b6:d2:bc:bd:13:47:0d:7b:76:f6:8a:c4:
2b:c2:d8:8a:e5:1b:2e:51:08:9b:56:e3:b3:7a:4c:3e:e5:be: 76:24:f8:4c:4e:26:fc:d8:c0:1f:3d:40:19:43:8e:41:ab:99:
4a:4d:f8:65:7b:a8:21:e0:ca:fe:8b:ab:d7:ec:f2:2d:f7:d0: 3a:99:9b:24:7c:ae:78:f3:df:2f:a2:ed:8f:27:0a:0a:0b:04:
bf:d7:c5:23:1c:08:d8:aa:57:c7:f3:5f:ba:33:3f:78:d1:f4: bf:25:74:88:87:96:c8:68:d5:bc:5b:a0:ef:14:aa:53:6e:c4:
8e:5e a3:e3
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIDkTCCAvqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux MIIDijCCAvOgAwIBAgIJAOkH0QGU7mbKMA0GCSqGSIb3DQEBBAUAMIGLMQswCQYD
EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB VQQGEwJTRTEQMA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G
YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0 A1UEChMITXlTUUwgQUIxEjAQBgNVBAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJ
Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMjA2WhcNMTMw ARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTAeFw0wNjA0MTgx
OTA5MTYyMjA2WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G NTM1MzdaFw0wOTAxMTIxNTM1MzdaMIGLMQswCQYDVQQGEwJTRTEQMA4GA1UECBMH
A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIFNlcnZlcjExMC8GCSqGSIb3 VXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxEjAQ
DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq BgNVBAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwu
hkiG9w0BAQEFAAOBjQAwgYkCgYEA6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40Y ZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
wheVE1LSP1UQV8g/WvWy+ovQZ0nMqoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFg 6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40YwheVE1LSP1UQV8g/WvWy+ovQZ0nM
h5hzXBDBsRpN8fOwmD/w15ebK/3VIXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0q qoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFgh5hzXBDBsRpN8fOwmD/w15ebK/3V
qLjKmY0CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w IXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0qqLjKmY0CAwEAAaOB8zCB8DAdBgNV
ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRu5Jtqxerk5sfv HQ4EFgQUbuSbasXq5ObH79ceyGNFYCsb1NQwgcAGA1UdIwSBuDCBtYAUbuSbasXq
1x7IY0VgKxvU1DCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB 5ObH79ceyGNFYCsb1NShgZGkgY4wgYsxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdV
jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT cHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjESMBAG
CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv A1UEAxMJbG9jYWxob3N0MTEwLwYJKoZIhvcNAQkBFiJhYnN0cmFjdC5teXNxbC5k
BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C ZXZlbG9wZXJAbXlzcWwuY29tggkA6QfRAZTuZsowDAYDVR0TBAUwAwEB/zANBgkq
AQAwDQYJKoZIhvcNAQEEBQADgYEAMXdpub2rKfP8WgkWb11C6roBVWnjdc+40be5 hkiG9w0BAQQFAAOBgQAfA1lu/x+dxxmejrIawAue7pQ1dyqTBOrVqPw2WlvjHAK4
v9pjhYxIkgZgdpfgAHhLrdqrapBtiwOosekJeOEpmFYSYGtC/uinxPjWFQfoK8LY zwRuIbAn9pZu1o/NAs8j8+f/au6pCcXJB4G20ry9E0cNe3b2isR2JPhMTib82MAf
iuUbLlEIm1bjs3pMPuW+Sk34ZXuoIeDK/our1+zyLffQv9fFIxwI2KpXx/NfujM/ PUAZQ45Bq5k6mZskfK54898vou2PJwoKCwS/JXSIh5bIaNW8W6DvFKpTbsSj4w==
eNH0jl4=
-----END CERTIFICATE----- -----END CERTIFICATE-----
...@@ -51,5 +51,5 @@ enum options_client ...@@ -51,5 +51,5 @@ enum options_client
#endif #endif
OPT_TRIGGERS, OPT_TRIGGERS,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
OPT_TZ_UTC, OPT_AUTO_CLOSE OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT
}; };
...@@ -3123,6 +3123,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, ...@@ -3123,6 +3123,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
if (opt_use_ssl) if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif #endif
if (opt_protocol) if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
......
...@@ -340,6 +340,8 @@ int main(int argc,char *argv[]) ...@@ -340,6 +340,8 @@ int main(int argc,char *argv[])
if (opt_use_ssl) if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif #endif
if (opt_protocol) if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
......
...@@ -905,6 +905,8 @@ static int dbConnect(char *host, char *user,char *passwd) ...@@ -905,6 +905,8 @@ static int dbConnect(char *host, char *user,char *passwd)
if (opt_use_ssl) if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif #endif
if (opt_protocol) if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
......
...@@ -384,6 +384,8 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd) ...@@ -384,6 +384,8 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd)
if (opt_use_ssl) if (opt_use_ssl)
mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif #endif
if (opt_protocol) if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
......
...@@ -109,6 +109,8 @@ int main(int argc, char **argv) ...@@ -109,6 +109,8 @@ int main(int argc, char **argv)
if (opt_use_ssl) if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(char*)&opt_ssl_verify_server_cert);
#endif #endif
if (opt_protocol) if (opt_protocol)
mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
......
...@@ -108,7 +108,7 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, ...@@ -108,7 +108,7 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL, OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL,
OPT_VIEW_PROTOCOL}; OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT};
/* ************************************************************************ */ /* ************************************************************************ */
/* /*
...@@ -2378,8 +2378,12 @@ int do_connect(struct st_query *q) ...@@ -2378,8 +2378,12 @@ int do_connect(struct st_query *q)
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
if (opt_use_ssl || con_ssl) if (opt_use_ssl || con_ssl)
{
mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
}
#endif #endif
if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR) if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR)
con_sock=fn_format(buff, con_sock, TMPDIR, "",0); con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
...@@ -4604,9 +4608,14 @@ int main(int argc, char **argv) ...@@ -4604,9 +4608,14 @@ int main(int argc, char **argv)
mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */
if (opt_use_ssl) if (opt_use_ssl)
{
mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher); opt_ssl_capath, opt_ssl_cipher);
mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
}
#endif #endif
if (!(cur_con->name = my_strdup("default", MYF(MY_WME)))) if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
......
...@@ -149,7 +149,8 @@ enum mysql_option ...@@ -149,7 +149,8 @@ enum mysql_option
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH, MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT
}; };
struct st_mysql_options { struct st_mysql_options {
...@@ -164,6 +165,7 @@ struct st_mysql_options { ...@@ -164,6 +165,7 @@ struct st_mysql_options {
char *ssl_ca; /* PEM CA file */ char *ssl_ca; /* PEM CA file */
char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_capath; /* PEM directory of CA-s? */
char *ssl_cipher; /* cipher to use */ char *ssl_cipher; /* cipher to use */
my_bool ssl_verify_server_cert; /* if to verify server cert */
char *shared_memory_base_name; char *shared_memory_base_name;
unsigned long max_allowed_packet; unsigned long max_allowed_packet;
my_bool use_ssl; /* if to use SSL or not */ my_bool use_ssl; /* if to use SSL or not */
......
...@@ -37,5 +37,10 @@ ...@@ -37,5 +37,10 @@
{"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).",
(gptr*) &opt_ssl_cipher, (gptr*) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, (gptr*) &opt_ssl_cipher, (gptr*) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
#ifdef MYSQL_CLIENT
{"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT,
"Verify servers \"Common Name\" in it's cert against hostname used when connecting. This option is disabled by default.",
(gptr*) &opt_ssl_verify_server_cert, (gptr*) &opt_ssl_verify_server_cert,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
...@@ -21,4 +21,7 @@ static char *opt_ssl_cert = 0; ...@@ -21,4 +21,7 @@ static char *opt_ssl_cert = 0;
static char *opt_ssl_ca = 0; static char *opt_ssl_ca = 0;
static char *opt_ssl_capath = 0; static char *opt_ssl_capath = 0;
static char *opt_ssl_cipher = 0; static char *opt_ssl_cipher = 0;
#ifdef MYSQL_CLIENT
static my_bool opt_ssl_verify_server_cert= 0;
#endif
#endif #endif
...@@ -1500,6 +1500,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , ...@@ -1500,6 +1500,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
mysql->options.ssl_ca= strdup_if_not_null(ca); mysql->options.ssl_ca= strdup_if_not_null(ca);
mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_capath= strdup_if_not_null(capath);
mysql->options.ssl_cipher= strdup_if_not_null(cipher); mysql->options.ssl_cipher= strdup_if_not_null(cipher);
mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1521,7 +1522,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) ...@@ -1521,7 +1522,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
if (ssl_fd) if (ssl_fd)
SSL_CTX_free(ssl_fd->ssl_context); SSL_CTX_free(ssl_fd->ssl_context);
my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
...@@ -1534,6 +1535,77 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) ...@@ -1534,6 +1535,77 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
mysql->connector_fd = 0; mysql->connector_fd = 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Check the server's (subject) Common Name against the
hostname we connected to
SYNOPSIS
ssl_verify_server_cert()
vio pointer to a SSL connected vio
server_hostname name of the server that we connected to
RETURN VALUES
0 Success
1 Failed to validate server
*/
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
{
SSL *ssl;
X509 *server_cert;
char *cp1, *cp2;
char buf[256];
DBUG_ENTER("ssl_verify_server_cert");
DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
if (!(ssl= (SSL*)vio->ssl_arg))
{
DBUG_PRINT("error", ("No SSL pointer found"));
DBUG_RETURN(1);
}
if (!server_hostname)
{
DBUG_PRINT("error", ("No server hostname supplied"));
DBUG_RETURN(1);
}
if (!(server_cert= SSL_get_peer_certificate(ssl)))
{
DBUG_PRINT("error", ("Could not get server certificate"));
DBUG_RETURN(1);
}
/*
We already know that the certificate exchanged was valid; the SSL library
handled that. Now we need to verify that the contents of the certificate
are what we expect.
*/
X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf));
X509_free (server_cert);
DBUG_PRINT("info", ("hostname in cert: %s", buf));
cp1 = strstr(buf, "/CN=");
if (cp1)
{
cp1 += 4; // Skip the "/CN=" that we found
// Search for next / which might be the delimiter for email
cp2 = strchr(cp1, '/');
if (cp2)
*cp2 = '\0';
DBUG_PRINT("info", ("Server hostname in cert: %s", cp1));
if (!strcmp(cp1, server_hostname))
{
/* Success */
DBUG_RETURN(0);
}
}
DBUG_PRINT("error", ("SSL certificate validation failure"));
DBUG_RETURN(1);
}
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
...@@ -2049,7 +2121,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2049,7 +2121,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
} }
DBUG_PRINT("info", ("IO layer change done!")); DBUG_PRINT("info", ("IO layer change done!"));
/* TODO Verify server cert */ /* Verify server cert */
if (mysql->options.ssl_verify_server_cert &&
ssl_verify_server_cert(mysql->net.vio, mysql->host))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
} }
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
...@@ -2789,6 +2868,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) ...@@ -2789,6 +2868,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_OPT_RECONNECT: case MYSQL_OPT_RECONNECT:
mysql->reconnect= *(my_bool *) arg; mysql->reconnect= *(my_bool *) arg;
break; break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
mysql->options.ssl_verify_server_cert= *(my_bool *) arg;
break;
default: default:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -290,20 +290,20 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, ...@@ -290,20 +290,20 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
const char *cipher) const char *cipher)
{ {
struct st_VioSSLFd *ssl_fd; struct st_VioSSLFd *ssl_fd;
int verify= SSL_VERIFY_NONE; int verify= SSL_VERIFY_PEER;
if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
ca_path, cipher, TLSv1_client_method()))) ca_path, cipher, TLSv1_client_method())))
{ {
return 0; return 0;
} }
/* Init the the VioSSLFd as a "connector" ie. the client side */ /* Init the the VioSSLFd as a "connector" ie. the client side */
/* /*
The verify_callback function is used to control the behaviour The verify_callback function is used to control the behaviour
when the SSL_VERIFY_PEER flag is set. Here it is SSL_VERIFY_NONE when the SSL_VERIFY_PEER flag is set.
and thus callback is set to NULL
*/ */
SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
return ssl_fd; return ssl_fd;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment