Commit e5712d84 authored by msvensson@neptunus.(none)'s avatar msvensson@neptunus.(none)

Merge neptunus.(none):/home/msvensson/mysql/mysql-5.0

into  neptunus.(none):/home/msvensson/mysql/bug17208/my50-bug17208
parents 7c701590 aa3abd15
...@@ -105,33 +105,22 @@ void vio_timeout(Vio *vio,uint which, uint timeout); ...@@ -105,33 +105,22 @@ void vio_timeout(Vio *vio,uint which, uint timeout);
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
struct st_VioSSLAcceptorFd struct st_VioSSLFd
{ {
SSL_CTX *ssl_context; SSL_CTX *ssl_context;
SSL_METHOD *ssl_method;
struct st_VioSSLAcceptorFd *session_id_context;
}; };
/* One copy for client */ int sslaccept(struct st_VioSSLFd*, Vio *, long timeout);
struct st_VioSSLConnectorFd int sslconnect(struct st_VioSSLFd*, Vio *, long timeout);
{
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);
struct st_VioSSLConnectorFd struct st_VioSSLFd
*new_VioSSLConnectorFd(const char *key_file, const char *cert_file, *new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
const char *ca_file, const char *ca_path, const char *ca_file, const char *ca_path,
const char *cipher); const char *cipher);
struct st_VioSSLAcceptorFd struct st_VioSSLFd
*new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, *new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
const char *ca_file,const char *ca_path, const char *ca_file,const char *ca_path,
const char *cipher); const char *cipher);
Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state);
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
......
...@@ -1514,8 +1514,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , ...@@ -1514,8 +1514,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
static void static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused))) mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
{ {
struct st_VioSSLConnectorFd *st= struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd;
(struct st_VioSSLConnectorFd*) mysql->connector_fd;
DBUG_ENTER("mysql_ssl_free"); DBUG_ENTER("mysql_ssl_free");
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
...@@ -1523,8 +1522,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) ...@@ -1523,8 +1522,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
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 (st) if (ssl_fd)
SSL_CTX_free(st->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));
mysql->options.ssl_key = 0; mysql->options.ssl_key = 0;
mysql->options.ssl_cert = 0; mysql->options.ssl_cert = 0;
...@@ -1568,6 +1567,63 @@ static MYSQL_METHODS client_methods= ...@@ -1568,6 +1567,63 @@ static MYSQL_METHODS client_methods=
#endif #endif
}; };
int ssl_verify_server_cert(Vio *vio, const char* server_host)
{
SSL *ssl;
X509 *server_cert;
char *cp1, *cp2;
char buf[256];
DBUG_ENTER("ssl_verify_server_cert");
DBUG_PRINT("enter", ("server_host: %s", server_host));
if (!(ssl= (SSL*)vio->ssl_arg))
{
DBUG_PRINT("error", ("No SSL pointer found"));
return 1;
}
if (!server_host)
{
DBUG_PRINT("error", ("No server hostname supplied"));
return 1;
}
if (!(server_cert= SSL_get_peer_certificate(ssl)))
{
DBUG_PRINT("error", ("Could not get server certificate"));
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);
// X509_NAME_get_text_by_NID(x509_get_subject_name(server_cert), NID_commonName, buf, sizeof(buf));... does the same thing
DBUG_PRINT("info", ("hostname in cert: %s", buf));
cp1 = strstr(buf, "/CN=");
if (cp1)
{
cp1 += 4; // Skip the "/CN=" that we found
cp2 = strchr(cp1, '/');
if (cp2)
*cp2 = '\0';
DBUG_PRINT("info", ("Server hostname in cert: ", cp1));
if (!strcmp(cp1, server_host))
{
/* Success */
DBUG_RETURN(0);
}
}
DBUG_PRINT("error", ("SSL certificate validation failure"));
DBUG_RETURN(1);
}
MYSQL * MYSQL *
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
...@@ -2013,21 +2069,24 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2013,21 +2069,24 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->client_flag=client_flag; mysql->client_flag=client_flag;
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
/*
Oops.. are we careful enough to not send ANY information without
encryption?
*/
if (client_flag & CLIENT_SSL) if (client_flag & CLIENT_SSL)
{ {
/* Do the SSL layering. */
struct st_mysql_options *options= &mysql->options; 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)) if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net))
{ {
set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
goto error; goto error;
} }
/* Do the SSL layering. */
if (!(mysql->connector_fd= /* Create the VioSSLConnectorFd - init SSL and load certs */
(gptr) new_VioSSLConnectorFd(options->ssl_key, if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
options->ssl_cert, options->ssl_cert,
options->ssl_ca, options->ssl_ca,
options->ssl_capath, options->ssl_capath,
...@@ -2036,14 +2095,27 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, ...@@ -2036,14 +2095,27 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error; goto error;
} }
mysql->connector_fd= (void*)ssl_fd;
/* Connect to the server */
DBUG_PRINT("info", ("IO layer change in progress...")); DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), if (sslconnect(ssl_fd, mysql->net.vio,
mysql->net.vio, (long) (mysql->options.connect_timeout))) (long) (mysql->options.connect_timeout)))
{ {
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error; goto error;
} }
DBUG_PRINT("info", ("IO layer change done!")); DBUG_PRINT("info", ("IO layer change done!"));
#if 0
/* Verify server cert */
if (mysql->options.ssl_verify_cert &&
ssl_verify_server_cert(mysql->net.vio, mysql->host))
{
set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
goto error;
}
#endif
} }
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
......
...@@ -1307,7 +1307,7 @@ extern pthread_t signal_thread; ...@@ -1307,7 +1307,7 @@ extern pthread_t signal_thread;
#endif #endif
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; extern struct st_VioSSLFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
......
...@@ -596,7 +596,7 @@ static void openssl_lock(int, openssl_lock_t *, const char *, int); ...@@ -596,7 +596,7 @@ static void openssl_lock(int, openssl_lock_t *, const char *, int);
static unsigned long openssl_id_function(); static unsigned long openssl_id_function();
#endif #endif
char *des_key_file; char *des_key_file;
struct st_VioSSLAcceptorFd *ssl_acceptor_fd; struct st_VioSSLFd *ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
...@@ -1107,7 +1107,10 @@ void clean_up(bool print_message) ...@@ -1107,7 +1107,10 @@ void clean_up(bool print_message)
#endif #endif
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
if (ssl_acceptor_fd) 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 */ #endif /* HAVE_OPENSSL */
#ifdef USE_REGEX #ifdef USE_REGEX
my_regex_end(); my_regex_end();
......
...@@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type, ...@@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
if (type == VIO_TYPE_SSL) if (type == VIO_TYPE_SSL)
{ {
vio->viodelete =vio_delete; vio->viodelete =vio_delete;
vio->vioerrno =vio_ssl_errno; vio->vioerrno =vio_errno;
vio->read =vio_ssl_read; vio->read =vio_ssl_read;
vio->write =vio_ssl_write; vio->write =vio_ssl_write;
vio->fastsend =vio_ssl_fastsend; vio->fastsend =vio_fastsend;
vio->viokeepalive =vio_ssl_keepalive; vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_ssl_should_retry; vio->should_retry =vio_should_retry;
vio->was_interrupted=vio_ssl_was_interrupted; vio->was_interrupted=vio_was_interrupted;
vio->vioclose =vio_ssl_close; vio->vioclose =vio_ssl_close;
vio->peer_addr =vio_ssl_peer_addr; vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_ssl_in_addr; vio->in_addr =vio_in_addr;
vio->vioblocking =vio_ssl_blocking; vio->vioblocking =vio_ssl_blocking;
vio->is_blocking =vio_is_blocking; vio->is_blocking =vio_is_blocking;
vio->timeout =vio_ssl_timeout; vio->timeout =vio_timeout;
} }
else /* default is VIO_TYPE_TCPIP */ else /* default is VIO_TYPE_TCPIP */
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
......
...@@ -30,28 +30,10 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); ...@@ -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_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);
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... */ /* When the workday is over... */
int vio_ssl_close(Vio *vio); 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); 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 */ #endif /* HAVE_OPENSSL */
This diff is collapsed.
This diff is collapsed.
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