From b2d5243e97b7395d38bd6afc4767199703cf7f7c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Mar 2006 16:41:14 +0100 Subject: Cleanup SSL implementation Remove duplicate code Merge common functions Enforce MySQL coding standard include/violite.h: Cleanup SSL implementation sql-common/client.c: Cleanup SSL implementation sql/mysql_priv.h: Cleanup SSL implementation sql/mysqld.cc: Cleanup SSL implementation sql/sql_acl.cc: Cleanup SSL implementation vio/vio.c: Cleanup SSL implementation vio/vio_priv.h: Cleanup SSL implementation vio/viossl.c: Cleanup SSL implementation vio/viosslfactories.c: Cleanup SSL implementation --- vio/vio.c | 16 +-- vio/vio_priv.h | 22 +--- vio/viossl.c | 336 ++++++++++++++------------------------------------ vio/viosslfactories.c | 301 +++++++++++++++++++------------------------- 4 files changed, 229 insertions(+), 446 deletions(-) (limited to 'vio') diff --git a/vio/vio.c b/vio/vio.c index bc286b2d2bb..21a824a4016 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -88,19 +88,19 @@ static void vio_init(Vio* vio, enum enum_vio_type type, if (type == VIO_TYPE_SSL) { vio->viodelete =vio_delete; - vio->vioerrno =vio_ssl_errno; + vio->vioerrno =vio_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; - vio->fastsend =vio_ssl_fastsend; - vio->viokeepalive =vio_ssl_keepalive; - vio->should_retry =vio_ssl_should_retry; - vio->was_interrupted=vio_ssl_was_interrupted; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_ssl_close; - vio->peer_addr =vio_ssl_peer_addr; - vio->in_addr =vio_ssl_in_addr; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ssl_timeout; + vio->timeout =vio_timeout; } else /* default is VIO_TYPE_TCPIP */ #endif /* HAVE_OPENSSL */ diff --git a/vio/vio_priv.h b/vio/vio_priv.h index eb495025ddd..db331abdea8 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -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_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... */ 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); -/* Single copy for server */ -enum vio_ssl_acceptorfd_state -{ - state_connect = 1, - state_accept = 2 -}; #endif /* HAVE_OPENSSL */ diff --git a/vio/viossl.c b/vio/viossl.c index 1273814c551..33b8f716b9e 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -70,12 +70,6 @@ report_errors() } -int vio_ssl_errno(Vio *vio __attribute__((unused))) -{ - return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ -} - - int vio_ssl_read(Vio * vio, gptr buf, int size) { int r; @@ -107,183 +101,51 @@ int vio_ssl_write(Vio * vio, const gptr buf, int size) } -int vio_ssl_fastsend(Vio * vio __attribute__((unused))) -{ - int r=0; - DBUG_ENTER("vio_ssl_fastsend"); - -#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) - { - int tos= IPTOS_THROUGHPUT; - r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); - } -#endif /* IPTOS_THROUGHPUT && !__EMX__ */ - if (!r) - { -#ifdef __WIN__ - BOOL nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, - sizeof(nodelay)); -#else - int nodelay= 1; - r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, - sizeof(nodelay)); -#endif /* __WIN__ */ - } - if (r) - { - DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); - r= -1; - } - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive) -{ - int r=0; - DBUG_ENTER("vio_ssl_keepalive"); - DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int) - set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE) - { - uint opt = (set_keep_alive) ? 1 : 0; - r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, - sizeof(opt)); - } - DBUG_RETURN(r); -} - - -my_bool -vio_ssl_should_retry(Vio * vio __attribute__((unused))) -{ - int en = socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK); -} - - -my_bool -vio_ssl_was_interrupted(Vio *vio __attribute__((unused))) -{ - int en= socket_errno; - return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || - en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); -} - - int vio_ssl_close(Vio * vio) { - int r; + int r= 0; + SSL* ssl= (SSL*)vio->ssl_arg; DBUG_ENTER("vio_ssl_close"); - r=0; - if ((SSL*) vio->ssl_arg) - { - r = SSL_shutdown((SSL*) vio->ssl_arg); - SSL_free((SSL*) vio->ssl_arg); - vio->ssl_arg= 0; - } - if (vio->sd >= 0) - { - if (shutdown(vio->sd, 2)) - r= -1; - if (closesocket(vio->sd)) - r= -1; - } - if (r) - { - DBUG_PRINT("error", ("close() failed, error: %d",socket_errno)); - report_errors(); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->sd= -1; - DBUG_RETURN(r); -} - - -const char *vio_ssl_description(Vio * vio) -{ - return vio->desc; -} - -enum enum_vio_type vio_ssl_type(Vio* vio) -{ - return vio->type; -} - -my_socket vio_ssl_fd(Vio* vio) -{ - return vio->sd; -} - -my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port) -{ - DBUG_ENTER("vio_ssl_peer_addr"); - DBUG_PRINT("enter", ("sd: %d", vio->sd)); - if (vio->localhost) - { - strmov(buf,"127.0.0.1"); - *port=0; - } - else + if (ssl) { - size_socket addrLen = sizeof(struct sockaddr); - if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), - &addrLen) != 0) + switch ((r= SSL_shutdown(ssl))) { - DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); - DBUG_RETURN(1); + case 1: /* Shutdown successful */ + break; + case 0: /* Shutdown not yet finished, call it again */ + if ((r= SSL_shutdown(ssl) >= 0)) + break; + /* Fallthrough */ + default: /* Shutdown failed */ + DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s", + SSL_get_error(ssl, r))); + break; } -#ifdef TO_BE_FIXED - my_inet_ntoa(vio->remote.sin_addr,buf); - *port= 0; -#else - strmov(buf, "unknown"); - *port= 0; -#endif + SSL_free(ssl); + vio->ssl_arg= 0; } - DBUG_PRINT("exit", ("addr: %s", buf)); - DBUG_RETURN(0); -} - - -void vio_ssl_in_addr(Vio *vio, struct in_addr *in) -{ - DBUG_ENTER("vio_ssl_in_addr"); - if (vio->localhost) - bzero((char*) in, sizeof(*in)); - else - *in=vio->remote.sin_addr; - DBUG_VOID_RETURN; + DBUG_RETURN(vio_close(vio)); } -/* - TODO: Add documentation -*/ - -int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) +int sslaccept(struct st_VioSSLFd* ptr, Vio* vio, long timeout) { - char *str; - char buf[1024]; + SSL *ssl; X509* client_cert; my_bool unused; my_bool net_blocking; enum enum_vio_type old_type; DBUG_ENTER("sslaccept"); - DBUG_PRINT("enter", ("sd: %d ptr: Ox%p, timeout: %d", + DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d", vio->sd, ptr, timeout)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + 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); - vio->ssl_arg= 0; - if (!(vio->ssl_arg= (void*) SSL_new(ptr->ssl_context))) + 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(); @@ -291,121 +153,114 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: Ox%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd((SSL*) vio->ssl_arg,vio->sd); - SSL_set_accept_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_accept_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); - SSL_free((SSL*) vio->ssl_arg); + 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 - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (client_cert != NULL) { - DBUG_PRINT("info",("Client certificate:")); - str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free (str); + char buf[1024]; + DBUG_PRINT("info",("cipher_name= '%s'", SSL_get_cipher_name(ssl))); - str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free (str); + if ((client_cert= SSL_get_peer_certificate (ssl))) + { + DBUG_PRINT("info",("Client certificate:")); + X509_NAME_oneline (X509_get_subject_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t subject: %s", buf)); - X509_free (client_cert); - } - else - DBUG_PRINT("info",("Client does not have certificate.")); + X509_NAME_oneline (X509_get_issuer_name (client_cert), + buf, sizeof(buf)); + DBUG_PRINT("info",("\t issuer: %s", buf)); - str=SSL_get_shared_ciphers((SSL*) vio->ssl_arg, buf, sizeof(buf)); - if (str) - { - DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str)); - } - else - { - DBUG_PRINT("info",("no shared ciphers!")); - } + X509_free (client_cert); + } + else + DBUG_PRINT("info",("Client does not have certificate.")); + if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf))) + { + DBUG_PRINT("info",("shared_ciphers: '%s'", buf)); + } + else + DBUG_PRINT("info",("no shared ciphers!")); + } #endif + DBUG_RETURN(0); } -int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) +int sslconnect(struct st_VioSSLFd* ptr, Vio* vio, long timeout) { - char *str; - X509* server_cert; + SSL *ssl; + X509 *server_cert; my_bool unused; my_bool net_blocking; - enum enum_vio_type old_type; + enum enum_vio_type old_type; + DBUG_ENTER("sslconnect"); - DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p", - vio->sd,ptr,ptr->ssl_context)); + DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p", + vio->sd, ptr, ptr->ssl_context)); old_type= vio->type; - net_blocking = vio_is_blocking(vio); + 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); - vio->ssl_arg= 0; - if (!(vio->ssl_arg = SSL_new(ptr->ssl_context))) + 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(); - vio_reset(vio, old_type,vio->sd,0,FALSE); - vio_blocking(vio, net_blocking, &unused); + vio_reset(vio, old_type, vio->sd, 0, FALSE); + vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } - DBUG_PRINT("info", ("ssl_: 0x%p timeout: %ld", - (SSL*) vio->ssl_arg, timeout)); - SSL_clear((SSL*) vio->ssl_arg); - SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout); - SSL_set_fd ((SSL*) vio->ssl_arg, vio_ssl_fd(vio)); - SSL_set_connect_state((SSL*) vio->ssl_arg); - if (SSL_do_handshake((SSL*) vio->ssl_arg) < 1) + vio->ssl_arg= (void*)ssl; + DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + SSL_set_connect_state(ssl); + if (SSL_do_handshake(ssl) < 1) { DBUG_PRINT("error", ("SSL_do_handshake failure")); report_errors(); - SSL_free((SSL*) vio->ssl_arg); + SSL_free(ssl); vio->ssl_arg= 0; - vio_reset(vio, old_type,vio->sd,0,FALSE); + vio_reset(vio, old_type, vio->sd, 0, FALSE); vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); - } + } #ifndef DBUG_OFF - DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" - ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); - server_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); - if (server_cert != NULL) + 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:")); - str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t subject: %s", str)); - free(str); - - str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); - DBUG_PRINT("info",("\t issuer: %s", str)); - free(str); - - /* - We could do all sorts of certificate verification stuff here before - deallocating the 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); } @@ -414,21 +269,10 @@ int vio_ssl_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode, my_bool *old_mode) { + /* Mode is always blocking */ + *old_mode= 1; /* Return error if we try to change to non_blocking mode */ - *old_mode=1; /* Mode is always blocking */ - return set_blocking_mode ? 0 : 1; + return (set_blocking_mode ? 0 : 1); } - -void vio_ssl_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) -{ -#ifdef __WIN__ - ulong wait_timeout= (ulong) timeout * 1000; - (void) setsockopt(vio->sd, SOL_SOCKET, - which ? SO_SNDTIMEO : SO_RCVTIMEO, (char*) &wait_timeout, - sizeof(wait_timeout)); -#endif /* __WIN__ */ -} #endif /* HAVE_OPENSSL */ diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 4ee27f1e491..c58fa449374 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -21,7 +21,6 @@ static bool ssl_algorithms_added = FALSE; static bool ssl_error_strings_loaded= FALSE; static int verify_depth = 0; -static int verify_error = X509_V_OK; static unsigned char dh512_p[]= { @@ -82,30 +81,31 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) DBUG_ENTER("vio_set_cert_stuff"); DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s", ctx, cert_file, key_file)); - if (cert_file != NULL) + if (cert_file) { - if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file)); + DBUG_PRINT("error",("unable to get certificate from '%s'\n", cert_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file); fflush(stderr); - DBUG_RETURN(0); + DBUG_RETURN(1); } - if (key_file == NULL) - key_file = cert_file; - if (SSL_CTX_use_PrivateKey_file(ctx,key_file, - SSL_FILETYPE_PEM) <= 0) + + if (!key_file) + key_file= cert_file; + + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { - DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file)); + DBUG_PRINT("error", ("unable to get private key from '%s'\n", key_file)); /* FIX stderr */ fprintf(stderr,"Error when connection to server using SSL:"); ERR_print_errors_fp(stderr); fprintf(stderr,"Unable to get private key from '%s'\n", cert_file); - fflush(stderr); - DBUG_RETURN(0); + fflush(stderr); + DBUG_RETURN(1); } /* @@ -116,45 +116,45 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) { DBUG_PRINT("error", ("Private key does not match the certificate public key\n")); - DBUG_RETURN(0); + DBUG_RETURN(1); } } - DBUG_RETURN(1); + DBUG_RETURN(0); } static int vio_verify_callback(int ok, X509_STORE_CTX *ctx) { - char buf[256]; - X509* err_cert; - int err,depth; + char buf[256]; + X509 *err_cert; DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d, ctx: 0x%p", ok, ctx)); - err_cert=X509_STORE_CTX_get_current_cert(ctx); - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); + DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx)); - X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf)); + err_cert= X509_STORE_CTX_get_current_cert(ctx); + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); + DBUG_PRINT("info", ("cert: %s", buf)); if (!ok) { - DBUG_PRINT("error",("verify error: num: %d : '%s'\n",err, + int err, depth; + err= X509_STORE_CTX_get_error(ctx); + depth= X509_STORE_CTX_get_error_depth(ctx); + + DBUG_PRINT("error",("verify error: %d, '%s'",err, X509_verify_cert_error_string(err))); + /* + Approve cert if depth is greater then "verify_depth", currently + verify_depth is always 0 and there is no way to increase it. + */ if (verify_depth >= depth) - { - ok=1; - verify_error=X509_V_OK; - } - else - { - verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; - } + ok= 1; } - switch (ctx->error) { + switch (ctx->error) + { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256); - DBUG_PRINT("info",("issuer= %s\n",buf)); + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); + DBUG_PRINT("info",("issuer= %s\n", buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: @@ -198,193 +198,150 @@ static void netware_ssl_init() #endif /* __NETWARE__ */ -/************************ VioSSLConnectorFd **********************************/ -/* - TODO: - Add option --verify to mysql to be able to change verification mode -*/ - -struct st_VioSSLConnectorFd * -new_VioSSLConnectorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path, - const char* cipher) +static void check_ssl_init() { - int verify = SSL_VERIFY_NONE; - struct st_VioSSLConnectorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLConnectorFd"); - - if (!(ptr=((struct st_VioSSLConnectorFd*) - my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0))))) - DBUG_RETURN(0); - - ptr->ssl_context= 0; - ptr->ssl_method= 0; - /* FIXME: constants! */ - if (!ssl_algorithms_added) { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; + ssl_algorithms_added= TRUE; SSL_library_init(); OpenSSL_add_all_algorithms(); + } + #ifdef __NETWARE__ + /* MASV, should it be done everytime? */ netware_ssl_init(); #endif if (!ssl_error_strings_loaded) { - DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; + ssl_error_strings_loaded= TRUE; SSL_load_error_strings(); } - ptr->ssl_method = TLSv1_client_method(); - ptr->ssl_context = SSL_CTX_new(ptr->ssl_method); - DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context)); - if (ptr->ssl_context == 0) +} + +/************************ VioSSLFd **********************************/ +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) +{ + DH *dh; + struct st_VioSSLFd *ssl_fd; + DBUG_ENTER("new_VioSSLFd"); + + check_ssl_init(); + + if (!(ssl_fd= ((struct st_VioSSLFd*) + my_malloc(sizeof(struct st_VioSSLFd),MYF(0))))) + DBUG_RETURN(0); + + if (!(ssl_fd->ssl_context= SSL_CTX_new(method))) { DBUG_PRINT("error", ("SSL_CTX_new failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - /* - SSL_CTX_set_options - SSL_CTX_set_info_callback - */ - if (cipher) + + /* Set the ciphers that can be used */ + if (cipher && SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher)) { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + DBUG_PRINT("error", ("failed to set ciphers to use")); + report_errors(); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) + + if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file)) { DBUG_PRINT("error", ("vio_set_cert_stuff failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0) + + if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0) { DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0) + if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0) { DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); report_errors(); - goto ctor_failure; + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); } - } + } /* DH stuff */ dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); + SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh); DH_free(dh); - DBUG_RETURN(ptr); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr)ptr,MYF(0)); - DBUG_RETURN(0); + DBUG_PRINT("exit", ("OK 1")); + + DBUG_RETURN(ssl_fd); } -/************************ VioSSLAcceptorFd **********************************/ -/* - TODO: - Add option --verify to mysqld to be able to change verification mode -*/ -struct st_VioSSLAcceptorFd* -new_VioSSLAcceptorFd(const char *key_file, - const char *cert_file, - const char *ca_file, - const char *ca_path, - const char *cipher) +/************************ VioSSLConnectorFd **********************************/ +struct st_VioSSLFd * +new_VioSSLConnectorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) { - int verify = (SSL_VERIFY_PEER | - SSL_VERIFY_CLIENT_ONCE); - struct st_VioSSLAcceptorFd* ptr; - int result; - DH *dh; - DBUG_ENTER("new_VioSSLAcceptorFd"); + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_NONE; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_client_method()))) + { + return 0; + } + /* Init the the VioSSLFd as a "connector" ie. the client side */ - ptr= ((struct st_VioSSLAcceptorFd*) - my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0))); - ptr->ssl_context=0; - ptr->ssl_method=0; - /* FIXME: constants! */ - ptr->session_id_context= ptr; + /* + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. Here it is SSL_VERIFY_NONE + and thus callback is set to NULL + */ + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); - if (!ssl_algorithms_added) - { - DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); - ssl_algorithms_added = TRUE; - SSL_library_init(); - OpenSSL_add_all_algorithms(); + return ssl_fd; +} - } -#ifdef __NETWARE__ - netware_ssl_init(); -#endif - if (!ssl_error_strings_loaded) - { - DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); - ssl_error_strings_loaded = TRUE; - SSL_load_error_strings(); - } - ptr->ssl_method= TLSv1_server_method(); - ptr->ssl_context= SSL_CTX_new(ptr->ssl_method); - if (ptr->ssl_context == 0) - { - DBUG_PRINT("error", ("SSL_CTX_new failed")); - report_errors(); - goto ctor_failure; - } - if (cipher) +/************************ VioSSLAcceptorFd **********************************/ +struct st_VioSSLFd* +new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, + const char *ca_file, const char *ca_path, + const char *cipher) +{ + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, + ca_path, cipher, TLSv1_server_method()))) { - result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher); - DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + return 0; } - /* SSL_CTX_set_quiet_shutdown(ctx,1); */ - SSL_CTX_sess_set_cache_size(ptr->ssl_context,128); + /* Init the the VioSSLFd as a "acceptor" ie. the server side */ - /* DH? */ - SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback); - SSL_CTX_set_session_id_context(ptr->ssl_context, - (const uchar*) &(ptr->session_id_context), - sizeof(ptr->session_id_context)); + /* Set max number of cached sessions, returns the previous size */ + SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); /* - SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. */ - if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1) - { - DBUG_PRINT("error", ("vio_set_cert_stuff failed")); - report_errors(); - goto ctor_failure; - } - if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0) - { - DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0) - { - DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); - report_errors(); - goto ctor_failure; - } - } - /* DH stuff */ - dh=get_dh512(); - SSL_CTX_set_tmp_dh(ptr->ssl_context,dh); - DH_free(dh); - DBUG_RETURN(ptr); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - my_free((gptr) ptr,MYF(0)); - DBUG_RETURN(0); + /* + Set session_id - an identifier for this server session + Use the ssl_fd pointer + */ + SSL_CTX_set_session_id_context(ssl_fd->ssl_context, + ssl_fd, + sizeof(ssl_fd)); + + return ssl_fd; } #endif /* HAVE_OPENSSL */ -- cgit v1.2.1