#At file:///Users/tnurnberg/forest/21287/55-21287/ based on revid:dao-gang.qu@stripped
3229 Tatiana Azundris Nurnberg 2011-04-28
Bug#11745920/Bug#21287: "SSL connection error" is not helpful! (ssl-verify-server-cert=true vs localhos)
SSL errors on client now more specific to aid end-user with
debugging.
@ include/violite.h
new_VioSSLConnectorFd/sslaccept/sslconnect new return more elaborate status
@ libmysql/errmsg.c
SSL errors now extended, more specific
@ mysql-test/r/openssl_1.result
SSL error messages now more specific
@ sql-common/client.c
ssl_verify_server_cert: we work out what's wrong, might as
well tell the user.
Do more detailed error reporting for setup, connect, and
server cert verifying phases.
@ sql/sql_acl.cc
sslaccept() signature has changed
@ vio/viossl.c
don't just print low level SSL problems to debug trace,
save the error code and return it to callers of sslaccept
and sslconnect!
@ vio/viosslfactories.c
new_VioSSLConnectorFd() now returns error codes from
new_VioSSLFd() rather than discard them.
modified:
include/violite.h
libmysql/errmsg.c
mysql-test/r/openssl_1.result
sql-common/client.c
sql/sql_acl.cc
vio/test-ssl.c
vio/test-sslclient.c
vio/test-sslserver.c
vio/viossl.c
vio/viosslfactories.c
vio/viotest-ssl.c
=== modified file 'include/violite.h'
--- a/include/violite.h 2010-06-07 14:01:39 +0000
+++ b/include/violite.h 2011-04-28 10:51:56 +0000
@@ -132,13 +132,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,
=== modified file 'libmysql/errmsg.c'
--- a/libmysql/errmsg.c 2010-11-24 10:23:44 +0000
+++ b/libmysql/errmsg.c 2011-04-28 10:51:56 +0000
@@ -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",
=== modified file 'mysql-test/r/openssl_1.result'
--- a/mysql-test/r/openssl_1.result 2010-01-29 14:54:27 +0000
+++ b/mysql-test/r/openssl_1.result 2011-04-28 10:51:56 +0000
@@ -44,13 +44,13 @@ ERROR 42000: DELETE command denied to us
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
=== modified file 'sql-common/client.c'
--- a/sql-common/client.c 2010-11-10 15:21:51 +0000
+++ b/sql-common/client.c 2011-04-28 10:51:56 +0000
@@ -1850,6 +1850,7 @@ mysql_get_ssl_cipher(MYSQL *mysql __attr
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
@@ -1859,7 +1860,7 @@ mysql_get_ssl_cipher(MYSQL *mysql __attr
#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;
@@ -1870,19 +1871,19 @@ static int ssl_verify_server_cert(Vio *v
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);
}
@@ -1911,7 +1912,7 @@ static int ssl_verify_server_cert(Vio *v
DBUG_RETURN(0);
}
}
- DBUG_PRINT("error", ("SSL certificate validation failure"));
+ *errptr= "SSL certificate validation failure";
DBUG_RETURN(1);
}
@@ -2492,6 +2493,9 @@ static int send_client_reply_packet(MCPV
/* 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
@@ -2511,9 +2515,11 @@ static int send_client_reply_packet(MCPV
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;
@@ -2521,18 +2527,24 @@ static int send_client_reply_packet(MCPV
/* Connect to the server */
DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslconnect(ssl_fd, net->vio,
- (long) (mysql->options.connect_timeout)))
- {
- set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
+ (long) (mysql->options.connect_timeout), &ssl_error))
+ {
+ 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;
}
}
@@ -3061,7 +3073,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
VIO_LOCALHOST | VIO_BUFFERED_READ);
if (!net->vio)
{
- DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+ DBUG_PRINT("error",("Unknown protocol %d ", mysql->options.protocol));
set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
closesocket(sock);
goto error;
@@ -3237,7 +3249,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
if (! net->vio )
{
- DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
+ DBUG_PRINT("error",("Unknown protocol %d ", mysql->options.protocol));
set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
closesocket(sock);
goto error;
@@ -3247,7 +3259,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
DBUG_PRINT("info", ("net->vio: %p", net->vio));
if (!net->vio)
{
- DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
+ DBUG_PRINT("error",("Unknown protocol %d ",mysql->options.protocol));
set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
goto error;
}
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2010-12-17 11:11:34 +0000
+++ b/sql/sql_acl.cc 2011-04-28 10:51:56 +0000
@@ -8395,13 +8395,14 @@ static ulong parse_client_handshake_pack
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;
=== modified file 'vio/test-ssl.c'
--- a/vio/test-ssl.c 2010-07-15 11:13:30 +0000
+++ b/vio/test-ssl.c 2011-04-28 10:51:56 +0000
@@ -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);
=== modified file 'vio/test-sslclient.c'
--- a/vio/test-sslclient.c 2010-07-08 21:20:08 +0000
+++ b/vio/test-sslclient.c 2011-04-28 10:51:56 +0000
@@ -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);
=== modified file 'vio/test-sslserver.c'
--- a/vio/test-sslserver.c 2010-07-08 21:20:08 +0000
+++ b/vio/test-sslserver.c 2011-04-28 10:51:56 +0000
@@ -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;
}
=== modified file 'vio/viossl.c'
--- a/vio/viossl.c 2010-08-16 12:50:27 +0000
+++ b/vio/viossl.c 2011-04-28 10:51:56 +0000
@@ -24,10 +24,12 @@
#ifdef HAVE_OPENSSL
-static void
+#include <openssl/err.h>
+
+static unsigned long
report_errors(SSL* ssl)
{
- unsigned long l;
+ unsigned long l, p= 0;
const char *file;
const char *data;
int line, flags;
@@ -41,14 +43,18 @@ report_errors(SSL* ssl)
{
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
+ p= l;
}
if (ssl)
- DBUG_PRINT("error", ("error: %s",
- ERR_error_string(SSL_get_error(ssl, l), buf)));
+ {
+ p= SSL_get_error(ssl, p);
+ DBUG_PRINT("error", ("SSL error: %lu - %s",
+ p, ERR_error_string(p, buf)));
+ }
DBUG_PRINT("info", ("socket_errno: %d", socket_errno));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(p);
}
@@ -144,7 +150,7 @@ 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)
{
SSL *ssl;
my_bool unused;
@@ -160,7 +166,7 @@ static int ssl_do(struct st_VioSSLFd *pt
if (!(ssl= SSL_new(ptr->ssl_context)))
{
DBUG_PRINT("error", ("SSL_new failure"));
- report_errors(ssl);
+ *errptr= report_errors(ssl);
vio_blocking(vio, was_blocking, &unused);
DBUG_RETURN(1);
}
@@ -172,7 +178,7 @@ static int ssl_do(struct st_VioSSLFd *pt
if (connect_accept_func(ssl) < 1)
{
DBUG_PRINT("error", ("SSL_connect/accept failure"));
- report_errors(ssl);
+ *errptr= report_errors(ssl);
SSL_free(ssl);
vio_blocking(vio, was_blocking, &unused);
DBUG_RETURN(1);
@@ -220,17 +226,17 @@ static int ssl_do(struct st_VioSSLFd *pt
}
-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));
}
=== modified file 'vio/viosslfactories.c'
--- a/vio/viosslfactories.c 2010-07-15 11:13:30 +0000
+++ b/vio/viosslfactories.c 2011-04-28 10:51:56 +0000
@@ -249,11 +249,10 @@ new_VioSSLFd(const char *key_file, const
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_fi
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;
}
=== modified file 'vio/viotest-ssl.c'
--- a/vio/viotest-ssl.c 2010-07-08 21:20:08 +0000
+++ b/vio/viotest-ssl.c 2011-04-28 10:51:56 +0000
@@ -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);
Attachment: [text/bzr-bundle] bzr/azundris@sun.com-20110428105156-hp6z05r5v9j7zglj.bundle