diff options
author | Tatjana Azundris Nuernberg <tatjana.nuernberg@oracle.com> | 2011-05-19 10:47:43 +0100 |
---|---|---|
committer | Tatjana Azundris Nuernberg <tatjana.nuernberg@oracle.com> | 2011-05-19 10:47:43 +0100 |
commit | cf80c6cb642d5f82a53f38a41742c94a2c768dbf (patch) | |
tree | d077b2f692ced3f83d965153a609265891c06dda | |
parent | 47f7fc4353f4ee665b703bee6479ad1664db0f48 (diff) | |
download | mariadb-git-cf80c6cb642d5f82a53f38a41742c94a2c768dbf.tar.gz |
Bug#11745920/Bug#21287: "SSL connection error" is not helpful! (ssl-verify-server-cert=true vs localhos)
SSL errors on client and now more specific to aid end-user
with debugging. Also restructures error handling for
compliance with SSL docs.
include/violite.h:
new_VioSSLConnectorFd/sslaccept/sslconnect return more elaborate status
libmysql/errmsg.c:
SSL errors now extended, more specific
mysql-test/r/openssl_1.result:
SSL errors now extended, more specific
sql-common/client.c:
Do more detailed error reporting for setup, connect, and
server cert verifying phases.
sql/sql_acl.cc:
sslaccept() signature has changed
vio/viossl.c:
Save the error code and return it to callers of sslaccept
and sslconnect.
vio/viosslfactories.c:
new_VioSSLConnectorFd(): return error code to caller
-rw-r--r-- | include/violite.h | 6 | ||||
-rw-r--r-- | libmysql/errmsg.c | 2 | ||||
-rw-r--r-- | mysql-test/r/openssl_1.result | 14 | ||||
-rw-r--r-- | sql-common/client.c | 35 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | vio/test-ssl.c | 9 | ||||
-rw-r--r-- | vio/test-sslclient.c | 8 | ||||
-rw-r--r-- | vio/test-sslserver.c | 3 | ||||
-rw-r--r-- | vio/viossl.c | 17 | ||||
-rw-r--r-- | vio/viosslfactories.c | 7 | ||||
-rw-r--r-- | vio/viotest-ssl.c | 9 |
11 files changed, 69 insertions, 45 deletions
diff --git a/include/violite.h b/include/violite.h index 140f021ebb4..ba057028ed2 100644 --- a/include/violite.h +++ b/include/violite.h @@ -134,13 +134,13 @@ struct st_VioSSLFd SSL_CTX *ssl_context; }; -int sslaccept(struct st_VioSSLFd*, Vio *, long timeout); -int sslconnect(struct st_VioSSLFd*, Vio *, long timeout); +int sslaccept(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); +int sslconnect(struct st_VioSSLFd*, Vio *, long timeout, unsigned long *errptr); struct st_VioSSLFd *new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, - const char *cipher); + const char *cipher, enum enum_ssl_init_error* error); struct st_VioSSLFd *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, const char *ca_file,const char *ca_path, diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index b99b3f2de30..a2d066b1eba 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -51,7 +51,7 @@ const char *client_errors[]= "Error on SHOW SLAVE HOSTS:", "Error connecting to slave:", "Error connecting to master:", - "SSL connection error", + "SSL connection error: %-.100s", "Malformed packet", "This client library is licensed only for use with MySQL servers having '%s' license", "Invalid use of null pointer", diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 6389438c993..72bbaa71da5 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -44,13 +44,13 @@ ERROR 42000: DELETE command denied to user 'ssl_user4'@'localhost' for table 't1 drop user ssl_user1@localhost, ssl_user2@localhost, ssl_user3@localhost, ssl_user4@localhost, ssl_user5@localhost; drop table t1; -mysqltest: Could not open connection 'default': 2026 SSL connection error -mysqltest: Could not open connection 'default': 2026 SSL connection error -mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation +mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation +mysqltest: Could not open connection 'default': 2026 SSL connection error: ASN: bad other signature confirmation SSL error: Unable to get private key from '' -mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error: Unable to get private key SSL error: Unable to get certificate from '' -mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error: Unable to get certificate SHOW STATUS LIKE 'Ssl_cipher'; Variable_name Value Ssl_cipher DHE-RSA-AES256-SHA @@ -83,7 +83,7 @@ Ssl_cipher AES128-SHA SHOW STATUS LIKE 'Ssl_cipher'; Variable_name Value Ssl_cipher AES128-SHA -mysqltest: Could not open connection 'default': 2026 SSL connection error +mysqltest: Could not open connection 'default': 2026 SSL connection error: SSL_CTX_new failed CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -189,7 +189,7 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; SSL error: Unable to get private key from 'MYSQL_TEST_DIR/std_data/client-cert.pem' -mysqldump: Got error: 2026: SSL connection error when trying to connect +mysqldump: Got error: 2026: SSL connection error: Unable to get private key when trying to connect DROP TABLE t1; Variable_name Value Ssl_cipher DHE-RSA-AES256-SHA diff --git a/sql-common/client.c b/sql-common/client.c index abaea310aae..f38467ff731 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1840,6 +1840,8 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused))) ssl_verify_server_cert() vio pointer to a SSL connected vio server_hostname name of the server that we connected to + errptr if we fail, we'll return (a pointer to a string + describing) the reason here RETURN VALUES 0 Success @@ -1849,7 +1851,7 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused))) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) -static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) +static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr) { SSL *ssl; X509 *server_cert; @@ -1860,19 +1862,19 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) if (!(ssl= (SSL*)vio->ssl_arg)) { - DBUG_PRINT("error", ("No SSL pointer found")); + *errptr= "No SSL pointer found"; DBUG_RETURN(1); } if (!server_hostname) { - DBUG_PRINT("error", ("No server hostname supplied")); + *errptr= "No server hostname supplied"; DBUG_RETURN(1); } if (!(server_cert= SSL_get_peer_certificate(ssl))) { - DBUG_PRINT("error", ("Could not get server certificate")); + *errptr= "Could not get server certificate"; DBUG_RETURN(1); } @@ -1901,7 +1903,7 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) DBUG_RETURN(0); } } - DBUG_PRINT("error", ("SSL certificate validation failure")); + *errptr= "SSL certificate validation failure"; DBUG_RETURN(1); } @@ -2507,6 +2509,9 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, /* Do the SSL layering. */ struct st_mysql_options *options= &mysql->options; struct st_VioSSLFd *ssl_fd; + enum enum_ssl_init_error ssl_init_error; + const char *cert_error; + unsigned long ssl_error; /* Send mysql->client_flag, max_packet_size - unencrypted otherwise @@ -2526,9 +2531,11 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, options->ssl_cert, options->ssl_ca, options->ssl_capath, - options->ssl_cipher))) + options->ssl_cipher, + &ssl_init_error))) { - set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), sslGetErrString(ssl_init_error)); goto error; } mysql->connector_fd= (unsigned char *) ssl_fd; @@ -2536,18 +2543,24 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, /* Connect to the server */ DBUG_PRINT("info", ("IO layer change in progress...")); if (sslconnect(ssl_fd, net->vio, - (long) (mysql->options.connect_timeout))) + (long) (mysql->options.connect_timeout), &ssl_error)) { - set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); + char buf[512]; + ERR_error_string_n(ssl_error, buf, 512); + buf[511]= 0; + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), + buf); goto error; } DBUG_PRINT("info", ("IO layer change done!")); /* Verify server cert */ if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && - ssl_verify_server_cert(net->vio, mysql->host)) + ssl_verify_server_cert(net->vio, mysql->host, &cert_error)) { - set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); + set_mysql_extended_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate, + ER(CR_SSL_CONNECTION_ERROR), cert_error); goto error; } } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0eb05489015..5056fb32bc7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -8528,14 +8528,14 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, DBUG_PRINT("info", ("client capabilities: %lu", mpvio->client_capabilities)); if (mpvio->client_capabilities & CLIENT_SSL) { - char error_string[1024] __attribute__((unused)); + unsigned long errptr; /* Do the SSL layering. */ if (!ssl_acceptor_fd) return packet_error; DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout)) + if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, &errptr)) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); return packet_error; diff --git a/vio/test-ssl.c b/vio/test-ssl.c index 1e846727d00..4d158ae83f7 100644 --- a/vio/test-ssl.c +++ b/vio/test-ssl.c @@ -59,6 +59,9 @@ main(int argc, char** argv) struct st_VioSSLFd* ssl_acceptor= 0; struct st_VioSSLFd* ssl_connector= 0; Vio* client_vio=0, *server_vio=0; + enum enum_ssl_init_error ssl_init_error; + unsigned long ssl_error; + MY_INIT(argv[0]); DBUG_PROCESS(argv[0]); DBUG_PUSH(default_dbug_option); @@ -91,16 +94,16 @@ main(int argc, char** argv) ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path, cipher); ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, - ca_path, cipher); + ca_path, cipher, &ssl_init_error); client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); client_vio->sd = sv[0]; client_vio->vioblocking(client_vio, 0, &unused); - sslconnect(ssl_connector,client_vio,60L); + sslconnect(ssl_connector,client_vio,60L,&ssl_error); server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); server_vio->sd = sv[1]; server_vio->vioblocking(client_vio, 0, &unused); - sslaccept(ssl_acceptor,server_vio,60L); + sslaccept(ssl_acceptor,server_vio,60L, &ssl_error); printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd); diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c index 643dcbf2c8e..9d8a741e313 100644 --- a/vio/test-sslclient.c +++ b/vio/test-sslclient.c @@ -50,6 +50,9 @@ main( int argc __attribute__((unused)), Vio* client_vio=0; int err; char xbuf[100]="Ohohhhhoh1234"; + enum enum_ssl_init_error ssl_init_error; + unsigned long ssl_error; + MY_INIT(argv[0]); DBUG_PROCESS(argv[0]); DBUG_PUSH(default_dbug_option); @@ -60,7 +63,8 @@ main( int argc __attribute__((unused)), if (ca_path!=0) printf("CApath : %s\n", ca_path); - ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher); + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher, + &ssl_init_error); if(!ssl_connector) { fatal_error("client:new_VioSSLConnectorFd failed"); } @@ -81,7 +85,7 @@ main( int argc __attribute__((unused)), /* ----------------------------------------------- */ /* Now we have TCP conncetion. Start SSL negotiation. */ read(client_vio->sd,xbuf, sizeof(xbuf)); - sslconnect(ssl_connector,client_vio,60L); + sslconnect(ssl_connector,client_vio,60L,&ssl_error); err = vio_read(client_vio,xbuf, sizeof(xbuf)); if (err<=0) { my_free(ssl_connector); diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c index 3123a4def2c..35cfa26bd00 100644 --- a/vio/test-sslserver.c +++ b/vio/test-sslserver.c @@ -52,6 +52,7 @@ do_ssl_stuff( TH_ARGS* args) const char* s = "Huhuhuhuuu"; Vio* server_vio; int err; + unsigned long ssl_error; DBUG_ENTER("do_ssl_stuff"); server_vio = vio_new(args->sd, VIO_TYPE_TCPIP, TRUE); @@ -60,7 +61,7 @@ do_ssl_stuff( TH_ARGS* args) /* TCP connection is ready. Do server side SSL. */ err = write(server_vio->sd,(uchar*)s, strlen(s)); - sslaccept(args->ssl_acceptor,server_vio,60L); + sslaccept(args->ssl_acceptor,server_vio,60L,&ssl_error); err = server_vio->write(server_vio,(uchar*)s, strlen(s)); DBUG_VOID_RETURN; } diff --git a/vio/viossl.c b/vio/viossl.c index 5cb5f36f20d..290abf788c2 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -144,8 +144,9 @@ void vio_ssl_delete(Vio *vio) static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, - int (*connect_accept_func)(SSL*)) + int (*connect_accept_func)(SSL*), unsigned long *errptr) { + int r; SSL *ssl; my_bool unused; my_bool was_blocking; @@ -160,7 +161,7 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); - report_errors(ssl); + *errptr= ERR_get_error(); vio_blocking(vio, was_blocking, &unused); DBUG_RETURN(1); } @@ -169,10 +170,10 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_set_fd(ssl, vio->sd); - if (connect_accept_func(ssl) < 1) + if ((r= connect_accept_func(ssl)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); - report_errors(ssl); + *errptr= SSL_get_error(ssl, r); SSL_free(ssl); vio_blocking(vio, was_blocking, &unused); DBUG_RETURN(1); @@ -220,17 +221,17 @@ static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, } -int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr) { DBUG_ENTER("sslaccept"); - DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept)); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept, errptr)); } -int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout, unsigned long *errptr) { DBUG_ENTER("sslconnect"); - DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect)); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect, errptr)); } diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 4971dec37fb..4f4dd5758ba 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -165,7 +165,7 @@ static 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, - enum enum_ssl_init_error* error) + enum enum_ssl_init_error *error) { DH *dh; struct st_VioSSLFd *ssl_fd; @@ -249,11 +249,10 @@ new_VioSSLFd(const char *key_file, const char *cert_file, struct st_VioSSLFd * new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *ca_file, const char *ca_path, - const char *cipher) + const char *cipher, enum enum_ssl_init_error* error) { struct st_VioSSLFd *ssl_fd; int verify= SSL_VERIFY_PEER; - enum enum_ssl_init_error dummy; /* Turn off verification of servers certificate if both @@ -263,7 +262,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, verify= SSL_VERIFY_NONE; if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, - ca_path, cipher, TLSv1_client_method(), &dummy))) + ca_path, cipher, TLSv1_client_method(), error))) { return 0; } diff --git a/vio/viotest-ssl.c b/vio/viotest-ssl.c index 5c68e861d2a..90489b46605 100644 --- a/vio/viotest-ssl.c +++ b/vio/viotest-ssl.c @@ -60,6 +60,9 @@ int main(int argc, char **argv) struct st_VioSSLConnectorFd* ssl_connector=0; Vio* client_vio=0; Vio* server_vio=0; + enum enum_ssl_init_error ssl_init_error; + unsigned long ssl_error; + MY_INIT(argv[0]); DBUG_PROCESS(argv[0]); DBUG_PUSH(default_dbug_option); @@ -92,14 +95,14 @@ int main(int argc, char **argv) ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path); ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, - ca_path); + ca_path, &ssl_init_error); client_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); client_vio->sd = sv[0]; - sslconnect(ssl_connector,client_vio); + sslconnect(ssl_connector,client_vio,&ssl_error); server_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); server_vio->sd = sv[1]; - sslaccept(ssl_acceptor,server_vio); + sslaccept(ssl_acceptor,server_vio,&ssl_error); printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd); |