diff options
author | unknown <msvensson@neptunus.(none)> | 2006-04-26 22:24:25 +0200 |
---|---|---|
committer | unknown <msvensson@neptunus.(none)> | 2006-04-26 22:24:25 +0200 |
commit | 88724885d545357c76dbda02a69a488a45296071 (patch) | |
tree | 67ff2b286c7d42090d89349a6b6c10d80480feb5 | |
parent | d61f1823d67771c1d4e48b8adb4819d748e4d747 (diff) | |
parent | c1d64ccc1b227e862f5cbaa991ce5525c59ab2ef (diff) | |
download | mariadb-git-88724885d545357c76dbda02a69a488a45296071.tar.gz |
Merge neptunus.(none):/home/msvensson/mysql/bug17208/my50-bug17208
into neptunus.(none):/home/msvensson/mysql/mysql-5.0-maint
client/mysql.cc:
Auto merged
include/mysql.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql-common/client.c:
SCCS merged
-rw-r--r-- | SSL/server-cert.pem | 78 | ||||
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysql.cc | 2 | ||||
-rw-r--r-- | client/mysqladmin.cc | 2 | ||||
-rw-r--r-- | client/mysqldump.c | 2 | ||||
-rw-r--r-- | client/mysqlimport.c | 2 | ||||
-rw-r--r-- | client/mysqlshow.c | 2 | ||||
-rw-r--r-- | client/mysqltest.c | 11 | ||||
-rw-r--r-- | include/mysql.h | 4 | ||||
-rw-r--r-- | include/sslopt-longopts.h | 7 | ||||
-rw-r--r-- | include/sslopt-vars.h | 3 | ||||
-rw-r--r-- | include/violite.h | 21 | ||||
-rw-r--r-- | sql-common/client.c | 126 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 7 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | vio/vio.c | 16 | ||||
-rw-r--r-- | vio/vio_priv.h | 22 | ||||
-rw-r--r-- | vio/viossl.c | 354 | ||||
-rw-r--r-- | vio/viosslfactories.c | 300 |
20 files changed, 428 insertions, 539 deletions
diff --git a/SSL/server-cert.pem b/SSL/server-cert.pem index debf7026e3c..4ef70ed5095 100644 --- a/SSL/server-cert.pem +++ b/SSL/server-cert.pem @@ -1,13 +1,14 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 2 (0x2) + Serial Number: + e9:07:d1:01:94:ee:66:ca 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 - Not Before: Sep 12 16:22:06 2003 GMT - Not After : Sep 9 16:22:06 2013 GMT - Subject: C=SE, L=Uppsala, O=MySQL AB, CN=MySQL Server/Email=abstract.mysql.developer@mysql.com + Not Before: Apr 18 15:35:37 2006 GMT + Not After : Jan 12 15:35:37 2009 GMT + Subject: C=SE, ST=Uppsala, L=Uppsala, O=MySQL AB, CN=localhost/emailAddress=abstract.mysql.developer@mysql.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) @@ -23,45 +24,42 @@ Certificate: 3d:0e:4d:2a:a8:b8:ca:99:8d Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - Netscape Comment: - OpenSSL Generated Certificate X509v3 Subject Key Identifier: 6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4 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 - DirName:/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com - serial:00 + keyid:6E:E4:9B:6A:C5:EA:E4:E6:C7:EF:D7:1E:C8:63:45:60:2B:1B:D4:D4 + DirName:/C=SE/ST=Uppsala/L=Uppsala/O=MySQL AB/CN=localhost/emailAddress=abstract.mysql.developer@mysql.com + serial:E9:07:D1:01:94:EE:66:CA + X509v3 Basic Constraints: + CA:TRUE Signature Algorithm: md5WithRSAEncryption - 31:77:69:b9:bd:ab:29:f3:fc:5a:09:16:6f:5d:42:ea:ba:01: - 55:69:e3:75:cf:b8:d1:b7:b9:bf:da:63:85:8c:48:92:06:60: - 76:97:e0:00:78:4b:ad:da:ab:6a:90:6d:8b:03:a8:b1:e9:09: - 78:e1:29:98:56:12:60:6b:42:fe:e8:a7:c4:f8:d6:15:07:e8: - 2b:c2:d8:8a:e5:1b:2e:51:08:9b:56:e3:b3:7a:4c:3e:e5:be: - 4a:4d:f8:65:7b:a8:21:e0:ca:fe:8b:ab:d7:ec:f2:2d:f7:d0: - bf:d7:c5:23:1c:08:d8:aa:57:c7:f3:5f:ba:33:3f:78:d1:f4: - 8e:5e + 1f:03:59:6e:ff:1f:9d:c7:19:9e:8e:b2:1a:c0:0b:9e:ee:94: + 35:77:2a:93:04:ea:d5:a8:fc:36:5a:5b:e3:1c:02:b8:cf:04: + 6e:21:b0:27:f6:96:6e:d6:8f:cd:02:cf:23:f3:e7:ff:6a:ee: + a9:09:c5:c9:07:81:b6:d2:bc:bd:13:47:0d:7b:76:f6:8a:c4: + 76:24:f8:4c:4e:26:fc:d8:c0:1f:3d:40:19:43:8e:41:ab:99: + 3a:99:9b:24:7c:ae:78:f3:df:2f:a2:ed:8f:27:0a:0a:0b:04: + bf:25:74:88:87:96:c8:68:d5:bc:5b:a0:ef:14:aa:53:6e:c4: + a3:e3 -----BEGIN CERTIFICATE----- -MIIDkTCCAvqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCU0Ux -EDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMSEwHwYDVQQDExhB -YnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAvBgkqhkiG9w0BCQEWImFic3RyYWN0 -Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb20wHhcNMDMwOTEyMTYyMjA2WhcNMTMw -OTA5MTYyMjA2WjB8MQswCQYDVQQGEwJTRTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G -A1UEChMITXlTUUwgQUIxFTATBgNVBAMTDE15U1FMIFNlcnZlcjExMC8GCSqGSIb3 -DQEJARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkq -hkiG9w0BAQEFAAOBjQAwgYkCgYEA6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40Y -wheVE1LSP1UQV8g/WvWy+ovQZ0nMqoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFg -h5hzXBDBsRpN8fOwmD/w15ebK/3VIXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0q -qLjKmY0CAwEAAaOCARQwggEQMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w -ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRu5Jtqxerk5sfv -1x7IY0VgKxvU1DCBtQYDVR0jBIGtMIGqgBSImGXZ8/KLAx1mYGEj+q1zbdNokqGB -jqSBizCBiDELMAkGA1UEBhMCU0UxEDAOBgNVBAcTB1VwcHNhbGExETAPBgNVBAoT -CE15U1FMIEFCMSEwHwYDVQQDExhBYnN0cmFjdCBNeVNRTCBEZXZlbG9wZXIxMTAv -BgkqhkiG9w0BCQEWImFic3RyYWN0Lm15c3FsLmRldmVsb3BlckBteXNxbC5jb22C -AQAwDQYJKoZIhvcNAQEEBQADgYEAMXdpub2rKfP8WgkWb11C6roBVWnjdc+40be5 -v9pjhYxIkgZgdpfgAHhLrdqrapBtiwOosekJeOEpmFYSYGtC/uinxPjWFQfoK8LY -iuUbLlEIm1bjs3pMPuW+Sk34ZXuoIeDK/our1+zyLffQv9fFIxwI2KpXx/NfujM/ -eNH0jl4= +MIIDijCCAvOgAwIBAgIJAOkH0QGU7mbKMA0GCSqGSIb3DQEBBAUAMIGLMQswCQYD +VQQGEwJTRTEQMA4GA1UECBMHVXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8G +A1UEChMITXlTUUwgQUIxEjAQBgNVBAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJ +ARYiYWJzdHJhY3QubXlzcWwuZGV2ZWxvcGVyQG15c3FsLmNvbTAeFw0wNjA0MTgx +NTM1MzdaFw0wOTAxMTIxNTM1MzdaMIGLMQswCQYDVQQGEwJTRTEQMA4GA1UECBMH +VXBwc2FsYTEQMA4GA1UEBxMHVXBwc2FsYTERMA8GA1UEChMITXlTUUwgQUIxEjAQ +BgNVBAMTCWxvY2FsaG9zdDExMC8GCSqGSIb3DQEJARYiYWJzdHJhY3QubXlzcWwu +ZGV2ZWxvcGVyQG15c3FsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +6YZ6VYSITL6k+JJzMBJJC3qFhzk0OQ19C40YwheVE1LSP1UQV8g/WvWy+ovQZ0nM +qoL8n84AtHPzNtI608KwDhTD1LIhdKHwMYFgh5hzXBDBsRpN8fOwmD/w15ebK/3V +IXmyL+tkFcmbnfyeLdT4BFvqqXVLQsM9Dk0qqLjKmY0CAwEAAaOB8zCB8DAdBgNV +HQ4EFgQUbuSbasXq5ObH79ceyGNFYCsb1NQwgcAGA1UdIwSBuDCBtYAUbuSbasXq +5ObH79ceyGNFYCsb1NShgZGkgY4wgYsxCzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdV +cHBzYWxhMRAwDgYDVQQHEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBBQjESMBAG +A1UEAxMJbG9jYWxob3N0MTEwLwYJKoZIhvcNAQkBFiJhYnN0cmFjdC5teXNxbC5k +ZXZlbG9wZXJAbXlzcWwuY29tggkA6QfRAZTuZsowDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQQFAAOBgQAfA1lu/x+dxxmejrIawAue7pQ1dyqTBOrVqPw2WlvjHAK4 +zwRuIbAn9pZu1o/NAs8j8+f/au6pCcXJB4G20ry9E0cNe3b2isR2JPhMTib82MAf +PUAZQ45Bq5k6mZskfK54898vou2PJwoKCwS/JXSIh5bIaNW8W6DvFKpTbsSj4w== -----END CERTIFICATE----- diff --git a/client/client_priv.h b/client/client_priv.h index a9d5364df49..9e011144836 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -51,5 +51,5 @@ enum options_client #endif OPT_TRIGGERS, 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 }; diff --git a/client/mysql.cc b/client/mysql.cc index 5b53570bf34..4e81e2ae686 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3125,6 +3125,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 5b52d524f8e..57ab4e071fb 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -340,6 +340,8 @@ int main(int argc,char *argv[]) if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqldump.c b/client/mysqldump.c index 78f12593f46..ee6d7b9d12b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -905,6 +905,8 @@ static int dbConnect(char *host, char *user,char *passwd) if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 8694093f06b..1f9b96f91be 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -384,6 +384,8 @@ static MYSQL *db_connect(char *host, char *database, char *user, char *passwd) if (opt_use_ssl) mysql_ssl_set(&mysql_connection, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql_connection,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 504f0d9844b..d090495ff81 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -109,6 +109,8 @@ int main(int argc, char **argv) if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); diff --git a/client/mysqltest.c b/client/mysqltest.c index e51d83270b5..7257958311f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -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_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_VIEW_PROTOCOL}; + OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT}; /* ************************************************************************ */ /* @@ -2378,8 +2378,12 @@ int do_connect(struct st_query *q) #ifdef HAVE_OPENSSL if (opt_use_ssl || con_ssl) + { mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + &opt_ssl_verify_server_cert); + } #endif if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR) con_sock=fn_format(buff, con_sock, TMPDIR, "",0); @@ -4604,9 +4608,14 @@ int main(int argc, char **argv) mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); #ifdef HAVE_OPENSSL + opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */ if (opt_use_ssl) + { mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + &opt_ssl_verify_server_cert); + } #endif if (!(cur_con->name = my_strdup("default", MYF(MY_WME)))) diff --git a/include/mysql.h b/include/mysql.h index 6217ce631b5..3a71e47f414 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -149,7 +149,8 @@ enum mysql_option MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT, MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 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 { @@ -164,6 +165,7 @@ struct st_mysql_options { char *ssl_ca; /* PEM CA file */ char *ssl_capath; /* PEM directory of CA-s? */ char *ssl_cipher; /* cipher to use */ + my_bool ssl_verify_server_cert; /* if to verify server cert */ char *shared_memory_base_name; unsigned long max_allowed_packet; my_bool use_ssl; /* if to use SSL or not */ diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index dc3b0922327..f444a7eb7ce 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -37,5 +37,10 @@ {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", (gptr*) &opt_ssl_cipher, (gptr*) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, 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 */ diff --git a/include/sslopt-vars.h b/include/sslopt-vars.h index 164cf541381..8e5f3434396 100644 --- a/include/sslopt-vars.h +++ b/include/sslopt-vars.h @@ -21,4 +21,7 @@ static char *opt_ssl_cert = 0; static char *opt_ssl_ca = 0; static char *opt_ssl_capath = 0; static char *opt_ssl_cipher = 0; +#ifdef MYSQL_CLIENT +static my_bool opt_ssl_verify_server_cert= 0; +#endif #endif diff --git a/include/violite.h b/include/violite.h index b48f3724f5b..b2a5f1640a5 100644 --- a/include/violite.h +++ b/include/violite.h @@ -105,33 +105,22 @@ void vio_timeout(Vio *vio,uint which, uint timeout); #include <openssl/ssl.h> #include <openssl/err.h> -struct st_VioSSLAcceptorFd +struct st_VioSSLFd { SSL_CTX *ssl_context; - SSL_METHOD *ssl_method; - struct st_VioSSLAcceptorFd *session_id_context; }; -/* One copy for client */ -struct st_VioSSLConnectorFd -{ - SSL_CTX *ssl_context; - /* function pointers which are only once for SSL client */ - SSL_METHOD *ssl_method; -}; - -int sslaccept(struct st_VioSSLAcceptorFd*, Vio *, long timeout); -int sslconnect(struct st_VioSSLConnectorFd*, Vio *, long timeout); +int sslaccept(struct st_VioSSLFd*, Vio *, long timeout); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout); -struct st_VioSSLConnectorFd +struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, const char *cipher); -struct st_VioSSLAcceptorFd +struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file,const char *ca_path, const char *cipher); -Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state); #endif /* HAVE_OPENSSL */ #ifdef HAVE_SMEM diff --git a/sql-common/client.c b/sql-common/client.c index 72745d72b12..9f445c02df9 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1500,6 +1500,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , mysql->options.ssl_ca= strdup_if_not_null(ca); mysql->options.ssl_capath= strdup_if_not_null(capath); mysql->options.ssl_cipher= strdup_if_not_null(cipher); + mysql->options.ssl_verify_server_cert= FALSE; /* Off by default */ #endif /* HAVE_OPENSSL */ DBUG_RETURN(0); } @@ -1514,17 +1515,16 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { - struct st_VioSSLConnectorFd *st= - (struct st_VioSSLConnectorFd*) mysql->connector_fd; + struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd; DBUG_ENTER("mysql_ssl_free"); my_free(mysql->options.ssl_key, 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_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); - if (st) - SSL_CTX_free(st->ssl_context); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + if (ssl_fd) + SSL_CTX_free(ssl_fd->ssl_context); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; @@ -1556,6 +1556,77 @@ mysql_get_ssl_cipher(MYSQL *mysql) DBUG_RETURN(NULL); } + +/* + 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 */ @@ -1589,7 +1660,6 @@ static MYSQL_METHODS client_methods= #endif }; - MYSQL * CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, @@ -2034,37 +2104,52 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->client_flag=client_flag; #ifdef HAVE_OPENSSL - /* - Oops.. are we careful enough to not send ANY information without - encryption? - */ if (client_flag & CLIENT_SSL) { + /* Do the SSL layering. */ struct st_mysql_options *options= &mysql->options; + struct st_VioSSLFd *ssl_fd; + + /* + Send client_flag, max_packet_size - unencrypted otherwise + the server does not know we want to do SSL + */ if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } - /* Do the SSL layering. */ - if (!(mysql->connector_fd= - (gptr) new_VioSSLConnectorFd(options->ssl_key, - options->ssl_cert, - options->ssl_ca, - options->ssl_capath, - options->ssl_cipher))) + + /* Create the VioSSLConnectorFd - init SSL and load certs */ + if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key, + options->ssl_cert, + options->ssl_ca, + options->ssl_capath, + options->ssl_cipher))) { set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } + mysql->connector_fd= (void*)ssl_fd; + + /* Connect to the server */ DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), - mysql->net.vio, (long) (mysql->options.connect_timeout))) + if (sslconnect(ssl_fd, mysql->net.vio, + (long) (mysql->options.connect_timeout))) { set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } DBUG_PRINT("info", ("IO layer change done!")); + + /* 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 */ @@ -2804,6 +2889,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) case MYSQL_OPT_RECONNECT: mysql->reconnect= *(my_bool *) arg; break; + case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: + mysql->options.ssl_verify_server_cert= *(my_bool *) arg; + break; default: DBUG_RETURN(1); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 98ffb54c240..e583ef95daf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1310,7 +1310,7 @@ extern pthread_t signal_thread; #endif #ifdef HAVE_OPENSSL -extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; +extern struct st_VioSSLFd * ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e84bcea8058..49efc24d15c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -620,7 +620,7 @@ static void openssl_lock(int, openssl_lock_t *, const char *, int); static unsigned long openssl_id_function(); #endif char *des_key_file; -struct st_VioSSLAcceptorFd *ssl_acceptor_fd; +struct st_VioSSLFd *ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ @@ -1131,7 +1131,10 @@ void clean_up(bool print_message) #endif #ifdef HAVE_OPENSSL if (ssl_acceptor_fd) - my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR)); + { + SSL_CTX_free(ssl_acceptor_fd->ssl_context); + my_free((gptr) ssl_acceptor_fd, MYF(0)); + } #endif /* HAVE_OPENSSL */ #ifdef USE_REGEX my_regex_end(); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d66a631dbcc..511c0ddbb2e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -858,8 +858,8 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, if (acl_user->x509_issuer) { DBUG_PRINT("info",("checkpoint 3")); - char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); - DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", + char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", acl_user->x509_issuer, ptr)); if (strcmp(acl_user->x509_issuer, ptr)) { diff --git a/vio/vio.c b/vio/vio.c index bc286b2d2bb..21a824a4016 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type, if (type == VIO_TYPE_SSL) { vio->viodelete =vio_delete; - vio->vioerrno =vio_ssl_errno; + vio->vioerrno =vio_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; - vio->fastsend =vio_ssl_fastsend; - vio->viokeepalive =vio_ssl_keepalive; - vio->should_retry =vio_ssl_should_retry; - vio->was_interrupted=vio_ssl_was_interrupted; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_ssl_close; - vio->peer_addr =vio_ssl_peer_addr; - vio->in_addr =vio_ssl_in_addr; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ssl_timeout; + vio->timeout =vio_timeout; } else /* default is VIO_TYPE_TCPIP */ #endif /* HAVE_OPENSSL */ diff --git a/vio/vio_priv.h b/vio/vio_priv.h index eb495025ddd..db331abdea8 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -30,28 +30,10 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); int vio_ssl_read(Vio *vio,gptr buf, int size); int vio_ssl_write(Vio *vio,const gptr buf,int size); -void vio_ssl_timeout(Vio *vio, uint which, uint timeout); - -/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */ -int vio_ssl_fastsend(Vio *vio); -/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */ -int vio_ssl_keepalive(Vio *vio, my_bool onoff); -/* Whenever we should retry the last read/write operation. */ -my_bool vio_ssl_should_retry(Vio *vio); -/* Check that operation was timed out */ -my_bool vio_ssl_was_interrupted(Vio *vio); + /* When the workday is over... */ int vio_ssl_close(Vio *vio); -/* Return last error number */ -int vio_ssl_errno(Vio *vio); -my_bool vio_ssl_peer_addr(Vio *vio, char *buf, uint16 *port); -void vio_ssl_in_addr(Vio *vio, struct in_addr *in); + int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); -/* Single copy for server */ -enum vio_ssl_acceptorfd_state -{ - state_connect = 1, - state_accept = 2 -}; #endif /* HAVE_OPENSSL */ diff --git a/vio/viossl.c b/vio/viossl.c index 1273814c551..aa4cdda9f01 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -54,12 +54,12 @@ static void report_errors() { unsigned long l; - const char* file; - const char* data; - int line,flags; + const char *file; + const char *data; + int line,flags; DBUG_ENTER("report_errors"); - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags))) + while ((l= ERR_get_error_line_data(&file,&line,&data,&flags))) { char buf[512]; DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), @@ -70,13 +70,7 @@ report_errors() } -int vio_ssl_errno(Vio *vio __attribute__((unused))) -{ - return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ -} - - -int vio_ssl_read(Vio * vio, gptr buf, int size) +int vio_ssl_read(Vio *vio, gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_read"); @@ -94,7 +88,7 @@ int vio_ssl_read(Vio * vio, gptr buf, int size) } -int vio_ssl_write(Vio * vio, const gptr buf, int size) +int vio_ssl_write(Vio *vio, const gptr buf, int size) { int r; DBUG_ENTER("vio_ssl_write"); @@ -107,183 +101,51 @@ int vio_ssl_write(Vio * vio, const gptr buf, int size) } -int vio_ssl_fastsend(Vio * vio __attribute__((unused))) -{ - int r=0; - DBUG_ENTER("vio_ssl_fastsend"); - -#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) - { - int tos= IPTOS_THROUGHPUT; - r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); - } -#endif /* IPTOS_THROUGHPUT && !__EMX__ */ - if (!r) - { -#ifdef __WIN__ - BOOL nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, - sizeof(nodelay)); -#else - int nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, - sizeof(nodelay)); -#endif /* __WIN__ */ - } - if (r) - { - DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); - r= -1; - } - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive) -{ - int r=0; - DBUG_ENTER("vio_ssl_keepalive"); - DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int) - set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE) - { - uint opt = (set_keep_alive) ? 1 : 0; - r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, - sizeof(opt)); - } - DBUG_RETURN(r); -} - - -my_bool -vio_ssl_should_retry(Vio * vio __attribute__((unused))) +int vio_ssl_close(Vio *vio) { - int en = socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK); -} - - -my_bool -vio_ssl_was_interrupted(Vio *vio __attribute__((unused))) -{ - int en= socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); -} - - -int vio_ssl_close(Vio * vio) -{ - int r; + int r= 0; + SSL *ssl= (SSL*)vio->ssl_arg; DBUG_ENTER("vio_ssl_close"); - r=0; - if ((SSL*) vio->ssl_arg) - { - r = SSL_shutdown((SSL*) vio->ssl_arg); - SSL_free((SSL*) vio->ssl_arg); - vio->ssl_arg= 0; - } - if (vio->sd >= 0) - { - if (shutdown(vio->sd, 2)) - r= -1; - if (closesocket(vio->sd)) - r= -1; - } - if (r) - { - DBUG_PRINT("error", ("close() failed, error: %d",socket_errno)); - report_errors(); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->sd= -1; - DBUG_RETURN(r); -} - - -const char *vio_ssl_description(Vio * vio) -{ - return vio->desc; -} - -enum enum_vio_type vio_ssl_type(Vio* vio) -{ - return vio->type; -} - -my_socket vio_ssl_fd(Vio* vio) -{ - return vio->sd; -} - -my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port) -{ - DBUG_ENTER("vio_ssl_peer_addr"); - DBUG_PRINT("enter", ("sd: %d", vio->sd)); - if (vio->localhost) - { - strmov(buf,"127.0.0.1"); - *port=0; - } - else + if (ssl) { - size_socket addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), - &addrLen) != 0) + switch ((r= SSL_shutdown(ssl))) { - DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); - DBUG_RETURN(1); + case 1: /* Shutdown successful */ + break; + case 0: /* Shutdown not yet finished, call it again */ + if ((r= SSL_shutdown(ssl) >= 0)) + break; + /* Fallthrough */ + default: /* Shutdown failed */ + DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s", + SSL_get_error(ssl, r))); + break; } -#ifdef TO_BE_FIXED - my_inet_ntoa(vio->remote.sin_addr,buf); - *port= 0; -#else - strmov(buf, "unknown"); - *port= 0; -#endif + SSL_free(ssl); + vio->ssl_arg= 0; } - DBUG_PRINT("exit", ("addr: %s", buf)); - DBUG_RETURN(0); -} - - -void vio_ssl_in_addr(Vio *vio, struct in_addr *in) -{ - DBUG_ENTER("vio_ssl_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; + DBUG_RETURN(vio_close(vio)); } -/* - TODO: Add documentation -*/ - -int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) +int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) { - char *str; - char buf[1024]; - X509* client_cert; + SSL *ssl; + X509 *client_cert; my_bool unused; my_bool net_blocking; enum enum_vio_type old_type; DBUG_ENTER("sslaccept"); - DBUG_PRINT("enter", ("sd: %d ptr: Ox%p, timeout: %d", + DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d", vio->sd, ptr, timeout)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + net_blocking= vio_is_blocking(vio); vio_blocking(vio, 1, &unused); /* Must be called before reset */ - vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); - vio->ssl_arg= 0; - if (!(vio->ssl_arg= (void*) SSL_new(ptr->ssl_context))) + vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE); + + if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); report_errors(); @@ -291,144 +153,126 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: Ox%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd((SSL*) vio->ssl_arg,vio->sd); - SSL_set_accept_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_accept_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); - SSL_free((SSL*) vio->ssl_arg); + SSL_free(ssl); vio->ssl_arg= 0; vio_reset(vio, old_type,vio->sd,0,FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } + #ifndef DBUG_OFF - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (client_cert != NULL) { - DBUG_PRINT("info",("Client certificate:")); - str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free (str); + char buf[1024]; + DBUG_PRINT("info",("cipher_name= '%s'", SSL_get_cipher_name(ssl))); - str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free (str); + if ((client_cert= SSL_get_peer_certificate (ssl))) + { + DBUG_PRINT("info",("Client certificate:")); + X509_NAME_oneline (X509_get_subject_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t subject: %s", buf)); - X509_free (client_cert); - } - else - DBUG_PRINT("info",("Client does not have certificate.")); + X509_NAME_oneline (X509_get_issuer_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t issuer: %s", buf)); - str=SSL_get_shared_ciphers((SSL*) vio->ssl_arg, buf, sizeof(buf)); - if (str) - { - DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str)); - } - else - { - DBUG_PRINT("info",("no shared ciphers!")); - } + X509_free (client_cert); + } + else + DBUG_PRINT("info",("Client does not have certificate.")); + if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) + { + DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); + } + else + DBUG_PRINT("info",("no shared ciphers!")); + } #endif + DBUG_RETURN(0); } -int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) +int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) { - char *str; - X509* server_cert; + SSL *ssl; + X509 *server_cert; my_bool unused; my_bool net_blocking; - enum enum_vio_type old_type; + enum enum_vio_type old_type; + DBUG_ENTER("sslconnect"); - DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p", - vio->sd,ptr,ptr->ssl_context)); + DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p", + vio->sd, ptr, ptr->ssl_context)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + net_blocking= vio_is_blocking(vio); vio_blocking(vio, 1, &unused); /* Must be called before reset */ - vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); - vio->ssl_arg= 0; - if (!(vio->ssl_arg = SSL_new(ptr->ssl_context))) + vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE); + if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); report_errors(); - vio_reset(vio, old_type,vio->sd,0,FALSE); - vio_blocking(vio, net_blocking, &unused); + vio_reset(vio, old_type, vio->sd, 0, FALSE); + vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: 0x%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd ((SSL*) vio->ssl_arg, vio_ssl_fd(vio)); - SSL_set_connect_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_connect_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); - SSL_free((SSL*) vio->ssl_arg); + SSL_free(ssl); vio->ssl_arg= 0; - vio_reset(vio, old_type,vio->sd,0,FALSE); + vio_reset(vio, old_type, vio->sd, 0, FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); - } + } #ifndef DBUG_OFF - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - server_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (server_cert != NULL) + DBUG_PRINT("info",("cipher_name: '%s'" , SSL_get_cipher_name(ssl))); + + if ((server_cert= SSL_get_peer_certificate (ssl))) { + char buf[256]; DBUG_PRINT("info",("Server certificate:")); - str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free(str); - - str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free(str); - - /* - We could do all sorts of certificate verification stuff here before - deallocating the certificate. - */ + X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf)); + DBUG_PRINT("info",("\t subject: %s", buf)); + X509_NAME_oneline (X509_get_issuer_name(server_cert), buf, sizeof(buf)); + DBUG_PRINT("info",("\t issuer: %s", buf)); X509_free (server_cert); } else DBUG_PRINT("info",("Server does not have certificate.")); #endif + DBUG_RETURN(0); } -int vio_ssl_blocking(Vio * vio __attribute__((unused)), +int vio_ssl_blocking(Vio *vio __attribute__((unused)), my_bool set_blocking_mode, my_bool *old_mode) { + /* Mode is always blocking */ + *old_mode= 1; /* Return error if we try to change to non_blocking mode */ - *old_mode=1; /* Mode is always blocking */ - return set_blocking_mode ? 0 : 1; + return (set_blocking_mode ? 0 : 1); } - -void vio_ssl_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) -{ -#ifdef __WIN__ - ulong wait_timeout= (ulong) timeout * 1000; - (void) setsockopt(vio->sd, SOL_SOCKET, - which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout, - sizeof(wait_timeout)); -#endif /* __WIN__ */ -} #endif /* HAVE_OPENSSL */ diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 4ee27f1e491..2b3e80a98e4 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -21,7 +21,6 @@ static bool ssl_algorithms_added = FALSE; static bool ssl_error_strings_loaded= FALSE; static int verify_depth = 0; -static int verify_error = X509_V_OK; static unsigned char dh512_p[]= { @@ -82,30 +81,31 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) DBUG_ENTER("vio_set_cert_stuff"); DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s", ctx, cert_file, key_file)); - if (cert_file != NULL) + if (cert_file) { - if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file)); + DBUG_PRINT("error",("unable to get certificate from '%s'\n", cert_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file); fflush(stderr); - DBUG_RETURN(0); + DBUG_RETURN(1); } - if (key_file == NULL) - key_file = cert_file; - if (SSL_CTX_use_PrivateKey_file(ctx,key_file, - SSL_FILETYPE_PEM) <= 0) + + if (!key_file) + key_file= cert_file; + + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file)); + DBUG_PRINT("error", ("unable to get private key from '%s'\n", key_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); fprintf(stderr,"Unable to get private key from '%s'\n", cert_file); - fflush(stderr); - DBUG_RETURN(0); + fflush(stderr); + DBUG_RETURN(1); } /* @@ -116,45 +116,45 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) { DBUG_PRINT("error", ("Private key does not match the certificate public key\n")); - DBUG_RETURN(0); + DBUG_RETURN(1); } } - DBUG_RETURN(1); + DBUG_RETURN(0); } static int vio_verify_callback(int ok, X509_STORE_CTX *ctx) { - char buf[256]; - X509* err_cert; - int err,depth; + char buf[256]; + X509 *err_cert; DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d, ctx: 0x%p", ok, ctx)); - err_cert=X509_STORE_CTX_get_current_cert(ctx); - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); + DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx)); - X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf)); + err_cert= X509_STORE_CTX_get_current_cert(ctx); + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + DBUG_PRINT("info", ("cert: %s", buf)); if (!ok) { - DBUG_PRINT("error",("verify error: num: %d : '%s'\n",err, + int err, depth; + err= X509_STORE_CTX_get_error(ctx); + depth= X509_STORE_CTX_get_error_depth(ctx); + + DBUG_PRINT("error",("verify error: %d, '%s'",err, X509_verify_cert_error_string(err))); + /* + Approve cert if depth is greater then "verify_depth", currently + verify_depth is always 0 and there is no way to increase it. + */ if (verify_depth >= depth) - { - ok=1; - verify_error=X509_V_OK; - } - else - { - verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; - } + ok= 1; } - switch (ctx->error) { + switch (ctx->error) + { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256); - DBUG_PRINT("info",("issuer= %s\n",buf)); + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); + DBUG_PRINT("info",("issuer= %s\n", buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: @@ -198,193 +198,149 @@ static void netware_ssl_init() #endif /* __NETWARE__ */ -/************************ VioSSLConnectorFd **********************************/ -/* - TODO: - Add option --verify to mysql to be able to change verification mode -*/ - -struct st_VioSSLConnectorFd * -new_VioSSLConnectorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path, - const char* cipher) +static void check_ssl_init() { - int verify = SSL_VERIFY_NONE; - struct st_VioSSLConnectorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLConnectorFd"); - - if (!(ptr=((struct st_VioSSLConnectorFd*) - my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0))))) - DBUG_RETURN(0); - - ptr->ssl_context= 0; - ptr->ssl_method= 0; - /* FIXME: constants! */ - if (!ssl_algorithms_added) { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; + ssl_algorithms_added= TRUE; SSL_library_init(); OpenSSL_add_all_algorithms(); + } + #ifdef __NETWARE__ netware_ssl_init(); #endif if (!ssl_error_strings_loaded) { - DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; + ssl_error_strings_loaded= TRUE; SSL_load_error_strings(); } - ptr->ssl_method = TLSv1_client_method(); - ptr->ssl_context = SSL_CTX_new(ptr->ssl_method); - DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context)); - if (ptr->ssl_context == 0) +} + +/************************ VioSSLFd **********************************/ +struct st_VioSSLFd * +new_VioSSLFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher, SSL_METHOD *method) +{ + DH *dh; + struct st_VioSSLFd *ssl_fd; + DBUG_ENTER("new_VioSSLFd"); + + check_ssl_init(); + + if (!(ssl_fd= ((struct st_VioSSLFd*) + my_malloc(sizeof(struct st_VioSSLFd),MYF(0))))) + DBUG_RETURN(0); + + if (!(ssl_fd->ssl_context= SSL_CTX_new(method))) { DBUG_PRINT("error", ("SSL_CTX_new failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - /* - SSL_CTX_set_options - SSL_CTX_set_info_callback - */ - if (cipher) + + /* Set the ciphers that can be used */ + if (cipher && SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher)) { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + DBUG_PRINT("error", ("failed to set ciphers to use")); + report_errors(); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) + + if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file)) { DBUG_PRINT("error", ("vio_set_cert_stuff failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0) + + if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0) { DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0) + if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0) { DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - } + } /* DH stuff */ dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); + SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh); DH_free(dh); - DBUG_RETURN(ptr); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr)ptr,MYF(0)); - DBUG_RETURN(0); + DBUG_PRINT("exit", ("OK 1")); + + DBUG_RETURN(ssl_fd); } -/************************ VioSSLAcceptorFd **********************************/ -/* - TODO: - Add option --verify to mysqld to be able to change verification mode -*/ -struct st_VioSSLAcceptorFd* -new_VioSSLAcceptorFd(const char *key_file, - const char *cert_file, - const char *ca_file, - const char *ca_path, - const char *cipher) +/************************ VioSSLConnectorFd **********************************/ +struct st_VioSSLFd * +new_VioSSLConnectorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) { - int verify = (SSL_VERIFY_PEER | - SSL_VERIFY_CLIENT_ONCE); - struct st_VioSSLAcceptorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLAcceptorFd"); + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_client_method()))) + { + return 0; + } - ptr= ((struct st_VioSSLAcceptorFd*) - my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0))); - ptr->ssl_context=0; - ptr->ssl_method=0; - /* FIXME: constants! */ - ptr->session_id_context= ptr; + /* Init the the VioSSLFd as a "connector" ie. the client side */ - if (!ssl_algorithms_added) - { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; - SSL_library_init(); - OpenSSL_add_all_algorithms(); + /* + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. + */ + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); - } -#ifdef __NETWARE__ - netware_ssl_init(); -#endif + return ssl_fd; +} - if (!ssl_error_strings_loaded) - { - DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; - SSL_load_error_strings(); - } - ptr->ssl_method= TLSv1_server_method(); - ptr->ssl_context= SSL_CTX_new(ptr->ssl_method); - if (ptr->ssl_context == 0) - { - DBUG_PRINT("error", ("SSL_CTX_new failed")); - report_errors(); - goto ctor_failure; - } - if (cipher) + +/************************ VioSSLAcceptorFd **********************************/ +struct st_VioSSLFd* +new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) +{ + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_server_method()))) { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + return 0; } - /* SSL_CTX_set_quiet_shutdown(ctx,1); */ - SSL_CTX_sess_set_cache_size(ptr->ssl_context,128); + /* Init the the VioSSLFd as a "acceptor" ie. the server side */ - /* DH? */ - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - SSL_CTX_set_session_id_context(ptr->ssl_context, - (const uchar*) &(ptr->session_id_context), - sizeof(ptr->session_id_context)); + /* Set max number of cached sessions, returns the previous size */ + SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); /* - SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. */ - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) - { - DBUG_PRINT("error", ("vio_set_cert_stuff failed")); - report_errors(); - goto ctor_failure; - } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0) - { - DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0) - { - DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); - report_errors(); - goto ctor_failure; - } - } - /* DH stuff */ - dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); - DH_free(dh); - DBUG_RETURN(ptr); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr) ptr,MYF(0)); - DBUG_RETURN(0); + /* + Set session_id - an identifier for this server session + Use the ssl_fd pointer + */ + SSL_CTX_set_session_id_context(ssl_fd->ssl_context, + ssl_fd, + sizeof(ssl_fd)); + + return ssl_fd; } #endif /* HAVE_OPENSSL */ |