static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, ssl_handshake_func_t func, unsigned long *ssl_errno_holder) { int r; SSL *ssl; my_socket sd= mysql_socket_getfd(vio->mysql_socket); DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, sd, (long) ptr->ssl_context)); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *ssl_errno_holder= ERR_get_error(); DBUG_RETURN(1); } 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, sd); #ifndef HAVE_YASSL SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); #endif /* Since yaSSL does not support non-blocking send operations, use special transport functions that properly handles non-blocking sockets. These functions emulate the behavior of blocking I/O operations by waiting for I/O to become available. */ #ifdef HAVE_YASSL /* Set first argument of the transport functions. */ yaSSL_transport_set_ptr(ssl, vio); /* Set functions to use in order to send and receive data. */ yaSSL_transport_set_recv_function(ssl, yassl_recv); yaSSL_transport_set_send_function(ssl, yassl_send); #endif if ((r= ssl_handshake_loop(vio, ssl, func, ssl_errno_holder)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); SSL_free(ssl); DBUG_RETURN(1); } /* Connection succeeded. Install new function handlers, change type, set sd to the fd used when connecting and set pointer to the SSL structure */ if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0)) DBUG_RETURN(1); #ifndef DBUG_OFF { /* Print some info about the peer */ X509 *cert; char buf[512]; DBUG_PRINT("info",("SSL connection succeeded")); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl))); 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 DBUG_PRINT("info",("Peer 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); }
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, ssl_handshake_func_t func, unsigned long *ssl_errno_holder) { int r; SSL *ssl; my_socket sd= mysql_socket_getfd(vio->mysql_socket); /* Declared here to make compiler happy */ #if !defined(HAVE_YASSL) && !defined(DBUG_OFF) int j, n; #endif DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, sd, (long) ptr->ssl_context)); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *ssl_errno_holder= ERR_get_error(); DBUG_RETURN(1); } 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, sd); #if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION) SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); /* OpenSSL >= 1.0 only */ #elif OPENSSL_VERSION_NUMBER >= 0x00908000L /* workaround for OpenSSL 0.9.8 */ sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); #endif #if !defined(HAVE_YASSL) && !defined(DBUG_OFF) { STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; ssl_comp_methods = SSL_COMP_get_compression_methods(); n= sk_SSL_COMP_num(ssl_comp_methods); DBUG_PRINT("info", ("Available compression methods:\n")); if (n == 0) DBUG_PRINT("info", ("NONE\n")); else for (j = 0; j < n; j++) { SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j); DBUG_PRINT("info", (" %d: %s\n", c->id, c->name)); } } #endif /* Since yaSSL does not support non-blocking send operations, use special transport functions that properly handles non-blocking sockets. These functions emulate the behavior of blocking I/O operations by waiting for I/O to become available. */ #ifdef HAVE_YASSL /* Set first argument of the transport functions. */ yaSSL_transport_set_ptr(ssl, vio); /* Set functions to use in order to send and receive data. */ yaSSL_transport_set_recv_function(ssl, yassl_recv); yaSSL_transport_set_send_function(ssl, yassl_send); #endif if ((r= ssl_handshake_loop(vio, ssl, func, ssl_errno_holder)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); SSL_free(ssl); DBUG_RETURN(1); } /* Connection succeeded. Install new function handlers, change type, set sd to the fd used when connecting and set pointer to the SSL structure */ if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0)) DBUG_RETURN(1); #ifndef DBUG_OFF { /* Print some info about the peer */ X509 *cert; char buf[512]; DBUG_PRINT("info",("SSL connection succeeded")); DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl))); 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 DBUG_PRINT("info",("Peer 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); }