/* Suspend curses while running an external program */ static ELVBOOL vio_prgopen (char *command, /* the shell command to run */ ELVBOOL willwrite, /* redirect stdin from elvis */ ELVBOOL willread) /* redirect stdiout back to elvis */ { /* unless both stdin and stdout/stderr are going to be redirected, * move the cursor to the bottom of the screen before running program. */ isfilter = (ELVBOOL)(willwrite && willread); if (!isfilter) { vio_CM (o_ttyrows - 1, 0); vio_CE (vc_term); vio_reset (); do_flush (); /* suspend curses */ vio_suspend (); } /* try to call the regular prgopen(); if it fails, then clean up */ if (!prgopen (command, willwrite, willread)) { if (!isfilter) vio_resume (ElvTrue); return ElvFalse; } return ElvTrue; }
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) { Vio *vio; DBUG_ENTER("vio_new"); DBUG_PRINT("enter", ("sd=%d", sd)); if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) { vio_reset(vio, type, sd, 0, localhost); sprintf(vio->desc, (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), vio->sd); #if !defined(__WIN32) && !defined(__EMX__) && !defined(OS2) #if !defined(NO_FCNTL_NONBLOCK) vio->fcntl_mode = fcntl(sd, F_GETFL); #elif defined(HAVE_SYS_IOCTL_H) /* hpux */ /* Non blocking sockets doesn't work good on HPUX 11.0 */ (void) ioctl(sd,FIOSNBIO,0); #endif #else /* !defined(_WIN32) && !defined(__EMX__) */ { /* set to blocking mode by default */ ulong arg=0, r; r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg)); } #endif } DBUG_RETURN(vio); }
/* establish SSL connection between client and server SYNOPSIS my_ssl_connect ssl ssl object RETURN VALUES 0 success 1 error */ int my_ssl_connect(SSL *ssl) { my_bool blocking; MYSQL *mysql; DBUG_ENTER("my_ssl_connect"); DBUG_ASSERT(ssl != NULL); mysql= (MYSQL *)SSL_get_app_data(ssl); CLEAR_CLIENT_ERROR(mysql); /* Set socket to blocking if not already set */ if (!(blocking= vio_is_blocking(mysql->net.vio))) vio_blocking(mysql->net.vio, TRUE); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), mysql->options.connect_timeout); SSL_set_fd(ssl, mysql->net.vio->sd); if (SSL_connect(ssl) != 1) { my_SSL_error(mysql); /* restore blocking mode */ if (!blocking) vio_blocking(mysql->net.vio, FALSE); DBUG_RETURN(1); } vio_reset(mysql->net.vio, VIO_TYPE_SSL, mysql->net.vio->sd, 0, 0); mysql->net.vio->ssl= ssl; DBUG_RETURN(0); }
/* establish SSL connection between client and server SYNOPSIS my_ssl_connect ssl ssl object RETURN VALUES 0 success 1 error */ int my_ssl_connect(SSL *ssl) { my_bool blocking; MYSQL *mysql; long rc; my_bool try_connect= 1; DBUG_ENTER("my_ssl_connect"); DBUG_ASSERT(ssl != NULL); mysql= (MYSQL *)SSL_get_app_data(ssl); CLEAR_CLIENT_ERROR(mysql); /* Set socket to non blocking */ if (!(blocking= vio_is_blocking(mysql->net.vio))) vio_blocking(mysql->net.vio, FALSE, 0); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), mysql->options.connect_timeout); SSL_set_fd(ssl, mysql->net.vio->sd); while (try_connect && (rc= SSL_connect(ssl)) == -1) { switch(SSL_get_error(ssl, rc)) { case SSL_ERROR_WANT_READ: if (vio_wait_or_timeout(mysql->net.vio, TRUE, mysql->options.connect_timeout) < 1) try_connect= 0; break; case SSL_ERROR_WANT_WRITE: if (vio_wait_or_timeout(mysql->net.vio, TRUE, mysql->options.connect_timeout) < 1) try_connect= 0; break; default: try_connect= 0; } } if (rc != 1) { my_SSL_error(mysql); DBUG_RETURN(1); } rc= SSL_get_verify_result(ssl); if (rc != X509_V_OK) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc)); /* restore blocking mode */ if (!blocking) vio_blocking(mysql->net.vio, FALSE, 0); DBUG_RETURN(1); } vio_reset(mysql->net.vio, VIO_TYPE_SSL, mysql->net.vio->sd, 0, 0); mysql->net.vio->ssl= ssl; DBUG_RETURN(0); }
/* Put the terminal in RAW mode. Send any required strings */ static void vio_resume (ELVBOOL sendstr) /* send strings? */ { /* Determine the present whereabouts of the cursor. */ VioGetCurPos (&c_row, &c_col, 0); raw_mode = TRUE; /* reset, so we don't try any suspicious optimizations */ vio_reset (); }
Vio *vio_new_win32pipe(HANDLE hPipe) { Vio *vio; DBUG_ENTER("vio_new_handle"); if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) { vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE); strmov(vio->desc, "named pipe"); } DBUG_RETURN(vio); }
/* establish SSL connection between client and server SYNOPSIS my_ssl_connect ssl ssl object RETURN VALUES 0 success 1 error */ int my_ssl_connect(SSL *ssl) { my_bool blocking; MYSQL *mysql; long rc; DBUG_ENTER("my_ssl_connect"); DBUG_ASSERT(ssl != NULL); mysql= (MYSQL *)SSL_get_app_data(ssl); CLEAR_CLIENT_ERROR(mysql); /* Set socket to blocking if not already set */ if (!(blocking= vio_is_blocking(mysql->net.vio))) vio_blocking(mysql->net.vio, TRUE, 0); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), mysql->options.connect_timeout); SSL_set_fd(ssl, mysql->net.vio->sd); if (SSL_connect(ssl) != 1) { my_SSL_error(mysql); /* restore blocking mode */ if (!blocking) vio_blocking(mysql->net.vio, FALSE, 0); DBUG_RETURN(1); } rc= SSL_get_verify_result(ssl); if (rc != X509_V_OK) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc)); /* restore blocking mode */ if (!blocking) vio_blocking(mysql->net.vio, FALSE, 0); DBUG_RETURN(1); } vio_reset(mysql->net.vio, VIO_TYPE_SSL, mysql->net.vio->sd, 0, 0); mysql->net.vio->ssl= ssl; DBUG_RETURN(0); }
Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map, HANDLE event_server_wrote, HANDLE event_server_read, HANDLE event_client_wrote, HANDLE event_client_read, HANDLE event_conn_closed) { Vio *vio; DBUG_ENTER("vio_new_win32shared_memory"); if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) { vio_reset(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, TRUE); vio->handle_file_map= handle_file_map; vio->handle_map= handle_map; vio->event_server_wrote= event_server_wrote; vio->event_server_read= event_server_read; vio->event_client_wrote= event_client_wrote; vio->event_client_read= event_client_read; vio->event_conn_closed= event_conn_closed; vio->shared_memory_remain= 0; vio->shared_memory_pos= handle_map; vio->net= net; strmov(vio->desc, "shared memory"); } DBUG_RETURN(vio); }
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) { Vio *vio; DBUG_ENTER("vio_new"); DBUG_PRINT("enter", ("sd=%d", sd)); if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) { vio_reset(vio, type, sd, 0, localhost); sprintf(vio->desc, (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), vio->sd); #ifndef VXWORKS #if !defined(NO_FCNTL_NONBLOCK) /* We call fcntl() to set the flags and then immediately read them back to make sure that we and the system are in agreement on the state of things. An example of why we need to do this is FreeBSD (and apparently some other BSD-derived systems, like Mac OS X), where the system sometimes reports that the socket is set for non-blocking when it really will block. */ fcntl(sd, F_SETFL, 0); vio->fcntl_mode= fcntl(sd, F_GETFL); #elif defined(HAVE_SYS_IOCTL_H) /* hpux */ /* Non blocking sockets doesn't work good on HPUX 11.0 */ (void) ioctl(sd,FIOSNBIO,0); vio->fcntl_mode &= ~O_NONBLOCK; #endif #endif } DBUG_RETURN(vio); }
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, int (*connect_accept_func)(SSL*), unsigned long *errptr) { int r; SSL *ssl; my_bool unused; my_bool was_blocking; DBUG_ENTER("ssl_do"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, vio->sd, (long) ptr->ssl_context)); /* Set socket to blocking if not already set */ vio_blocking(vio, 1, &was_blocking); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); *errptr= ERR_get_error(); vio_blocking(vio, was_blocking, &unused); 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, vio->sd); #if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION) SSL_set_options(ssl, SSL_OP_NO_COMPRESSION); #endif if ((r= connect_accept_func(ssl)) < 1) { DBUG_PRINT("error", ("SSL_connect/accept failure")); *errptr= SSL_get_error(ssl, r); SSL_free(ssl); vio_blocking(vio, was_blocking, &unused); 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 */ vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0); vio->ssl_arg= (void*)ssl; #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); }
int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) { SSL *ssl; my_bool unused; my_bool was_blocking; DBUG_ENTER("sslconnect"); DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d ctx: 0x%lx", (long) ptr, vio->sd, (long) ptr->ssl_context)); /* Set socket to blocking if not already set */ vio_blocking(vio, 1, &was_blocking); if (!(ssl= SSL_new(ptr->ssl_context))) { DBUG_PRINT("error", ("SSL_new failure")); report_errors(ssl); vio_blocking(vio, was_blocking, &unused); 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, vio->sd); /* 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_do_handshake failure")); report_errors(ssl); SSL_free(ssl); vio_blocking(vio, was_blocking, &unused); 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 */ vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0); vio->ssl_arg= (void*)ssl; #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); }