summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2006-04-26 22:24:25 +0200
committerunknown <msvensson@neptunus.(none)>2006-04-26 22:24:25 +0200
commit88724885d545357c76dbda02a69a488a45296071 (patch)
tree67ff2b286c7d42090d89349a6b6c10d80480feb5 /sql-common
parentd61f1823d67771c1d4e48b8adb4819d748e4d747 (diff)
parentc1d64ccc1b227e862f5cbaa991ce5525c59ab2ef (diff)
downloadmariadb-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
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/client.c126
1 files changed, 107 insertions, 19 deletions
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);
}