diff options
| author | Xanadu <none@none> | 2010-07-20 02:49:28 +0200 |
|---|---|---|
| committer | Xanadu <none@none> | 2010-07-20 02:49:28 +0200 |
| commit | 79622802f397258ee0f34327ba3ae6977ca3e7ff (patch) | |
| tree | 1868946c234ab9ee256a6b7766a15713eae94235 /externals/mysql/vio | |
| parent | 7dd2dc91816ab8b3bc3b99a1b1c99c7ea314d5a8 (diff) | |
| parent | f906976837502fa5aa81b982b901d1509f5aa0c4 (diff) | |
Merge. Revision history for source files should be all back now.
--HG--
branch : trunk
rename : sql/CMakeLists.txt => sql/tools/CMakeLists.txt
rename : src/server/game/Pools/PoolHandler.cpp => src/server/game/Pools/PoolMgr.cpp
rename : src/server/game/Pools/PoolHandler.h => src/server/game/Pools/PoolMgr.h
rename : src/server/game/PrecompiledHeaders/NixCorePCH.cpp => src/server/game/PrecompiledHeaders/gamePCH.cpp
rename : src/server/game/PrecompiledHeaders/NixCorePCH.h => src/server/game/PrecompiledHeaders/gamePCH.h
Diffstat (limited to 'externals/mysql/vio')
| -rw-r--r-- | externals/mysql/vio/test-ssl.c | 149 | ||||
| -rw-r--r-- | externals/mysql/vio/test-sslclient.c | 101 | ||||
| -rw-r--r-- | externals/mysql/vio/test-sslserver.c | 155 | ||||
| -rw-r--r-- | externals/mysql/vio/vio.c | 242 | ||||
| -rw-r--r-- | externals/mysql/vio/vio_priv.h | 46 | ||||
| -rw-r--r-- | externals/mysql/vio/viosocket.c | 714 | ||||
| -rw-r--r-- | externals/mysql/vio/viossl.c | 279 | ||||
| -rw-r--r-- | externals/mysql/vio/viosslfactories.c | 385 | ||||
| -rw-r--r-- | externals/mysql/vio/viotest-ssl.c | 151 | ||||
| -rw-r--r-- | externals/mysql/vio/viotest-sslconnect.cc | 80 | ||||
| -rw-r--r-- | externals/mysql/vio/viotest.cc | 47 |
11 files changed, 2349 insertions, 0 deletions
diff --git a/externals/mysql/vio/test-ssl.c b/externals/mysql/vio/test-ssl.c new file mode 100644 index 00000000000..855dc5fbb3e --- /dev/null +++ b/externals/mysql/vio/test-ssl.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#if defined(HAVE_OPENSSL) && !defined(__NETWARE__) +#include <my_sys.h> +#include <m_string.h> +#include <m_ctype.h> +#include "mysql.h" +#include "errmsg.h" +#include <my_dir.h> +#include <my_getopt.h> +#include <signal.h> +#include <violite.h> + +const char *VER="0.2"; + + +#ifndef DBUG_OFF +const char *default_dbug_option="d:t:O,-"; +#endif + +void +fatal_error( const char* r) +{ + perror(r); + exit(0); +} + +void +print_usage() +{ + printf("viossl-test: testing SSL virtual IO. Usage:\n"); + printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n"); +} + + +int +main(int argc, char** argv) +{ + char* server_key = 0, *server_cert = 0; + char* client_key = 0, *client_cert = 0; + char* ca_file = 0, *ca_path = 0; + char* cipher=0; + int child_pid,sv[2]; + my_bool unused; + struct st_VioSSLFd* ssl_acceptor= 0; + struct st_VioSSLFd* ssl_connector= 0; + Vio* client_vio=0, *server_vio=0; + MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + DBUG_PUSH(default_dbug_option); + + if (argc<5) + { + print_usage(); + return 1; + } + + server_key = argv[1]; + server_cert = argv[2]; + client_key = argv[3]; + client_cert = argv[4]; + if (argc>5) + ca_file = argv[5]; + if (argc>6) + ca_path = argv[6]; + printf("Server key/cert : %s/%s\n", server_key, server_cert); + printf("Client key/cert : %s/%s\n", client_key, client_cert); + if (ca_file!=0) + printf("CAfile : %s\n", ca_file); + if (ca_path!=0) + printf("CApath : %s\n", ca_path); + + + if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1) + fatal_error("socketpair"); + + ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, + ca_path, cipher); + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, + ca_path, cipher); + + client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); + client_vio->sd = sv[0]; + client_vio->vioblocking(client_vio, 0, &unused); + sslconnect(ssl_connector,client_vio,60L); + server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0)); + server_vio->sd = sv[1]; + server_vio->vioblocking(client_vio, 0, &unused); + sslaccept(ssl_acceptor,server_vio,60L); + + printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd); + + child_pid = fork(); + if (child_pid==-1) { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("fork"); + } + if (child_pid==0) + { + /* child, therefore, client */ + char xbuf[100]; + int r = vio_read(client_vio,xbuf, sizeof(xbuf)); + if (r<=0) { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } + xbuf[r] = 0; + printf("client:got %s\n", xbuf); + my_free((uchar*)client_vio,MYF(0)); + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + } + else + { + const char* s = "Huhuhuh"; + int r = vio_write(server_vio,(uchar*)s, strlen(s)); + if (r<=0) { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("server:SSL_write"); + } + my_free((uchar*)server_vio,MYF(0)); + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + } + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/test-sslclient.c b/externals/mysql/vio/test-sslclient.c new file mode 100644 index 00000000000..e1b8461397b --- /dev/null +++ b/externals/mysql/vio/test-sslclient.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#ifdef HAVE_OPENSSL +#include <my_sys.h> +#include <m_string.h> +#include <m_ctype.h> +#include "mysql.h" +#include "errmsg.h" +#include <my_dir.h> +#include <my_getopt.h> +#include <signal.h> +#include <violite.h> + +const char *VER="0.2"; + + +#ifndef DBUG_OFF +const char *default_dbug_option="d:t:O,-"; +#endif + +void +fatal_error( const char* r) +{ + perror(r); + exit(0); +} + +int +main( int argc __attribute__((unused)), + char** argv) +{ + char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem"; + char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0; + struct st_VioSSLFd* ssl_connector= 0; + struct sockaddr_in sa; + Vio* client_vio=0; + int err; + char xbuf[100]="Ohohhhhoh1234"; + MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + DBUG_PUSH(default_dbug_option); + + printf("Client key/cert : %s/%s\n", client_key, client_cert); + if (ca_file!=0) + printf("CAfile : %s\n", ca_file); + if (ca_path!=0) + printf("CApath : %s\n", ca_path); + + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher); + if(!ssl_connector) { + fatal_error("client:new_VioSSLConnectorFd failed"); + } + + /* ----------------------------------------------- */ + /* Create a socket and connect to server using normal socket calls. */ + + client_vio = vio_new(socket (AF_INET, SOCK_STREAM, 0), VIO_TYPE_TCPIP, TRUE); + + memset (&sa, '\0', sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server IP */ + sa.sin_port = htons (1111); /* Server Port number */ + + err = connect(client_vio->sd, (struct sockaddr*) &sa, + sizeof(sa)); + + /* ----------------------------------------------- */ + /* Now we have TCP conncetion. Start SSL negotiation. */ + read(client_vio->sd,xbuf, sizeof(xbuf)); + sslconnect(ssl_connector,client_vio,60L); + err = vio_read(client_vio,xbuf, sizeof(xbuf)); + if (err<=0) { + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } + xbuf[err] = 0; + printf("client:got %s\n", xbuf); + my_free((uchar*)client_vio,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/test-sslserver.c b/externals/mysql/vio/test-sslserver.c new file mode 100644 index 00000000000..8877dd3cbc8 --- /dev/null +++ b/externals/mysql/vio/test-sslserver.c @@ -0,0 +1,155 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#ifdef HAVE_OPENSSL +#include <my_sys.h> +#include <m_string.h> +#include <m_ctype.h> +#include "mysql.h" +#include "errmsg.h" +#include <my_dir.h> +#include <my_getopt.h> +#include <signal.h> +#include <violite.h> + +const char *VER="0.2"; + + +#ifndef DBUG_OFF +const char *default_dbug_option="d:t:O,-"; +#endif + +#if 0 +static void +fatal_error( const char* r) +{ + perror(r); + exit(0); +} +#endif + +typedef struct { + int sd; + struct st_VioSSLFd* ssl_acceptor; +} TH_ARGS; + +static void +do_ssl_stuff( TH_ARGS* args) +{ + const char* s = "Huhuhuhuuu"; + Vio* server_vio; + int err; + DBUG_ENTER("do_ssl_stuff"); + + server_vio = vio_new(args->sd, VIO_TYPE_TCPIP, TRUE); + + /* ----------------------------------------------- */ + /* TCP connection is ready. Do server side SSL. */ + + err = write(server_vio->sd,(uchar*)s, strlen(s)); + sslaccept(args->ssl_acceptor,server_vio,60L); + err = server_vio->write(server_vio,(uchar*)s, strlen(s)); + DBUG_VOID_RETURN; +} + +static void* +client_thread( void* arg) +{ + my_thread_init(); + do_ssl_stuff((TH_ARGS*)arg); + return 0; +} + +int +main(int argc __attribute__((unused)), char** argv) +{ + char server_key[] = "../SSL/server-key.pem", + server_cert[] = "../SSL/server-cert.pem"; + char ca_file[] = "../SSL/cacert.pem", + *ca_path = 0, + *cipher = 0; + struct st_VioSSLFd* ssl_acceptor; + pthread_t th; + TH_ARGS th_args; + + + struct sockaddr_in sa_serv; + struct sockaddr_in sa_cli; + int listen_sd; + int err; + socklen_t client_len; + int reuseaddr = 1; /* better testing, uh? */ + + MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + DBUG_PUSH(default_dbug_option); + + printf("Server key/cert : %s/%s\n", server_key, server_cert); + if (ca_file!=0) + + printf("CAfile : %s\n", ca_file); + if (ca_path!=0) + printf("CApath : %s\n", ca_path); + + th_args.ssl_acceptor = ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path,cipher); + + /* ----------------------------------------------- */ + /* Prepare TCP socket for receiving connections */ + + listen_sd = socket (AF_INET, SOCK_STREAM, 0); + setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(&reuseaddr)); + + memset (&sa_serv, '\0', sizeof(sa_serv)); + sa_serv.sin_family = AF_INET; + sa_serv.sin_addr.s_addr = INADDR_ANY; + sa_serv.sin_port = htons (1111); /* Server Port number */ + + err = bind(listen_sd, (struct sockaddr*) &sa_serv, + sizeof (sa_serv)); + + /* Receive a TCP connection. */ + + err = listen (listen_sd, 5); + client_len = sizeof(sa_cli); + th_args.sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); + close (listen_sd); + + printf ("Connection from %lx, port %x\n", + (long)sa_cli.sin_addr.s_addr, sa_cli.sin_port); + + /* ----------------------------------------------- */ + /* TCP connection is ready. Do server side SSL. */ + + err = pthread_create(&th, NULL, client_thread, (void*)&th_args); + DBUG_PRINT("info", ("pthread_create: %d", err)); + pthread_join(th, NULL); + +#if 0 + if (err<=0) { + my_free((uchar*)ssl_acceptor,MYF(0)); + fatal_error("server:SSL_write"); + } +#endif /* 0 */ + + my_free((uchar*)ssl_acceptor,MYF(0)); + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/vio.c b/externals/mysql/vio/vio.c new file mode 100644 index 00000000000..cc5f629e26d --- /dev/null +++ b/externals/mysql/vio/vio.c @@ -0,0 +1,242 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Note that we can't have assertion on file descriptors; The reason for + this is that during mysql shutdown, another thread can close a file + we are working on. In this case we should just return read errors from + the file descriptior. +*/ + +#include "vio_priv.h" + +/* + * Helper to fill most of the Vio* with defaults. + */ + +static void vio_init(Vio* vio, enum enum_vio_type type, + my_socket sd, HANDLE hPipe, uint flags) +{ + DBUG_ENTER("vio_init"); + DBUG_PRINT("enter", ("type: %d sd: %d flags: %d", type, sd, flags)); + +#ifndef HAVE_VIO_READ_BUFF + flags&= ~VIO_BUFFERED_READ; +#endif + bzero((char*) vio, sizeof(*vio)); + vio->type = type; + vio->sd = sd; + vio->hPipe = hPipe; + vio->localhost= flags & VIO_LOCALHOST; + if ((flags & VIO_BUFFERED_READ) && + !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME)))) + flags&= ~VIO_BUFFERED_READ; +#ifdef __WIN__ + if (type == VIO_TYPE_NAMEDPIPE) + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read =vio_read_pipe; + vio->write =vio_write_pipe; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; + vio->vioclose =vio_close_pipe; + vio->peer_addr =vio_peer_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_ignore_timeout; + } + else /* default is VIO_TYPE_TCPIP */ +#endif +#ifdef HAVE_SMEM + if (type == VIO_TYPE_SHARED_MEMORY) + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read =vio_read_shared_memory; + vio->write =vio_write_shared_memory; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; + vio->vioclose =vio_close_shared_memory; + vio->peer_addr =vio_peer_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_ignore_timeout; + } + else +#endif +#ifdef HAVE_OPENSSL + if (type == VIO_TYPE_SSL) + { + vio->viodelete =vio_ssl_delete; + vio->vioerrno =vio_errno; + vio->read =vio_ssl_read; + vio->write =vio_ssl_write; + 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_peer_addr; + vio->vioblocking =vio_ssl_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_timeout; + } + else /* default is VIO_TYPE_TCPIP */ +#endif /* HAVE_OPENSSL */ + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read; + vio->write =vio_write; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->was_interrupted=vio_was_interrupted; + vio->vioclose =vio_close; + vio->peer_addr =vio_peer_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + vio->timeout =vio_timeout; + } + DBUG_VOID_RETURN; +} + + +/* Reset initialized VIO to use with another transport type */ + +void vio_reset(Vio* vio, enum enum_vio_type type, + my_socket sd, HANDLE hPipe, uint flags) +{ + my_free(vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR)); + vio_init(vio, type, sd, hPipe, flags); +} + + +/* Open the socket or TCP/IP connection and read the fnctl() status */ + +Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags) +{ + Vio *vio; + DBUG_ENTER("vio_new"); + DBUG_PRINT("enter", ("sd: %d", sd)); + if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) + { + vio_init(vio, type, sd, 0, flags); + sprintf(vio->desc, + (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), + vio->sd); +#if !defined(__WIN__) +#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 +#else /* !defined(__WIN__) */ + { + /* set to blocking mode by default */ + ulong arg=0, r; + r = ioctlsocket(sd,FIONBIO,(void*) &arg); + vio->fcntl_mode &= ~O_NONBLOCK; + } +#endif + } + DBUG_RETURN(vio); +} + + +#ifdef __WIN__ + +Vio *vio_new_win32pipe(HANDLE hPipe) +{ + Vio *vio; + DBUG_ENTER("vio_new_handle"); + if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) + { + vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST); + strmov(vio->desc, "named pipe"); + } + DBUG_RETURN(vio); +} + +#ifdef HAVE_SMEM +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_init(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, VIO_LOCALHOST); + 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); +} +#endif +#endif + + +void vio_delete(Vio* vio) +{ + if (!vio) + return; /* It must be safe to delete null pointers. */ + + if (vio->type != VIO_CLOSED) + vio->vioclose(vio); + my_free((uchar*) vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*) vio,MYF(0)); +} + + +/* + Cleanup memory allocated by vio or the + components below it when application finish + +*/ +void vio_end(void) +{ +#ifdef HAVE_YASSL + yaSSL_CleanUp(); +#endif +} diff --git a/externals/mysql/vio/vio_priv.h b/externals/mysql/vio/vio_priv.h new file mode 100644 index 00000000000..54c18dd8420 --- /dev/null +++ b/externals/mysql/vio/vio_priv.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Structures and functions private to the vio package */ + +#define DONT_MAP_VIO +#include <my_global.h> +#include <mysql_com.h> +#include <my_sys.h> +#include <m_string.h> +#include <violite.h> + +#ifndef __WIN__ +#include <sys/socket.h> +#include <netdb.h> +#endif + + +void vio_ignore_timeout(Vio *vio, uint which, uint timeout); +void vio_timeout(Vio *vio,uint which, uint timeout); + +#ifdef HAVE_OPENSSL +#include "my_net.h" /* needed because of struct in_addr */ + +size_t vio_ssl_read(Vio *vio,uchar* buf, size_t size); +size_t vio_ssl_write(Vio *vio,const uchar* buf, size_t size); + +/* When the workday is over... */ +int vio_ssl_close(Vio *vio); +void vio_ssl_delete(Vio *vio); + +int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); + +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/viosocket.c b/externals/mysql/vio/viosocket.c new file mode 100644 index 00000000000..e823f25c24e --- /dev/null +++ b/externals/mysql/vio/viosocket.c @@ -0,0 +1,714 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Note that we can't have assertion on file descriptors; The reason for + this is that during mysql shutdown, another thread can close a file + we are working on. In this case we should just return read errors from + the file descriptior. +*/ + +#include "vio_priv.h" + +int vio_errno(Vio *vio __attribute__((unused))) +{ + return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ +} + + +size_t vio_read(Vio * vio, uchar* buf, size_t size) +{ + size_t r; + DBUG_ENTER("vio_read"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf, + (uint) size)); + + /* Ensure nobody uses vio_read_buff and vio_read simultaneously */ + DBUG_ASSERT(vio->read_end == vio->read_pos); +#ifdef __WIN__ + r = recv(vio->sd, buf, size,0); +#else + errno=0; /* For linux */ + r = read(vio->sd, buf, size); +#endif /* __WIN__ */ +#ifndef DBUG_OFF + if (r == (size_t) -1) + { + DBUG_PRINT("vio_error", ("Got error %d during read",errno)); + } +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%ld", (long) r)); + DBUG_RETURN(r); +} + + +/* + Buffered read: if average read size is small it may + reduce number of syscalls. +*/ + +size_t vio_read_buff(Vio *vio, uchar* buf, size_t size) +{ + size_t rc; +#define VIO_UNBUFFERED_READ_MIN_SIZE 2048 + DBUG_ENTER("vio_read_buff"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf, + (uint) size)); + + if (vio->read_pos < vio->read_end) + { + rc= min((size_t) (vio->read_end - vio->read_pos), size); + memcpy(buf, vio->read_pos, rc); + vio->read_pos+= rc; + /* + Do not try to read from the socket now even if rc < size: + vio_read can return -1 due to an error or non-blocking mode, and + the safest way to handle it is to move to a separate branch. + */ + } + else if (size < VIO_UNBUFFERED_READ_MIN_SIZE) + { + rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE); + if (rc != 0 && rc != (size_t) -1) + { + if (rc > size) + { + vio->read_pos= vio->read_buffer + size; + vio->read_end= vio->read_buffer + rc; + rc= size; + } + memcpy(buf, vio->read_buffer, rc); + } + } + else + rc= vio_read(vio, buf, size); + DBUG_RETURN(rc); +#undef VIO_UNBUFFERED_READ_MIN_SIZE +} + + +size_t vio_write(Vio * vio, const uchar* buf, size_t size) +{ + size_t r; + DBUG_ENTER("vio_write"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf, + (uint) size)); +#ifdef __WIN__ + r = send(vio->sd, buf, size,0); +#else + r = write(vio->sd, buf, size); +#endif /* __WIN__ */ +#ifndef DBUG_OFF + if (r == (size_t) -1) + { + DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); + } +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%u", (uint) r)); + DBUG_RETURN(r); +} + +int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode, + my_bool *old_mode) +{ + int r=0; + DBUG_ENTER("vio_blocking"); + + *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK)); + DBUG_PRINT("enter", ("set_blocking_mode: %d old_mode: %d", + (int) set_blocking_mode, (int) *old_mode)); + +#if !defined(__WIN__) +#if !defined(NO_FCNTL_NONBLOCK) + if (vio->sd >= 0) + { + int old_fcntl=vio->fcntl_mode; + if (set_blocking_mode) + vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ + else + vio->fcntl_mode |= O_NONBLOCK; /* set bit */ + if (old_fcntl != vio->fcntl_mode) + { + r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode); + if (r == -1) + { + DBUG_PRINT("info", ("fcntl failed, errno %d", errno)); + vio->fcntl_mode= old_fcntl; + } + } + } +#else + r= set_blocking_mode ? 0 : 1; +#endif /* !defined(NO_FCNTL_NONBLOCK) */ +#else /* !defined(__WIN__) */ + if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY) + { + ulong arg; + int old_fcntl=vio->fcntl_mode; + if (set_blocking_mode) + { + arg = 0; + vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ + } + else + { + arg = 1; + vio->fcntl_mode |= O_NONBLOCK; /* set bit */ + } + if (old_fcntl != vio->fcntl_mode) + r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg); + } + else + r= test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode; +#endif /* !defined(__WIN__) */ + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + +my_bool +vio_is_blocking(Vio * vio) +{ + my_bool r; + DBUG_ENTER("vio_is_blocking"); + r = !(vio->fcntl_mode & O_NONBLOCK); + DBUG_PRINT("exit", ("%d", (int) r)); + DBUG_RETURN(r); +} + + +int vio_fastsend(Vio * vio __attribute__((unused))) +{ + int r=0; + DBUG_ENTER("vio_fastsend"); + +#if defined(IPTOS_THROUGHPUT) + { + int tos = IPTOS_THROUGHPUT; + r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); + } +#endif /* IPTOS_THROUGHPUT */ + if (!r) + { +#ifdef __WIN__ + BOOL nodelay= 1; +#else + int nodelay = 1; +#endif + + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, + IF_WIN(const char*, void*) &nodelay, + sizeof(nodelay)); + + } + 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_keepalive(Vio* vio, my_bool set_keep_alive) +{ + int r=0; + uint opt = 0; + DBUG_ENTER("vio_keepalive"); + DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d", vio->sd, (int) + set_keep_alive)); + if (vio->type != VIO_TYPE_NAMEDPIPE) + { + if (set_keep_alive) + opt = 1; + r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, + sizeof(opt)); + } + DBUG_RETURN(r); +} + + +my_bool +vio_should_retry(Vio * vio __attribute__((unused))) +{ + int en = socket_errno; + return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || + en == SOCKET_EWOULDBLOCK); +} + + +my_bool +vio_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_close(Vio * vio) +{ + int r=0; + DBUG_ENTER("vio_close"); +#ifdef _WIN32 + if (vio->type == VIO_TYPE_NAMEDPIPE) + { +#ifdef MYSQL_SERVER + CancelIo(vio->hPipe); + DisconnectNamedPipe(vio->hPipe); +#endif + r=CloseHandle(vio->hPipe); + } + else +#endif /* _WIN32 */ + if (vio->type != VIO_CLOSED) + { + DBUG_ASSERT(vio->sd >= 0); + if (shutdown(vio->sd, SHUT_RDWR)) + r= -1; + if (closesocket(vio->sd)) + r= -1; + } + if (r) + { + DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); + /* FIXME: error handling (not critical for MySQL) */ + } + vio->type= VIO_CLOSED; + vio->sd= -1; + DBUG_RETURN(r); +} + + +const char *vio_description(Vio * vio) +{ + return vio->desc; +} + +enum enum_vio_type vio_type(Vio* vio) +{ + return vio->type; +} + +my_socket vio_fd(Vio* vio) +{ + return vio->sd; +} + +my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen) +{ + DBUG_ENTER("vio_peer_addr"); + DBUG_PRINT("enter", ("sd: %d", vio->sd)); + + if (vio->localhost) + { + strmov(buf, "127.0.0.1"); + *port= 0; + } + else + { + int error; + char port_buf[NI_MAXSERV]; + socklen_t addrLen = sizeof(vio->remote); + if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote), + &addrLen) != 0) + { + DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); + DBUG_RETURN(1); + } + vio->addrLen= (int)addrLen; + + if ((error= getnameinfo((struct sockaddr *)(&vio->remote), + addrLen, + buf, buflen, + port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV))) + { + DBUG_PRINT("exit", ("getnameinfo gave error: %s", + gai_strerror(error))); + DBUG_RETURN(1); + } + + *port= (uint16)strtol(port_buf, (char **)NULL, 10); + + /* + A lot of users do not have IPv6 loopback resolving to localhost + correctly setup. Should this exist? No. If we do not do it though + we will be getting a lot of support questions from users who + have bad setups. This code should be removed by say... 2012. + -Brian + */ + if (!memcmp(buf, "::ffff:127.0.0.1", sizeof("::ffff:127.0.0.1"))) + strmov(buf, "127.0.0.1"); + } + DBUG_PRINT("exit", ("addr: %s", buf)); + DBUG_RETURN(0); +} + + +/* Return 0 if there is data to be read */ + +my_bool vio_poll_read(Vio *vio,uint timeout) +{ +#ifdef __WIN__ + int res; + my_socket fd= vio->sd; + fd_set readfds, errorfds; + struct timeval tm; + DBUG_ENTER("vio_poll"); + tm.tv_sec= timeout; + tm.tv_usec= 0; + FD_ZERO(&readfds); + FD_ZERO(&errorfds); + FD_SET(fd, &readfds); + FD_SET(fd, &errorfds); + /* The first argument is ignored on Windows, so a conversion to int is OK */ + if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0)) + { + DBUG_RETURN(res < 0 ? 0 : 1); + } + res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds); + DBUG_RETURN(!res); +#elif defined(HAVE_POLL) + struct pollfd fds; + int res; + DBUG_ENTER("vio_poll"); + fds.fd=vio->sd; + fds.events=POLLIN; + fds.revents=0; + if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) + { + DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ + } + DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1); +#else + return 0; +#endif +} + + +my_bool vio_peek_read(Vio *vio, uint *bytes) +{ +#ifdef __WIN__ + int len; + if (ioctlsocket(vio->sd, FIONREAD, &len)) + return TRUE; + *bytes= len; + return FALSE; +#elif FIONREAD_IN_SYS_IOCTL + int len; + if (ioctl(vio->sd, FIONREAD, &len) < 0) + return TRUE; + *bytes= len; + return FALSE; +#else + char buf[1024]; + ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK); + if (res < 0) + return TRUE; + *bytes= res; + return FALSE; +#endif +} + +void vio_timeout(Vio *vio, uint which, uint timeout) +{ +#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) + int r; + DBUG_ENTER("vio_timeout"); + + { +#ifdef __WIN__ + /* Windows expects time in milliseconds as int */ + int wait_timeout= (int) timeout * 1000; +#else + /* POSIX specifies time as struct timeval. */ + struct timeval wait_timeout; + wait_timeout.tv_sec= timeout; + wait_timeout.tv_usec= 0; +#endif + + r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, + IF_WIN(const char*, const void*)&wait_timeout, + sizeof(wait_timeout)); + + } + +#ifndef DBUG_OFF + if (r != 0) + DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno)); +#endif + + DBUG_VOID_RETURN; +#else +/* + Platforms not suporting setting of socket timeout should either use + thr_alarm or just run without read/write timeout(s) +*/ +#endif +} + + +#ifdef __WIN__ +size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size) +{ + DWORD length; + DBUG_ENTER("vio_read_pipe"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf, + (uint) size)); + + if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) + DBUG_RETURN(-1); + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN((size_t) length); +} + + +size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) +{ + DWORD length; + DBUG_ENTER("vio_write_pipe"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf, + (uint) size)); + + if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) + DBUG_RETURN(-1); + + DBUG_PRINT("exit", ("%d", length)); + DBUG_RETURN((size_t) length); +} + +int vio_close_pipe(Vio * vio) +{ + int r; + DBUG_ENTER("vio_close_pipe"); +#ifdef MYSQL_SERVER + CancelIo(vio->hPipe); + DisconnectNamedPipe(vio->hPipe); +#endif + r=CloseHandle(vio->hPipe); + if (r) + { + DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError())); + /* FIXME: error handling (not critical for MySQL) */ + } + vio->type= VIO_CLOSED; + vio->sd= -1; + DBUG_RETURN(r); +} + + +void vio_ignore_timeout(Vio *vio __attribute__((unused)), + uint which __attribute__((unused)), + uint timeout __attribute__((unused))) +{ +} + + +#ifdef HAVE_SMEM + +size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) +{ + size_t length; + size_t remain_local; + char *current_postion; + HANDLE events[2]; + + DBUG_ENTER("vio_read_shared_memory"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %d", vio->sd, buf, + size)); + + remain_local = size; + current_postion=buf; + + events[0]= vio->event_server_wrote; + events[1]= vio->event_conn_closed; + + do + { + if (vio->shared_memory_remain == 0) + { + /* + WaitForMultipleObjects can return next values: + WAIT_OBJECT_0+0 - event from vio->event_server_wrote + WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read + anything + WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything + */ + if (WaitForMultipleObjects(array_elements(events), events, FALSE, + vio->net->read_timeout*1000) != WAIT_OBJECT_0) + { + DBUG_RETURN(-1); + }; + + vio->shared_memory_pos = vio->handle_map; + vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos); + vio->shared_memory_pos+=4; + } + + length = size; + + if (vio->shared_memory_remain < length) + length = vio->shared_memory_remain; + if (length > remain_local) + length = remain_local; + + memcpy(current_postion,vio->shared_memory_pos,length); + + vio->shared_memory_remain-=length; + vio->shared_memory_pos+=length; + current_postion+=length; + remain_local-=length; + + if (!vio->shared_memory_remain) + { + if (!SetEvent(vio->event_client_read)) + DBUG_RETURN(-1); + } + } while (remain_local); + length = size; + + DBUG_PRINT("exit", ("%lu", (ulong) length)); + DBUG_RETURN(length); +} + + +size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) +{ + size_t length, remain, sz; + HANDLE pos; + const uchar *current_postion; + HANDLE events[2]; + + DBUG_ENTER("vio_write_shared_memory"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %d", vio->sd, buf, + size)); + + remain = size; + current_postion = buf; + + events[0]= vio->event_server_read; + events[1]= vio->event_conn_closed; + + while (remain != 0) + { + if (WaitForMultipleObjects(array_elements(events), events, FALSE, + vio->net->write_timeout*1000) != WAIT_OBJECT_0) + { + DBUG_RETURN((size_t) -1); + } + + sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length : + remain); + + int4store(vio->handle_map,sz); + pos = vio->handle_map + 4; + memcpy(pos,current_postion,sz); + remain-=sz; + current_postion+=sz; + if (!SetEvent(vio->event_client_wrote)) + DBUG_RETURN((size_t) -1); + } + length = size; + + DBUG_PRINT("exit", ("%lu", (ulong) length)); + DBUG_RETURN(length); +} + + +/** + Close shared memory and DBUG_PRINT any errors that happen on closing. + @return Zero if all closing functions succeed, and nonzero otherwise. +*/ +int vio_close_shared_memory(Vio * vio) +{ + int error_count= 0; + DBUG_ENTER("vio_close_shared_memory"); + if (vio->type != VIO_CLOSED) + { + /* + Set event_conn_closed for notification of both client and server that + connection is closed + */ + SetEvent(vio->event_conn_closed); + /* + Close all handlers. UnmapViewOfFile and CloseHandle return non-zero + result if they are success. + */ + if (UnmapViewOfFile(vio->handle_map) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); + } + if (CloseHandle(vio->event_server_wrote) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); + } + if (CloseHandle(vio->event_server_read) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); + } + if (CloseHandle(vio->event_client_wrote) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); + } + if (CloseHandle(vio->event_client_read) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); + } + if (CloseHandle(vio->handle_file_map) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); + } + if (CloseHandle(vio->event_conn_closed) == 0) + { + error_count++; + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); + } + } + vio->type= VIO_CLOSED; + vio->sd= -1; + DBUG_RETURN(error_count); +} +#endif /* HAVE_SMEM */ +#endif /* __WIN__ */ + + +/** + Number of bytes in the read buffer. + + @return number of bytes in the read buffer or < 0 if error. +*/ + +ssize_t vio_pending(Vio *vio) +{ +#ifdef HAVE_OPENSSL + SSL *ssl= (SSL*) vio->ssl_arg; +#endif + + if (vio->read_pos < vio->read_end) + return vio->read_end - vio->read_pos; + +#ifdef HAVE_OPENSSL + if (ssl) + return SSL_pending(ssl); +#endif + + return 0; +} diff --git a/externals/mysql/vio/viossl.c b/externals/mysql/vio/viossl.c new file mode 100644 index 00000000000..9cbd74034a9 --- /dev/null +++ b/externals/mysql/vio/viossl.c @@ -0,0 +1,279 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Note that we can't have assertion on file descriptors; The reason for + this is that during mysql shutdown, another thread can close a file + we are working on. In this case we should just return read errors from + the file descriptior. +*/ + +#include "vio_priv.h" + +#ifdef HAVE_OPENSSL + +#ifdef __NETWARE__ + +/* yaSSL already uses BSD sockets */ +#ifndef HAVE_YASSL + +/* + The default OpenSSL implementation on NetWare uses WinSock. + This code allows us to use the BSD sockets. +*/ + +static int SSL_set_fd_bsd(SSL *s, int fd) +{ + int result= -1; + BIO_METHOD *BIO_s_bsdsocket(); + BIO *bio; + + if ((bio= BIO_new(BIO_s_bsdsocket()))) + { + result= BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, bio); + } + return result; +} + +#define SSL_set_fd(A, B) SSL_set_fd_bsd((A), (B)) + +#endif /* HAVE_YASSL */ +#endif /* __NETWARE__ */ + + +static void +report_errors(SSL* ssl) +{ + unsigned long l; + const char *file; + const char *data; + int line, flags; +#ifndef DBUG_OFF + char buf[512]; +#endif + + DBUG_ENTER("report_errors"); + + while ((l= ERR_get_error_line_data(&file,&line,&data,&flags))) + { + DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), + file,line,(flags&ERR_TXT_STRING)?data:"")) ; + } + + if (ssl) + DBUG_PRINT("error", ("error: %s", + ERR_error_string(SSL_get_error(ssl, l), buf))); + + DBUG_PRINT("info", ("socket_errno: %d", socket_errno)); + DBUG_VOID_RETURN; +} + + +size_t vio_ssl_read(Vio *vio, uchar* buf, size_t size) +{ + size_t r; + DBUG_ENTER("vio_ssl_read"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u ssl: %p", + vio->sd, buf, (uint) size, vio->ssl_arg)); + + r= SSL_read((SSL*) vio->ssl_arg, buf, size); +#ifndef DBUG_OFF + if (r == (size_t) -1) + report_errors((SSL*) vio->ssl_arg); +#endif + DBUG_PRINT("exit", ("%u", (uint) r)); + DBUG_RETURN(r); +} + + +size_t vio_ssl_write(Vio *vio, const uchar* buf, size_t size) +{ + size_t r; + DBUG_ENTER("vio_ssl_write"); + DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, + buf, (uint) size)); + + r= SSL_write((SSL*) vio->ssl_arg, buf, size); +#ifndef DBUG_OFF + if (r == (size_t) -1) + report_errors((SSL*) vio->ssl_arg); +#endif + DBUG_PRINT("exit", ("%u", (uint) r)); + DBUG_RETURN(r); +} + + +int vio_ssl_close(Vio *vio) +{ + int r= 0; + SSL *ssl= (SSL*)vio->ssl_arg; + DBUG_ENTER("vio_ssl_close"); + + if (ssl) + { + /* + THE SSL standard says that SSL sockets must send and receive a close_notify + alert on socket shutdown to avoid truncation attacks. However, this can + cause problems since we often hold a lock during shutdown and this IO can + take an unbounded amount of time to complete. Since our packets are self + describing with length, we aren't vunerable to these attacks. Therefore, + we just shutdown by closing the socket (quiet shutdown). + */ + SSL_set_quiet_shutdown(ssl, 1); + + switch ((r= SSL_shutdown(ssl))) { + case 1: + /* Shutdown successful */ + break; + case 0: + /* + Shutdown not yet finished - since the socket is going to + be closed there is no need to call SSL_shutdown() a second + time to wait for the other side to respond + */ + break; + default: /* Shutdown failed */ + DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d", + SSL_get_error(ssl, r))); + break; + } + } + DBUG_RETURN(vio_close(vio)); +} + + +void vio_ssl_delete(Vio *vio) +{ + if (!vio) + return; /* It must be safe to delete null pointer */ + + if (vio->type == VIO_TYPE_SSL) + vio_ssl_close(vio); /* Still open, close connection first */ + + if (vio->ssl_arg) + { + SSL_free((SSL*) vio->ssl_arg); + vio->ssl_arg= 0; + } + + vio_delete(vio); +} + +#ifndef EMBEDDED_LIBRARY +static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout, + int (*connect_accept_func)(SSL*)) +{ + SSL *ssl; + my_bool unused; + my_bool was_blocking; + + DBUG_ENTER("ssl_do"); + DBUG_PRINT("enter", ("ptr: %p, sd: %d ctx: %p", + ptr, vio->sd, 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: %p timeout: %ld", ssl, timeout)); + SSL_clear(ssl); + SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout); + SSL_set_fd(ssl, vio->sd); + + if (connect_accept_func(ssl) < 1) + { + DBUG_PRINT("error", ("SSL_connect/accept 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); +} + + +int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +{ + DBUG_ENTER("sslaccept"); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept)); +} + + +int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout) +{ + DBUG_ENTER("sslconnect"); + DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect)); +} +#endif /*EMBEDDED_LIBRARY*/ + +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 */ + return (set_blocking_mode ? 0 : 1); +} + + + +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/viosslfactories.c b/externals/mysql/vio/viosslfactories.c new file mode 100644 index 00000000000..95dbd73d24d --- /dev/null +++ b/externals/mysql/vio/viosslfactories.c @@ -0,0 +1,385 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "vio_priv.h" + +#ifdef HAVE_OPENSSL + +static my_bool ssl_algorithms_added = FALSE; +static my_bool ssl_error_strings_loaded= FALSE; +static int verify_depth = 0; + +static unsigned char dh512_p[]= +{ + 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, + 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, + 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, + 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, + 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, + 0x47,0x74,0xE8,0x33, +}; + +static unsigned char dh512_g[]={ + 0x02, +}; + +static DH *get_dh512(void) +{ + DH *dh; + if ((dh=DH_new())) + { + dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); + dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); + if (! dh->p || ! dh->g) + { + DH_free(dh); + dh=0; + } + } + return(dh); +} + + +static void +report_errors() +{ + unsigned long l; + const char* file; + const char* data; + int line,flags; + + DBUG_ENTER("report_errors"); + + while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) + { +#ifndef DBUG_OFF /* Avoid warning */ + char buf[200]; + DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), + file,line,(flags & ERR_TXT_STRING) ? data : "")) ; +#endif + } + DBUG_VOID_RETURN; +} + + +static int +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) + { + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) + { + DBUG_PRINT("error",("unable to get certificate from '%s'", cert_file)); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, "SSL error: Unable to get certificate from '%s'\n", + cert_file); + fflush(stderr); + DBUG_RETURN(1); + } + + 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'", key_file)); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, "SSL error: Unable to get private key from '%s'\n", + key_file); + fflush(stderr); + DBUG_RETURN(1); + } + + /* + If we are using DSA, we can copy the parameters from the private key + Now we know that a key and cert have been set against the SSL context + */ + if (!SSL_CTX_check_private_key(ctx)) + { + DBUG_PRINT("error", + ("Private key does not match the certificate public key")); + DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE);); + fprintf(stderr, + "SSL error: " + "Private key does not match the certificate public key\n"); + fflush(stderr); + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + + +static int +vio_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + char buf[256]; + X509 *err_cert; + + DBUG_ENTER("vio_verify_callback"); + DBUG_PRINT("enter", ("ok: %d ctx: %p", ok, ctx)); + + 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) + { + 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; + } + 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)); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + DBUG_PRINT("error", ("notBefore")); + /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/ + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + DBUG_PRINT("error", ("notAfter error")); + /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/ + break; + } + DBUG_PRINT("exit", ("%d", ok)); + DBUG_RETURN(ok); +} + + +#ifdef __NETWARE__ + +/* NetWare SSL cleanup */ +void netware_ssl_cleanup() +{ + /* free memory from SSL_library_init() */ + EVP_cleanup(); + +/* OpenSSL NetWare port specific functions */ +#ifndef HAVE_YASSL + + /* free global X509 method */ + X509_STORE_method_cleanup(); + + /* free the thread_hash error table */ + ERR_free_state_table(); +#endif +} + + +/* NetWare SSL initialization */ +static void netware_ssl_init() +{ + /* cleanup OpenSSL library */ + NXVmRegisterExitHandler(netware_ssl_cleanup, NULL); +} + +#endif /* __NETWARE__ */ + + +static void check_ssl_init() +{ + if (!ssl_algorithms_added) + { + ssl_algorithms_added= TRUE; + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + } + +#ifdef __NETWARE__ + netware_ssl_init(); +#endif + + if (!ssl_error_strings_loaded) + { + ssl_error_strings_loaded= TRUE; + SSL_load_error_strings(); + } +} + +#ifndef EMBEDDED_LIBRARY +/************************ VioSSLFd **********************************/ +static 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"); + DBUG_PRINT("enter", + ("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' " + "cipher: '%s'", + key_file ? key_file : "NULL", + cert_file ? cert_file : "NULL", + ca_file ? ca_file : "NULL", + ca_path ? ca_path : "NULL", + cipher ? cipher : "NULL")); + + 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(); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } + + /* + Set the ciphers that can be used + NOTE: SSL_CTX_set_cipher_list will return 0 if + none of the provided ciphers could be selected + */ + if (cipher && + SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher) == 0) + { + DBUG_PRINT("error", ("failed to set ciphers to use")); + report_errors(); + SSL_CTX_free(ssl_fd->ssl_context); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } + + /* Load certs from the trusted ca */ + 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(ssl_fd->ssl_context) == 0) + { + DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); + report_errors(); + SSL_CTX_free(ssl_fd->ssl_context); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } + } + + if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file)) + { + DBUG_PRINT("error", ("vio_set_cert_stuff failed")); + report_errors(); + SSL_CTX_free(ssl_fd->ssl_context); + my_free((void*)ssl_fd,MYF(0)); + DBUG_RETURN(0); + } + + /* DH stuff */ + dh=get_dh512(); + SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh); + DH_free(dh); + + DBUG_PRINT("exit", ("OK 1")); + + DBUG_RETURN(ssl_fd); +} + + +/************************ 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) +{ + struct st_VioSSLFd *ssl_fd; + int verify= SSL_VERIFY_PEER; + + /* + Turn off verification of servers certificate if both + ca_file and ca_path is set to NULL + */ + if (ca_file == 0 && ca_path == 0) + 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 VioSSLFd as a "connector" ie. the client side */ + + /* + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. + */ + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + + return ssl_fd; +} + + +/************************ 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()))) + { + return 0; + } + /* Init the the VioSSLFd as a "acceptor" ie. the server side */ + + /* Set max number of cached sessions, returns the previous size */ + SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); + + /* + The verify_callback function is used to control the behaviour + when the SSL_VERIFY_PEER flag is set. + */ + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + + /* + Set session_id - an identifier for this server session + Use the ssl_fd pointer + */ + SSL_CTX_set_session_id_context(ssl_fd->ssl_context, + (const unsigned char *)ssl_fd, + sizeof(ssl_fd)); + + return ssl_fd; +} + +void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd) +{ + SSL_CTX_free(fd->ssl_context); + my_free((uchar*) fd, MYF(0)); +} +#endif /*EMBEDDED_LIBRARY*/ +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/viotest-ssl.c b/externals/mysql/vio/viotest-ssl.c new file mode 100644 index 00000000000..b8abbac4ed6 --- /dev/null +++ b/externals/mysql/vio/viotest-ssl.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#ifdef HAVE_OPENSSL +#include <my_sys.h> +#include <m_string.h> +#include <m_ctype.h> +#include "mysql.h" +#include "errmsg.h" +#include <my_dir.h> +#include <my_getopt.h> +#include <signal.h> +#include <violite.h> + +const char *VER="0.2"; + + +#ifndef DBUG_OFF +const char *default_dbug_option="d:t:O,/tmp/viotest-ssl.trace"; +#endif + +void +fatal_error(const char *r) +{ + perror(r); + exit(0); +} + +void +print_usage() +{ + printf("viossl-test: testing SSL virtual IO. Usage:\n"); + printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n"); +} + + +int main(int argc, char **argv) +{ + char* server_key = 0; + char* server_cert = 0; + char* client_key = 0; + char* client_cert = 0; + char* ca_file = 0; + char* ca_path = 0; + int child_pid,sv[2]; + struct st_VioSSLAcceptorFd* ssl_acceptor=0; + struct st_VioSSLConnectorFd* ssl_connector=0; + Vio* client_vio=0; + Vio* server_vio=0; + MY_INIT(argv[0]); + DBUG_PROCESS(argv[0]); + DBUG_PUSH(default_dbug_option); + + if (argc<5) + { + print_usage(); + return 1; + } + + server_key = argv[1]; + server_cert = argv[2]; + client_key = argv[3]; + client_cert = argv[4]; + if (argc>5) + ca_file = argv[5]; + if (argc>6) + ca_path = argv[6]; + printf("Server key/cert : %s/%s\n", server_key, server_cert); + printf("Client key/cert : %s/%s\n", client_key, client_cert); + if (ca_file!=0) + printf("CAfile : %s\n", ca_file); + if (ca_path!=0) + printf("CApath : %s\n", ca_path); + + + if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1) + fatal_error("socketpair"); + + ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, + ca_path); + ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, + ca_path); + + client_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); + client_vio->sd = sv[0]; + sslconnect(ssl_connector,client_vio); + server_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0)); + server_vio->sd = sv[1]; + sslaccept(ssl_acceptor,server_vio); + + printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd); + + child_pid = fork(); + if (child_pid==-1) + { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("fork"); + } + if (child_pid==0) + { + /* child, therefore, client */ + char xbuf[100]; + int r = vio_ssl_read(client_vio,xbuf, sizeof(xbuf)); + if (r<=0) { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } + xbuf[r] = 0; + printf("client:got %s\n", xbuf); + my_free((uchar*)client_vio,MYF(0)); + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + sleep(1); + } + else + { + const char* s = "Huhuhuh"; + int r = vio_ssl_write(server_vio,(uchar*)s, strlen(s)); + if (r<=0) { + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + fatal_error("server:SSL_write"); + } + my_free((uchar*)server_vio,MYF(0)); + my_free((uchar*)ssl_acceptor,MYF(0)); + my_free((uchar*)ssl_connector,MYF(0)); + sleep(1); + } + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/externals/mysql/vio/viotest-sslconnect.cc b/externals/mysql/vio/viotest-sslconnect.cc new file mode 100644 index 00000000000..89e1a6e7dfe --- /dev/null +++ b/externals/mysql/vio/viotest-sslconnect.cc @@ -0,0 +1,80 @@ + +/* +** Virtual I/O library +** Written by Andrei Errapart <andreie@no.spam.ee> +*/ + +#include "all.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <stdio.h> +#include <unistd.h> + + +void +fatal_error( const char* r) +{ + perror(r); + exit(0); +} + +void +print_usage() +{ + printf("viotest-sslconnect: testing SSL virtual IO. Usage:\n"); + printf("viotest-sslconnect key cert\n"); +} + +int +main( int argc, + char** argv) +{ + char* key = 0; + char* cert = 0; + + if (argc<3) + { + print_usage(); + return 1; + } + + char ip[4] = {127, 0, 0, 1}; + unsigned long addr = (unsigned long) + ((unsigned long)ip[0]<<24L)| + ((unsigned long)ip[1]<<16L)| + ((unsigned long)ip[2]<< 8L)| + ((unsigned long)ip[3]); + int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd<0) + fatal_error("socket"); + struct sockaddr_in sa; + sa.sin_family = AF_INET; + sa.sin_port=htons(4433); + sa.sin_addr.s_addr=htonl(addr); + int sa_size = sizeof sa; + if (connect(fd, reinterpret_cast<const sockaddr*>(&sa), sa_size)==-1) + fatal_error("connect"); + key = argv[1]; + cert = argv[2]; + printf("Key : %s\n", key); + printf("Cert : %s\n", cert); + + VIO_NS::VioSSLConnectorFd* ssl_connector = new VIO_NS::VioSSLConnectorFd(cert, key,0,0); + + VIO_NS::VioSSL* vio = ssl_connector->connect(fd); + + char xbuf[100]; + int r = vio->read(xbuf, sizeof(xbuf)); + if (r<=0) { + delete ssl_connector; + delete vio; + fatal_error("client:SSL_read"); + } + xbuf[r] = 0; + printf("client:got %s\n", xbuf); + delete vio; + delete ssl_connector; + return 0; +} diff --git a/externals/mysql/vio/viotest.cc b/externals/mysql/vio/viotest.cc new file mode 100644 index 00000000000..490a9ca6694 --- /dev/null +++ b/externals/mysql/vio/viotest.cc @@ -0,0 +1,47 @@ +/* +** Virtual I/O library +** Written by Andrei Errapart <andreie@no.spam.ee> +*/ + +#include "all.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> + +#include <string.h> + +VIO_NS_USING; + +int +main( int argc, + char** argv) +{ + VioFd* fs = 0; + VioSocket* ss = 0; + int fd = -1; + char* hh = "hshshsh\n"; + + DBUG_ENTER("main"); + DBUG_PROCESS(argv[0]); + DBUG_PUSH("d:t"); + + fd = open("/dev/tty", O_WRONLY); + if (fd<0) + { + perror("open"); + return 1; + } + fs = new VioFd(fd); + ss = new VioSocket(fd); + if (fs->write(hh,strlen(hh)) < 0) + perror("write"); + ss->write(hh,strlen(hh)); + printf("peer_name:%s\n", ss->peer_name()); + printf("cipher_description:%s\n", ss->cipher_description()); + delete fs; + delete ss; + + DBUG_RETURN(0); +} + |
