Commit 9c3a03a2 authored by unknown's avatar unknown

Bug#28812 rpl_ssl fails due to assert in extra/yassl/src/socket_wrapper.cpp:117

 - Merge sslaccept and sslconnect.
 - Atomically "reset" vio to VIO_TYPE_SSL when the SSL connection has
   succeeded, this avoids having to revert anything and thus protects
   against "close_active_vio" in the middle.
 - Add some variance to the testcase


mysql-test/t/rpl_ssl.test:
  Add some variance by running two selects before stopping the slave
  Check that number of records in t1 are equal on master and slave
vio/viossl.c:
  Rewrite sslconnect and sslaccept to automically "reset" the vio
  to VIO_TYPE_SSL. Also use the fd from 'SSL_get_fd' to avoid
  setting vio->sd to -1, that previously occured when "close_active_vio"
  was called during connect/accept.
  
  Merge the two function since they were exactly the same except for one line.
  
  Update the DBUG printouts to be generic(i.e use peer instead of client/server).
parent e878be4c
...@@ -41,24 +41,39 @@ select * from t1; ...@@ -41,24 +41,39 @@ select * from t1;
# Do the same thing a number of times # Do the same thing a number of times
disable_query_log; disable_query_log;
disable_result_log;
let $i= 100; let $i= 100;
while ($i) while ($i)
{ {
start slave; start slave;
connection master; connection master;
insert into t1 values (NULL); insert into t1 values (NULL);
select * from t1; # Some variance
connection slave; connection slave;
select * from t1; # Some variance
stop slave; stop slave;
dec $i; dec $i;
} }
start slave; start slave;
enable_query_log; enable_query_log;
enable_result_log;
connection master; connection master;
insert into t1 values (NULL); insert into t1 values (NULL);
let $master_count= `select count(*) from t1`;
sync_slave_with_master; sync_slave_with_master;
--source include/wait_for_slave_to_start.inc --source include/wait_for_slave_to_start.inc
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # --replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 #
query_vertical show slave status; query_vertical show slave status;
let $slave_count= `select count(*) from t1`;
if (`select $slave_count != $master_count`)
{
echo master and slave differed in number of rows;
echo master: $master_count;
echo slave: $slave_count;
}
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -172,67 +172,79 @@ void vio_ssl_delete(Vio *vio) ...@@ -172,67 +172,79 @@ void vio_ssl_delete(Vio *vio)
vio_delete(vio); vio_delete(vio);
} }
int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
{
DBUG_ENTER("sslaccept");
DBUG_RETURN(sslconnect(ptr, vio, timeout));
}
int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
{ {
SSL *ssl; SSL *ssl;
my_bool unused; my_bool unused;
my_bool net_blocking; my_bool was_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx, timeout: %ld",
vio->sd, (long) ptr, timeout));
old_type= vio->type; DBUG_ENTER("sslconnect");
net_blocking= vio_is_blocking(vio); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx",
vio_blocking(vio, 1, &unused); /* Must be called before reset */ (long) ptr, vio->sd, (long) ptr->ssl_context));
vio_reset(vio, VIO_TYPE_SSL, vio->sd, 0, FALSE);
/* Set socket to blocking if not already set */
vio_blocking(vio, 1, &was_blocking);
if (!(ssl= SSL_new(ptr->ssl_context))) if (!(ssl= SSL_new(ptr->ssl_context)))
{ {
DBUG_PRINT("error", ("SSL_new failure")); DBUG_PRINT("error", ("SSL_new failure"));
report_errors(ssl); report_errors(ssl);
vio_reset(vio, old_type,vio->sd,0,FALSE); vio_blocking(vio, was_blocking, &unused);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
vio->ssl_arg= (void*)ssl;
DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout)); DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
SSL_clear(ssl); SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
SSL_set_fd(ssl, vio->sd); SSL_set_fd(ssl, vio->sd);
if (SSL_accept(ssl) < 1)
/*
SSL_do_handshake will select between SSL_connect
or SSL_accept depending on server or client side
*/
if (SSL_do_handshake(ssl) < 1)
{ {
DBUG_PRINT("error", ("SSL_accept failure")); DBUG_PRINT("error", ("SSL_do_handshake failure"));
report_errors(ssl); report_errors(ssl);
SSL_free(ssl); SSL_free(ssl);
vio->ssl_arg= 0; vio_blocking(vio, was_blocking, &unused);
vio_reset(vio, old_type,vio->sd,0,FALSE);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
#ifndef DBUG_OFF /*
{ Connection succeeded. Install new function handlers,
char buf[1024]; change type, set sd to the fd used when connecting
X509 *client_cert; and set pointer to the SSL structure
DBUG_PRINT("info",("cipher_name= '%s'", SSL_get_cipher_name(ssl))); */
vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0);
vio->ssl_arg= (void*)ssl;
if ((client_cert= SSL_get_peer_certificate (ssl))) #ifndef DBUG_OFF
{ {
DBUG_PRINT("info",("Client certificate:")); /* Print some info about the peer */
X509_NAME_oneline (X509_get_subject_name (client_cert), X509 *cert;
buf, sizeof(buf)); char buf[512];
DBUG_PRINT("info",("\t subject: %s", buf));
X509_NAME_oneline (X509_get_issuer_name (client_cert), DBUG_PRINT("info",("SSL connection succeeded"));
buf, sizeof(buf)); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));
DBUG_PRINT("info",("\t issuer: %s", buf));
X509_free (client_cert); if ((cert= SSL_get_peer_certificate (ssl)))
{
DBUG_PRINT("info",("Peer certificate:"));
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
DBUG_PRINT("info",("\t subject: '%s'", buf));
X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
DBUG_PRINT("info",("\t issuer: '%s'", buf));
X509_free(cert);
} }
else else
DBUG_PRINT("info",("Client does not have certificate.")); DBUG_PRINT("info",("Peer does not have certificate."));
if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
{ {
...@@ -247,68 +259,6 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) ...@@ -247,68 +259,6 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
} }
int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
{
SSL *ssl;
my_bool unused;
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslconnect");
DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx ctx: 0x%lx",
vio->sd, (long) ptr, (long) ptr->ssl_context));
old_type= vio->type;
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);
if (!(ssl= SSL_new(ptr->ssl_context)))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors(ssl);
vio_reset(vio, old_type, vio->sd, 0, FALSE);
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
vio->ssl_arg= (void*)ssl;
DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
SSL_set_fd(ssl, vio->sd);
if (SSL_connect(ssl) < 1)
{
DBUG_PRINT("error", ("SSL_connect failure"));
report_errors(ssl);
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
{
X509 *server_cert;
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:"));
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 set_blocking_mode,
my_bool *old_mode) my_bool *old_mode)
......
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