diff options
Diffstat (limited to 'vio')
-rw-r--r-- | vio/Makefile.am | 27 | ||||
-rw-r--r-- | vio/Vio.cc | 23 | ||||
-rw-r--r-- | vio/Vio.h | 64 | ||||
-rw-r--r-- | vio/VioAcceptorFd.cc | 18 | ||||
-rw-r--r-- | vio/VioAcceptorFd.h | 23 | ||||
-rw-r--r-- | vio/VioConnectorFd.cc | 22 | ||||
-rw-r--r-- | vio/VioConnectorFd.h | 19 | ||||
-rw-r--r-- | vio/VioFd.cc | 156 | ||||
-rw-r--r-- | vio/VioFd.h | 38 | ||||
-rw-r--r-- | vio/VioPipe.cc | 25 | ||||
-rw-r--r-- | vio/VioPipe.h | 38 | ||||
-rw-r--r-- | vio/VioSSL.cc | 292 | ||||
-rw-r--r-- | vio/VioSSL.h | 54 | ||||
-rw-r--r-- | vio/VioSSLAcceptorFd.cc | 4 | ||||
-rw-r--r-- | vio/VioSSLFactoriesFd.cc | 360 | ||||
-rw-r--r-- | vio/VioSSLFactoriesFd.h | 64 | ||||
-rw-r--r-- | vio/VioSocket.cc | 326 | ||||
-rw-r--r-- | vio/VioSocket.h | 55 | ||||
-rw-r--r-- | vio/test-ssl.c | 148 | ||||
-rw-r--r-- | vio/test-sslclient.c | 105 | ||||
-rw-r--r-- | vio/test-sslserver.c | 159 | ||||
-rw-r--r-- | vio/version.cc | 7 | ||||
-rw-r--r-- | vio/vio-global.h | 33 | ||||
-rw-r--r-- | vio/vio.c | 135 | ||||
-rw-r--r-- | vio/vioelitexx.cc | 26 | ||||
-rw-r--r-- | vio/violite.h | 101 | ||||
-rw-r--r-- | vio/viosocket.c | 331 | ||||
-rw-r--r-- | vio/viossl.c | 365 | ||||
-rw-r--r-- | vio/viosslfactories.c | 352 | ||||
-rw-r--r-- | vio/viotest-ssl.c | 156 | ||||
-rw-r--r-- | vio/viotest-ssl.cc | 104 | ||||
-rw-r--r-- | vio/viotypes.h | 32 |
32 files changed, 1765 insertions, 1897 deletions
diff --git a/vio/Makefile.am b/vio/Makefile.am index 9bb8691eee6..b512ec33777 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -14,20 +14,21 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = -I$(srcdir)/../include -I../include \ - @OPENSSL_INCLUDES@ -LDADD = libvio.la -pkglib_LTLIBRARIES = libvio.la -noinst_PROGRAMS = +INCLUDES = -I$(srcdir)/../include -I../include $(openssl_includes) +LDADD = @CLIENT_EXTRA_LDFLAGS@ libvio.a $(openssl_libs) +pkglib_LIBRARIES = libvio.a +noinst_PROGRAMS = test-ssl test-sslserver test-sslclient noinst_HEADERS = -libvio_la_SOURCES = \ - Vio.cc VioAcceptorFd.cc \ - VioConnectorFd.cc VioFd.cc \ - VioHandle.cc VioSSL.cc \ - VioSSLFactoriesFd.cc VioSocket.cc \ - auto.cc hostnamexx.cc \ - vdbug.cc version.cc \ - vmem.cc violitexx.cc +test_ssl_SOURCES = test-ssl.c +test_ssl_LDADD = @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \ + ../strings/libmystrings.a libvio.a $(openssl_libs) +test_sslserver_SOURCES = test-sslserver.c +test_sslserver_LDADD = @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \ + ../strings/libmystrings.a libvio.a $(openssl_libs) +test_sslclient_SOURCES = test-sslclient.c +test_sslclient_LDADD = @CLIENT_EXTRA_LDFLAGS@ ../dbug/libdbug.a libvio.a ../mysys/libmysys.a \ + ../strings/libmystrings.a libvio.a $(openssl_libs) +libvio_a_SOURCES = vio.c viosocket.c viossl.c viosslfactories.c OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ __math.h time.h __time.h unistd.h __unistd.h types.h \ diff --git a/vio/Vio.cc b/vio/Vio.cc deleted file mode 100644 index b15f9cfa6d2..00000000000 --- a/vio/Vio.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif -#include "vio-global.h" - -VIO_NS_BEGIN - -void -Vio::release() -{ - delete this; -} - -Vio::~Vio() -{ -} - -VIO_NS_END diff --git a/vio/Vio.h b/vio/Vio.h deleted file mode 100644 index 959d472873f..00000000000 --- a/vio/Vio.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Abstract Virtual IO interface - class Vio. Heavily - * influenced by Berkeley sockets and oriented toward MySQL. - */ - -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -** Modified by Monty -*/ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, - VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL}; - -class Vio { -public: - virtual bool is_open() const = 0; - virtual int read(vio_ptr buf, int size) = 0; - virtual int write(const vio_ptr buf, int size) = 0; - virtual int blocking(bool onoff) = 0; - virtual bool blocking() const = 0; - virtual bool fcntl() const = 0; - virtual int fastsend(bool onoff = true) = 0; - virtual int keepalive(bool onoff) = 0; - virtual bool should_retry() const = 0; - virtual int close() = 0; - virtual void release(); - virtual const char* description() const = 0; - virtual bool peer_addr(char *buf) const = 0; - virtual const char* cipher_description() const = 0; - virtual int vio_errno(); - virtual ~Vio(); -}; - -/* Macros to simulate the violite C interface */ - - -Vio *vio_new(my_socket sd, enum enum_vio_type type, - my_bool localhost); -#ifdef __WIN__ -Vio* vio_new_win32pipe(HANDLE hPipe); -#endif - -#define vio_delete(vio) delete vio -#define vio_read(vio,buf,size) vio->read(buf,size) -#define vio_write(vio,buf,size) vio->write(buf,size) -#define vio_blocking(vio,mode) vio->blocking(mode) -#define vio_is_blocking(vio) vio->is_blocking() -#define vio_fastsend(vio,mode) vio->fastsend(mode) -#define vio_keepalive(vio,mode) vio->keepalive(mode) -#define vio_shouldretry(vio) vio->shouldretry(mode) -#define vio_close(vio) vio->close() -#define vio_description(vio) vio->description() -#define vio_errno(Vio *vio) vio->errno() -#define vio_peer_addr(vio,buf) vio->peer_addr(buf) -#define vio_in_addr(vio,in) vio->in_addr(in) - -VIO_NS_END diff --git a/vio/VioAcceptorFd.cc b/vio/VioAcceptorFd.cc deleted file mode 100644 index 4572e2cb71b..00000000000 --- a/vio/VioAcceptorFd.cc +++ /dev/null @@ -1,18 +0,0 @@ - -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -#include "vio-global.h" -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -VIO_NS_BEGIN - -VioAcceptorFd::~VioAcceptorFd() -{ -} - -VIO_NS_END diff --git a/vio/VioAcceptorFd.h b/vio/VioAcceptorFd.h deleted file mode 100644 index e0441780db9..00000000000 --- a/vio/VioAcceptorFd.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -/* - * Abstract acceptor. - */ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioAcceptorFd -{ -public: - virtual ~VioAcceptorFd(); - virtual Vio* accept( int fd) = 0; -}; - -VIO_NS_END diff --git a/vio/VioConnectorFd.cc b/vio/VioConnectorFd.cc deleted file mode 100644 index 49f81077a84..00000000000 --- a/vio/VioConnectorFd.cc +++ /dev/null @@ -1,22 +0,0 @@ - -/* - * Unneccessary virtual destructor. - */ - -#include "vio-global.h" -#include <unistd.h> -#include <fcntl.h> -#include <assert.h> - -#include "viotypes.h" -#include "Vio.h" -#include "VioConnectorFd.h" - -VIO_NS_BEGIN - -VioConnectorFd::~VioConnectorFd() -{ -} - -VIO_NS_END - diff --git a/vio/VioConnectorFd.h b/vio/VioConnectorFd.h deleted file mode 100644 index da684df5f1b..00000000000 --- a/vio/VioConnectorFd.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Abstract connector. The file (or socket) descriptor has to be - * prepared. - */ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioConnectorFd -{ -public: - virtual ~VioConnectorFd(); - virtual Vio* connect(int fd) = 0; -}; - -VIO_NS_END diff --git a/vio/VioFd.cc b/vio/VioFd.cc deleted file mode 100644 index da59798fc25..00000000000 --- a/vio/VioFd.cc +++ /dev/null @@ -1,156 +0,0 @@ -/* -** Virtual I/O library for files -** Written by Andrei Errapart <andreie@no.spam.ee> -** Checked and modfied by Monty -*/ - -#include "vio-global.h" -#include <assert.h> - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -VIO_NS_BEGIN - -VioFd::VioFd( int fd) : fd_(fd) -{ - sprintf(desc_, "VioFd(%d)", fd_); -} - -VioFd:: ~VioFd() -{ - if (fd_ >= 0) - { - it r = ::close(fd_); - if ( r < 0) - { - /* FIXME: error handling (Not Critical for MySQL) */ - } - } -} - - -bool -VioFd::open() const -{ - return fd_ >= 0; -} - -int -VioFd::read(vio_ptr buf, int size) -{ - assert(fd_>=0); - return ::read(fd_, buf, size); -} - -int -VioFd::write(const vio_ptr buf, int size) -{ - assert(fd_>=0); - return ::write(fd_, buf, size); -} - -int -VioFd::blocking(bool onoff) -{ - if (onoff) - return 0; - else - return -1; -} - -bool -VioFd::blocking() const -{ - return true; -} - -int -VioFd::fastsend(bool tmp) -{ - return 0; -} - - -int -VioFd::keepalive(boolonoff) -{ - return -2; // Why -2 ? (monty) -} - -bool -VioFd::fcntl() const -{ - return FALSE; -} - -bool -VioFd::should_retry() const -{ - return FALSE; -} - -int -VioFd::fcntl(int cmd) -{ - assert(fd_>=0); - return ::fcntl(fd_, cmd); -} - -int -VioFd::fcntl(int cmd, long arg) -{ - assert(fd_>=0); - return ::fcntl(fd_, cmd, arg); -} - -int -VioFd::fcntl(int cmd, struct flock* lock) -{ - assert(fd_>=0); - return ::fcntl(fd_, cmd, lock); -} - -int -VioFd::close() -{ - int r = -2; - if (fd_>=0) - { - - if ((r= ::close(fd_)) == 0) - fd_ = -1; - } - else - { - /* FIXME: error handling */ - } - return r; -} - -const char* -VioFd::description() const -{ - return desc_; -} - -const char* -VioFd::peer_addr() const -{ - return ""; -} - -const char* -VioFd::peer_name() const -{ - return "localhost"; -} - -const char* -VioFd::cipher_description() const -{ - return ""; -} - -VIO_NS_END diff --git a/vio/VioFd.h b/vio/VioFd.h deleted file mode 100644 index f1c009d848c..00000000000 --- a/vio/VioFd.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Concrete Vio around a file descriptor. - */ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioFd : public Vio -{ -public: - VioFd( int fd); - virtual ~VioFd(); - virtual bool open() const; - virtual int read( vio_ptr buf, int size); - virtual int write( const vio_ptr buf, int size); - virtual bool blocking() const; - virtual int blocking(bool onoff); - virtual int fastsend(bool onoff=true); - virtual int keepalive( bool onoff); - virtual bool fcntl() const; - virtual bool should_retry() const; - virtual int fcntl( int cmd); - virtual int fcntl( int cmd, long arg); - virtual int fcntl( int cmd, struct flock* lock); - virtual int close(); - virtual const char* description() const; - virtual const char* peer_addr() const; - virtual bool peer_name(char *buf) const; - virtual const char* cipher_description() const; -private: - int fd_; - char desc_[100]; -}; - -VIO_NS_END diff --git a/vio/VioPipe.cc b/vio/VioPipe.cc deleted file mode 100644 index 5d6f9f36496..00000000000 --- a/vio/VioPipe.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* -** Virtual I/O library for Windows named pipes -** Written by Monty -*/ - - -#ifdef __WIN32__ -#include "vio-global.h" - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -VIO_NS_BEGIN - - - - - - - - -VIO_NS_END - -#endif /* WIN32 */ diff --git a/vio/VioPipe.h b/vio/VioPipe.h deleted file mode 100644 index a6bb587c548..00000000000 --- a/vio/VioPipe.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Concrete Vio around Handle. - */ - -#ifdef __WIN__ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioPipe : public Vio -{ -public: - VioPipe(int fd); - virtual ~VioPipe(); - virtual bool is_open() const; - virtual int read(vio_ptr buf, int size); - virtual int write(const vio_ptr buf, int size); - virtual int blocking(bool onoff); - virtual bool blocking() const; - virtual bool fcntl() const; - virtual int fastsend(bool onoff = true); - virtual int keepalive(bool onoff); - virtual bool should_retry() const; - virtual int close(); - virtual void release(); - virtual const char* description() const; - virtual bool peer_addr(char *buf) const; - virtual const char* cipher_description() const { return "";} - virtual int vio_errno(); -private: -}; - -VIO_NS_END - -#endif /* WIN32 */ diff --git a/vio/VioSSL.cc b/vio/VioSSL.cc deleted file mode 100644 index 15964c09aba..00000000000 --- a/vio/VioSSL.cc +++ /dev/null @@ -1,292 +0,0 @@ -/* -** Virtual I/O library for SSL wrapper -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -/* - * This file has some huge DBUG_ statements. Boy, this is silly... - */ - -#include "vio-global.h" -#ifdef VIO_HAVE_OPENSSL -#include <assert.h> -#include <netinet/in.h> -#include <openssl/x509.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/pem.h> - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -VIO_NS_BEGIN - -#define this_ssl_con my_static_cast(SSL*)(this->ssl_con_) -#define this_bio my_static_cast(BIO*)(this->bio_) -typedef char* dataptr_t; - -static void -report_errors() -{ - unsigned long l; - const char* file; - const char* data; - int line,flags; - DBUG_ENTER("VioSSLConnectorFd::report_errors"); - - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) - { - char buf[200]; - DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), - file,line,(flags&ERR_TXT_STRING)?data:"")) ; - } - DBUG_VOID_RETURN; -} - -//FIXME: duplicate code! -VioSSL::VioSSL(int fd, - vio_ptr ssl_context, - int state) - : bio_(0), ssl_con_(0), open_(FALSE), sd_(new VioSocket(fd)) -{ - DBUG_ENTER("VioSSL::VioSSL"); - DBUG_PRINT("enter", ("this=%p, fd=%d, ssl_context=%p, state=%d", - this, fd, ssl_context, state)); - assert(fd!=0); - assert(ssl_context!=0); - assert(state==state_connect || state==state_accept); - - if (!init_bio_(fd, ssl_context, state, BIO_NOCLOSE)) - open_ = true; - DBUG_VOID_RETURN; -} - - -VioSSL::VioSSL(VioSocket* sd, - vio_ptr ssl_context, - int state) - :bio_(0), ssl_con_(0), open_(FALSE), sd_(sd) -{ - DBUG_ENTER("VioSSL::VioSSL"); - DBUG_PRINT("enter", - ("this=%p, sd=%s, ssl_context=%p, state=%d", - this, sd ? sd->description() : "0", ssl_context, state)); - assert(sd != 0); - assert(ssl_context != 0); - assert(state == state_connect || state==state_accept); - - if (!init_bio_(sd->sd_, ssl_context, state, BIO_NOCLOSE)) - open_ = true; - DBUG_VOID_RETURN; -} - -VioSSL::~VioSSL() -{ - DBUG_ENTER("VioSSL::~VioSSL"); - DBUG_PRINT("enter", ("this=%p", this)); - if (ssl_con_!=0) - { - SSL_shutdown(this_ssl_con); - SSL_free(this_ssl_con); - } - if (sd_!=0) - delete sd_; - /* FIXME: no need to close bio? */ - /* - if (bio_!=0) - BIO_free(this_bio); - */ - DBUG_VOID_RETURN; -} - -bool -VioSSL::is_open() const -{ - return open_; -} - -int -VioSSL::read(vio_ptr buf, int size) -{ - int r; - DBUG_ENTER("VioSSL::read"); - DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size)); - assert(this_ssl_con != 0); - r = SSL_read(this_ssl_con, my_static_cast(dataptr_t)(buf), size); - if ( r< 0) - report_errors(); - DBUG_PRINT("exit", ("r=%d", r)); - DBUG_RETURN(r); -} - -int -VioSSL::write(const vio_ptr buf, int size) -{ - int r; - DBUG_ENTER("VioSSL::write"); - DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size)); - assert(this_ssl_con!=0); - r = SSL_write(this_ssl_con, my_static_cast(dataptr_t)(buf), size); - if (r<0) - report_errors(); - DBUG_PRINT("exit", ("r=%d", r)); - DBUG_RETURN(r); -} - -int -VioSSL::blocking(bool onoff) -{ - int r; - DBUG_ENTER("VioSSL::blocking"); - DBUG_PRINT("enter", ("this=%p, onoff=%s", this, onoff?"true":"false")); - r = sd_->blocking(onoff); - DBUG_PRINT("exit", ("r=%d", (int)r )); - DBUG_RETURN(r); -} - -bool -VioSSL::blocking() const -{ - bool r; - DBUG_ENTER("VioSSL::blocking"); - DBUG_PRINT("enter", ("this=%p", this)); - r = sd_->blocking(); - DBUG_PRINT("exit", ("r=%d", (int)r )); - DBUG_RETURN(r); -} - -int -VioSSL::fastsend(bool onoff) -{ - int r; - DBUG_ENTER("VioSSL::fastsend"); - DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff)); - r = sd_->fastsend(onoff); - DBUG_PRINT("exit", ("r=%d", (int)r )); - DBUG_RETURN(r); -} - -int VioSSL::keepalive(bool onoff) -{ - int r; - DBUG_ENTER("VioSSL::keepalive"); - DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff)); - r = sd_->keepalive(onoff); - DBUG_PRINT("exit", ("r=%d", int(r) )); - DBUG_RETURN(r); -} - -bool -VioSSL::fcntl() const -{ - bool r; - DBUG_ENTER("VioSSL::fcntl"); - DBUG_PRINT("enter", ("this=%p", this)); - r = sd_->fcntl(); - DBUG_PRINT("exit", ("r=%d", (int)r )); - DBUG_RETURN(r); -} - -bool -VioSSL::should_retry() const -{ - bool r; - DBUG_ENTER("VioSSL::should_retry"); - DBUG_PRINT("enter", ("this=%p", this)); - r = sd_->should_retry(); - DBUG_PRINT("exit", ("r=%d", (int)r )); - DBUG_RETURN(r); -} - -int -VioSSL::close() -{ - int r= -2; - DBUG_ENTER("VioSSL::close"); - DBUG_PRINT("enter", ("this=%p", this)); - if (ssl_con) - { - r = SSL_shutdown(this_ssl_con); - SSL_free(this_ssl_con); - ssl_con_ = 0; - BIO_free(this_bio); - bio_ = 0; - } - DBUG_PRINT("exit", ("r=%d", r)); - DBUG_RETURN(r); -} - -const char* -VioSSL::description() const -{ - return desc_; -} - -const char* -VioSSL::peer_addr() const -{ - if (sd_!=0) - return sd != 0 ? sd_->peer_addr() : ""; -} - -const char* -VioSSL::peer_name() const -{ - return sd != 0 ? sd_->peer_name() : ""; -} - -const char* -VioSSL::cipher_description() const -{ - return SSL_get_cipher_name(this_ssl_con); -} - - -int -VioSSL::init_bio_(int fd, - vio_ptr ssl_context, - int state, - int bio_flags) -{ - DBUG_ENTER("VioSSL::init_bio_"); - DBUG_PRINT("enter", - ("this=%p, fd=%p, ssl_context=%p, state=%d, bio_flags=%d", - this, fd, ssl_context, state, bio_flags)); - - - if (!(ssl_con_ = SSL_new(my_static_cast(SSL_CTX*)(ssl_context)))) - { - DBUG_PRINT("error", ("SSL_new failure")); - report_errors(); - DBUG_RETURN(-1); - } - if (!(bio_ = BIO_new_socket(fd, bio_flags))) - { - DBUG_PRINT("error", ("BIO_new_socket failure")); - report_errors(); - SSL_free(ssl_con_); - ssl_con_ =0; - DBUG_RETURN(-1); - } - SSL_set_bio(this_ssl_con, this_bio, this_bio); - switch(state) { - case state_connect: - SSL_set_connect_state(this_ssl_con); - break; - case state_accept: - SSL_set_accept_state(this_ssl_con); - break; - default: - assert(0); - } - sprintf(desc_, "VioSSL(%d)", fd); - ssl_cip_ = new SSL_CIPHER ; - DBUG_RETURN(0); -} - - -VIO_NS_END - -#endif /* VIO_HAVE_OPENSSL */ - diff --git a/vio/VioSSL.h b/vio/VioSSL.h deleted file mode 100644 index 6446c10700e..00000000000 --- a/vio/VioSSL.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Concrete Vio around OpenSSL's SSL structure. - */ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioSocket; - -class VioSSL : public Vio -{ -public: - enum { - state_connect = 1, - state_accept = 2 - }; -public: - VioSSL(int fd, vio_ptr ssl_context, int state); - VioSSL(VioSocket* sd, vio_ptr ssl_context, int state); - virtual ~VioSSL(); - virtual bool open() const; - virtual int read( vio_ptr buf, int size); - virtual int write( const vio_ptr buf, int size); - virtual bool blocking() const; - virtual int blocking(bool onoff); - virtual int fastsend(bool onoff=true); - virtual int keepalive(bool onoff); - virtual bool fcntl() const; - virtual bool should_retry() const; - virtual int close(); - virtual const char* description() const; - virtual const char* peer_addr() const; - virtual const char* peer_name() const; - virtual const char* cipher_description() const; - -private: - int init_bio_(int fd, - vio_ptr ssl_context, - int state, - int bio_flags); - vio_ptr bio_; - vio_ptr ssl_con_; - vio_ptr ssl_cip_; - char desc_[100]; - bool open_; - VioSocket* sd_; -}; - -VIO_NS_END - -#endif /* VIO_HAVE_OPENSSL */ diff --git a/vio/VioSSLAcceptorFd.cc b/vio/VioSSLAcceptorFd.cc deleted file mode 100644 index f821685430e..00000000000 --- a/vio/VioSSLAcceptorFd.cc +++ /dev/null @@ -1,4 +0,0 @@ - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif diff --git a/vio/VioSSLFactoriesFd.cc b/vio/VioSSLFactoriesFd.cc deleted file mode 100644 index bd64202770a..00000000000 --- a/vio/VioSSLFactoriesFd.cc +++ /dev/null @@ -1,360 +0,0 @@ -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -#include "vio-global.h" - -#ifdef VIO_HAVE_OPENSSL - -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif - -#include <netinet/in.h> -#include <openssl/x509.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/pem.h> -#include <openssl/asn1.h> - -VIO_NS_BEGIN - -#define this_ssl_method my_static_cast(SSL_METHOD*)(this->ssl_method_) -#define this_ssl_context my_static_cast(SSL_CTX*)(this->ssl_context_) -typedef unsigned char* ssl_data_ptr_t; - -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 int -vio_verify_callback(int ok, X509_STORE_CTX *ctx) -{ - DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx)); - char buf[256]; - X509* err_cert; - int err,depth; - - err_cert=X509_STORE_CTX_get_current_cert(ctx); - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); - - X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buff)); - if (!ok) - { - DBUG_PRINT("error",("verify error:num=%d:%s\n",err, - X509_verify_cert_error_string(err))); - if (verify_depth >= depth) - { - ok=1; - verify_error=X509_V_OK; - } - else - { - ok=0; - verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; - } - } - 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", ("r=%d", ok)); - DBUG_RETURN(ok); -} - - -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=%p, key_file=%p", - ctx, cert_file, key_file)); - if (cert_file != NULL) - { - 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)); - /* FIX stderr */ - ERR_print_errors_fp(stderr); - DBUG_RETURN(0); - } - if (key_file == NULL) - 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)); - /* FIX stderr */ - ERR_print_errors_fp(stderr); - DBUG_RETURN(0); - } - - /* 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\n")); - DBUG_RETURN(0); - } - } - DBUG_RETURN(1); -} - -/************************ VioSSLConnectorFd **********************************/ -VioSSLConnectorFd::VioSSLConnectorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path) -:ssl_context_(0),ssl_method_(0) -{ - DBUG_ENTER("VioSSLConnectorFd::VioSSLConnectorFd"); - DBUG_PRINT("enter", - ("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s", - this, key_file, cert_file, ca_path, ca_file)); - - /* FIXME: constants! */ - int verify = SSL_VERIFY_PEER; - - if (!ssl_algorithms_added) - { - DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()")); - ssl_algorithms_added = true; - SSLeay_add_ssl_algorithms(); - } - if (!ssl_error_strings_loaded) - { - DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); - ssl_error_strings_loaded = true; - SSL_load_error_strings(); - } - ssl_method_ = SSLv3_client_method(); - ssl_context_ = SSL_CTX_new(this_ssl_method); - if (ssl_context_ == 0) - { - DBUG_PRINT("error", ("SSL_CTX_new failed")); - report_errors(); - goto ctor_failure; - } - /* - * SSL_CTX_set_options - * SSL_CTX_set_info_callback - * SSL_CTX_set_cipher_list - */ - SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback); - if (vio_set_cert_stuff(this_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( this_ssl_context, ca_file,ca_path)==0) - { - DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0) - { - DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); - report_errors(); - goto ctor_failure; - } - } - DBUG_VOID_RETURN; -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - DBUG_VOID_RETURN; -} - -VioSSLConnectorFd::~VioSSLConnectorFd() -{ - DBUG_ENTER("VioSSLConnectorFd::~VioSSLConnectorFd"); - DBUG_PRINT("enter", ("this=%p", this)); - if (ssl_context_!=0) - SSL_CTX_free(this_ssl_context); - DBUG_VOID_RETURN; -} - -VioSSL* VioSSLConnectorFd::connect( int fd) -{ - DBUG_ENTER("VioSSLConnectorFd::connect"); - DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd)); - DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_connect)); -} - -VioSSL* -VioSSLConnectorFd::connect( VioSocket* sd) -{ - DBUG_ENTER("VioSSLConnectorFd::connect"); - DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description())); - DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_connect)); -} - -void -VioSSLConnectorFd::report_errors() -{ - unsigned long l; - const char* file; - const char* data; - int line,flags; - - DBUG_ENTER("VioSSLConnectorFd::report_errors"); - DBUG_PRINT("enter", ("this=%p", this)); - - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) - { - char buf[200]; - DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), - file,line,(flags&ERR_TXT_STRING)?data:"")) ; - } - DBUG_VOID_RETURN; -} - -/************************ VioSSLAcceptorFd **********************************/ - -VioSSLAcceptorFd::VioSSLAcceptorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path) - :ssl_context_(0), ssl_method_(0) -{ - DBUG_ENTER("VioSSLAcceptorFd::VioSSLAcceptorFd"); - DBUG_PRINT("enter", - ("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s", - this, key_file, cert_file, ca_path, ca_file)); - - /* FIXME: constants! */ - int verify = (SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE); - session_id_context_ = static_cast<vio_ptr>(this); - - if (!ssl_algorithms_added) - { - DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()")); - ssl_algorithms_added = true; - SSLeay_add_ssl_algorithms(); - } - if (!ssl_error_strings_loaded) - { - DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); - ssl_error_strings_loaded = true; - SSL_load_error_strings(); - } - ssl_method_ = SSLv3_server_method(); - ssl_context_ = SSL_CTX_new(this_ssl_method); - if (ssl_context_==0) - { - DBUG_PRINT("error", ("SSL_CTX_new failed")); - report_errors(); - goto ctor_failure; - } - /* - * SSL_CTX_set_quiet_shutdown(ctx,1); - * - */ - SSL_CTX_sess_set_cache_size(this_ssl_context,128); - - /* DH? - */ - SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback); - /* - * Double cast needed at least for egcs-1.1.2 to - * supress warnings: - * 1) ANSI C++ blaah implicit cast from 'void*' to 'unsigned char*' - * 2) static_cast from 'void**' to 'unsigned char*' - * Wish I had a copy of standard handy... - */ - SSL_CTX_set_session_id_context(this_ssl_context, - my_static_cast(ssl_data_ptr_t) - (my_static_cast(void*)(&session_id_context_)), - sizeof(session_id_context_)); - - /* - * SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); - */ - if (vio_set_cert_stuff(this_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( this_ssl_context, ca_file, ca_path)==0) - { - DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); - if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0) - { - DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); - report_errors(); - goto ctor_failure; - } - } - DBUG_VOID_RETURN; -ctor_failure: - DBUG_PRINT("exit", ("there was an error")); - DBUG_VOID_RETURN; -} - -VioSSLAcceptorFd::~VioSSLAcceptorFd() -{ - DBUG_ENTER("VioSSLAcceptorFd::~VioSSLAcceptorFd"); - DBUG_PRINT("enter", ("this=%p", this)); - if (ssl_context_!=0) - SSL_CTX_free(this_ssl_context); - DBUG_VOID_RETURN; -} - -VioSSL* -VioSSLAcceptorFd::accept(int fd) -{ - DBUG_ENTER("VioSSLAcceptorFd::accept"); - DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd)); - DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_accept)); -} - -VioSSL* -VioSSLAcceptorFd::accept(VioSocket* sd) -{ - DBUG_ENTER("VioSSLAcceptorFd::accept"); - DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description())); - DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_accept)); -} - -void -VioSSLAcceptorFd::report_errors() -{ - unsigned long l; - const char* file; - const char* data; - int line,flags; - - DBUG_ENTER("VioSSLConnectorFd::report_errors"); - DBUG_PRINT("enter", ("this=%p", this)); - - while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) - { - char buf[200]; - DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), - file,line,(flags&ERR_TXT_STRING)?data:"")) ; - } - DBUG_VOID_RETURN; -} - -VIO_NS_END - -#endif /* VIO_HAVE_OPENSSL */ diff --git a/vio/VioSSLFactoriesFd.h b/vio/VioSSLFactoriesFd.h deleted file mode 100644 index ed5a24f6b4a..00000000000 --- a/vio/VioSSLFactoriesFd.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Wrapper around SSL_CTX. - */ - -#ifdef VIO_HAVE_OPENSSL - -#ifdef __GNUC__ -#pragma interface /* gcc class implementation */ -#endif - -VIO_NS_BEGIN - -class VioSSLAcceptorFd : public VioAcceptorFd -{ -public: - VioSSLAcceptorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path); - - virtual ~VioSSLAcceptorFd(); - virtual VioSSL* accept(int fd); - virtual VioSSL* accept(VioSocket* sd); -private: - VioSSLAcceptorFd(const VioSSLAcceptorFd& rhs);//undefined - VioSSLAcceptorFd& operator=(const VioSSLAcceptorFd& rhs);//undefined -private: - void report_errors(); - vio_ptr ssl_; - vio_ptr ssl_context_; - vio_ptr ssl_method_; - vio_ptr session_id_context_; -}; - -VIO_NS_END - -/* - * The Factory where Vio's are made! - */ - -class VioSSLConnectorFd : public VioConnectorFd -{ -public: - VioSSLConnectorFd(const char* key_file, - const char* cert_file, - const char* ca_file, - const char* ca_path); - - virtual ~VioSSLConnectorFd(); - virtual VioSSL* connect(int fd); - virtual VioSSL* connect(VioSocket* sd); -private: - VioSSLConnectorFd(const VioSSLConnectorFd& rhs);//undefined - VioSSLConnectorFd& operator=(const VioSSLConnectorFd& rhs);//undefined -private: - void report_errors(); - vio_ptr ssl_context_; - vio_ptr ssl_method_; - vio_ptr ssl_; -}; - -VIO_NS_END - -#endif /* VIO_HAVE_OPENSSL */ diff --git a/vio/VioSocket.cc b/vio/VioSocket.cc deleted file mode 100644 index e8390edb98a..00000000000 --- a/vio/VioSocket.cc +++ /dev/null @@ -1,326 +0,0 @@ -/* Copyright Abandoned 2000 Monty Program KB - - This file is public domain and comes with NO WARRANTY of any kind */ - -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -#include "vio-global.h" -#ifdef __GNUC__ -#pragma implementation // gcc: Class implementation -#endif -#include <assert.h> - -/* - * Probably no need to clean this up - */ - -#ifdef _WIN32 -#include <winsock.h> -#endif -#include <sys/types.h> -#if !defined(__WIN32__) && !defined(MSDOS) -#include <sys/socket.h> -#endif -#if !defined(MSDOS) && !defined(__WIN32__) && !defined(HAVE_BROKEN_NETINET_INCLUDES) -#include <netinet/in_systm.h> -#include <netinet/in.h> -#include <netinet/ip.h> -#if !defined(alpha_linux_port) -#include <netinet/tcp.h> -#endif -#if defined(__EMX__) -#include <sys/ioctl.h> -#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C))) -#undef HAVE_FCNTL -#endif -#endif - -#if defined(MSDOS) || defined(__WIN32__) -#ifdef __WIN32__ -#undef errno -#undef EINTR -#undef EAGAIN -#define errno WSAGetLastError() -#define EINTR WSAEINTR -#define EAGAIN WSAEINPROGRESS -#endif -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK EAGAIN -#endif - -#ifdef __cplusplus -extern "C" { // Because of SCO 3.2V4.2 -#endif -#ifndef __WIN32__ -#include <sys/resource.h> -#ifdef HAVE_SYS_UN_H -#include <sys/un.h> -#endif -#include <netdb.h> -#include <sys/utsname.h> -#endif // __WIN32__ -#ifdef __cplusplus -} -#endif - -VIO_NS_BEGIN - -#define this_ssl_cip my_static_cast(SSL_CIPHER*)(this->ssl_cip_) - -VioSocket::VioSocket(vio_socket sd, enum_vio_type type, bool localhost) -:sd_(sd), localhost_(localhost), fcntl_(0), - fcntl_set_(FALSE), cipher_description_(0) -{ - DBUG_ENTER("VioSocket::VioSocket"); - DBUG_PRINT("enter", ("sd=%d", sd)); - if (type == VIO_TYPE_SOCKET) - sprintf(desc_,"Socket (%d)",sd_); - else - sprintf(desc_,"TCP/IP (%d)",sd_); - DBUG_VOID_RETURN; -} - -VioSocket::~VioSocket() -{ - DBUG_ENTER("VioSocket::~VioSocket"); - DBUG_PRINT("enter", ("sd_=%d", sd_)); - if (sd_>=0) - close(); - DBUG_VOID_RETURN; -} - -bool -VioSocket::is_open() const -{ - return sd_>=0; -} - -int -VioSocket::read(vio_ptr buf, int size) -{ - int r; - DBUG_ENTER("VioSocket::read"); - DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size)); - assert(sd_>=0); -#if defined(MSDOS) || defined(__WIN32__) - r = ::recv(sd_, buf, size,0); -#else - r = ::read(sd_, buf, size); -#endif -#ifndef DBUG_OFF - if ( r < 0) - { - DBUG_PRINT("error", ("Got error %d during read",errno)); - } -#endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - -int -VioSocket::write(vio_ptr buf, int size) -{ - int r; - DBUG_ENTER("VioSocket::write"); - DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size)); - assert(sd_>=0); -#if defined(__WIN32__) - r = ::send(sd_, buf, size,0); -#else - r = ::write(sd_, buf, size); -#endif /* __WIN32__ */ -#ifndef DBUG_OFF - if (r < 0) - { - DBUG_PRINT("error", ("Got error %d on write",errno)); - } -#endif /* DBUG_OFF */ - DBUG_RETURN(r); -} - -int -VioSocket::blocking(bool set_blocking_mode) -{ - int r= 0; - DBUG_ENTER("VioSocket::blocking"); - DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode)); - -#if !defined(___WIN32__) && !defined(__EMX__) -#if !defined(NO_FCNTL_NONBLOCK) - assert(sd_>=0); - - int old_fcntl=fcntl_; - if (!fcntl_set_) - { - fcntl_set_ = true; - old_fcntl= fcntl_ = fcntl(F_GETFL); - } - if (set_blocking_mode) - fcntl_&=~O_NONBLOCK; //clear bit - else - fcntl_|=O_NONBLOCK; //set bit - if (old_fcntl != fcntl_) - r = ::fcntl(sd_, F_SETFL, fcntl_); -#endif /* !defined(NO_FCNTL_NONBLOCK) */ -#else /* !defined(__WIN32__) && !defined(__EMX__) */ - { - ulong arg; - int old_fcntl=vio->fcntl_mode; - if (!vio->fcntl_set) - { - vio->fcntl_set = TRUE; - old_fnctl=vio->fcntl_mode=0; - } - if (set_blocking_mode) - { - arg = 0; - fcntl_&=~ O_NONBLOCK; //clear bit - } - else - { - arg = 1; - fcntl_|= O_NONBLOCK; //set bit - } - if (old_fcntl != fcntl_) - r = ioctlsocket(sd_,FIONBIO,(void*)&arg,sizeof(arg)); - } -#endif - DBUG_RETURN(r); -} - -bool -VioSocket::blocking() const -{ - DBUG_ENTER("VioSocket::blocking"); - bool r = !(fcntl_ & O_NONBLOCK); - DBUG_PRINT("exit", ("%d", (int)r)); - DBUG_RETURN(r); -} - -int -VioSocket::fastsend(bool onoff) -{ - int r=0; - DBUG_ENTER("VioSocket::fastsend"); - DBUG_PRINT("enter", ("onoff:%d", (int)onoff)); - assert(sd_>=0); - -#ifdef IPTOS_THROUGHPUT -#ifndef __EMX__ - int tos = IPTOS_THROUGHPUT; - if (!setsockopt(sd_, IPPROTO_IP, IP_TOS, (void*) &tos, sizeof(tos))) -#endif /* !__EMX__ */ - { - int nodelay = 1; - if (setsockopt(sd_, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, - sizeof(nodelay))) - { - DBUG_PRINT("warning", - ("Couldn't set socket option for fast send")); - r= -1; - } - } -#endif /* IPTOS_THROUGHPUT */ - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(0); -} - - -int -VioSocket::keepalive(bool set_keep_alive) -{ - DBUG_ENTER("VioSocket::keepalive"); - DBUG_PRINT("enter", ("sd_=%d, set_keep_alive=%d", sd_, - (int) set_keep_alive)); - assert(sd_>=0); - uint opt= set_keep_alive ? 1 : 0; - DBUG_RETURN(setsockopt(sd_, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt, - sizeof(opt))); -} - - -bool -VioSocket::should_retry() const -{ - int en = errno; - return en == EAGAIN || en == EINTR || en == EWOULDBLOCK; -} - -int -VioSocket::close() -{ - DBUG_ENTER("VioSocket::close"); - assert(sd_>=0); - int r=0; - if (::shutdown(sd_,2)) - r= -1; - if (::closesocket(sd_)) - r= -1; - if (r) - { - DBUG_PRINT("error", ("close() failed, error: %d",errno)); - /* FIXME: error handling (not critical for MySQL) */ - } - sd_ = -1; - DBUG_RETURN(r); -} - - -int -VioSocket::shutdown(int how) -{ - DBUG_ENTER("VioSocket::shutdown"); - DBUG_PRINT("enter", ("how=%d", how)); - assert(sd_>=0); - int r = ::shutdown(sd_, how); - DBUG_PRINT("exit", ("%d", r)); - DBUG_RETURN(r); -} - - -const char* -VioSocket::description() const -{ - return desc_; -} - - -bool -VioSocket::peer_addr(char *buf) const -{ - DBUG_ENTER("VioSocket::peer_addr"); - DBUG_PRINT("enter", ("sd_=%d", sd_)); - if (localhost_) - { - strmov(buf,"127.0.0.1"); - } - else - { - size_socket addrLen= sizeof(struct sockaddr); - if (getpeername(sd_, my_reinterpret_cast(struct sockaddr *) (&remote_), - &addrLen) != 0) - { - DBUG_PRINT("exit", ("getpeername, error: %d", errno)); - DBUG_RETURN(1); - } - my_inet_ntoa(remote_.sin_addr,buf); - } - DBUG_PRINT("exit", ("addr=%s", buf)); - DBUG_RETURN(0); -} - - -const char* -VioSocket::cipher_description() const -{ - DBUG_ENTER("VioSocket::cipher_description"); - char *r = cipher_description_ ? cipher_description_:""; - DBUG_PRINT("exit", ("name: %s", r)); - DBUG_RETURN(r); -} - -VIO_NS_END diff --git a/vio/VioSocket.h b/vio/VioSocket.h deleted file mode 100644 index e2c6eafa516..00000000000 --- a/vio/VioSocket.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -/* - * Concrete Vio around socket. Doesn't differ much from VioFd. - */ - -#ifdef WIN32 - typedef SOCKET vio_socket; -#else - typedef int vio_socket; -#endif /* WIN32 */ - -VIO_NS_BEGIN - -class VioSSL; -class VioSocket : public Vio -{ -public: - VioSocket(vio_socket sd, bool localhost=true); - virtual ~VioSocket(); - virtual bool is_open() const; - virtual int read(vio_ptr buf, int size); - virtual int write(const vio_ptr buf, int size); - virtual int blocking(bool onoff); - virtual bool blocking() const; - virtual int fastsend(bool onoff=true); - virtual int keepalive(bool onoff); - virtual bool should_retry() const; - virtual int close(); - virtual const char* description() const; - virtual bool peer_addr(char *buf) const; - virtual const char* cipher_description() const; - virtual int vio_errno(); - int shutdown(int how); - -private: - vio_socket sd_; - const bool localhost_; - int fcntl_; - bool fcntl_set_; - char desc_[30]; - mutable struct sockaddr_in local_; - mutable struct sockaddr_in remote_; - mutable char* cipher_description_; - - friend class VioSSL; // he wants to tinker with this->sd_; -}; - -VIO_NS_END - -#endif /* vio_VioSocket_h_ */ - diff --git a/vio/test-ssl.c b/vio/test-ssl.c new file mode 100644 index 00000000000..acce201bfba --- /dev/null +++ b/vio/test-ssl.c @@ -0,0 +1,148 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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> +#ifndef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ // Skip warnings in getopt.h +#endif +#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_VioSSLAcceptorFd* ssl_acceptor=0; + struct st_VioSSLConnectorFd* 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((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("fork"); + } + if (child_pid==0) { + //child, therefore, client + char xbuf[100]; + int r = client_vio->read(client_vio,xbuf, sizeof(xbuf)); + if (r<=0) { + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } + xbuf[r] = 0; + printf("client:got %s\n", xbuf); + my_free((gptr)client_vio,MYF(0)); + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + } else { + const char* s = "Huhuhuh"; + int r = server_vio->write(server_vio,(gptr)s, strlen(s)); + if (r<=0) { + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("server:SSL_write"); + } + my_free((gptr)server_vio,MYF(0)); + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + } + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/vio/test-sslclient.c b/vio/test-sslclient.c new file mode 100644 index 00000000000..84853e45485 --- /dev/null +++ b/vio/test-sslclient.c @@ -0,0 +1,105 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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> +#ifndef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ // Skip warnings in getopt.h +#endif +#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_VioSSLConnectorFd* 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 = client_vio->read(client_vio,xbuf, sizeof(xbuf)); + if (err<=0) { + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } + xbuf[err] = 0; + printf("client:got %s\n", xbuf); + my_free((gptr)client_vio,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/vio/test-sslserver.c b/vio/test-sslserver.c new file mode 100644 index 00000000000..f0116a2817d --- /dev/null +++ b/vio/test-sslserver.c @@ -0,0 +1,159 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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> +#ifndef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ // Skip warnings in getopt.h +#endif +#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_VioSSLAcceptorFd* 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,(gptr)s, strlen(s)); + sslaccept(args->ssl_acceptor,server_vio,60L); + err = server_vio->write(server_vio,(gptr)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_VioSSLAcceptorFd* ssl_acceptor; + pthread_t th; + TH_ARGS th_args; + + + struct sockaddr_in sa_serv; + struct sockaddr_in sa_cli; + int listen_sd; + int err; + size_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((gptr)ssl_acceptor,MYF(0)); + fatal_error("server:SSL_write"); + } +#endif /* 0 */ + + my_free((gptr)ssl_acceptor,MYF(0)); + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/vio/version.cc b/vio/version.cc deleted file mode 100644 index 7c09d431a9d..00000000000 --- a/vio/version.cc +++ /dev/null @@ -1,7 +0,0 @@ -#include "vio-global.h" - -extern "C" const char* -vio_version() -{ - return "0.2"; -} diff --git a/vio/vio-global.h b/vio/vio-global.h deleted file mode 100644 index 0c3d279695d..00000000000 --- a/vio/vio-global.h +++ /dev/null @@ -1,33 +0,0 @@ -#include <global.h> - -#if !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL) -#define VIO_HAVE_OPENSSL HAVE_OPENSSL -#endif /* !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL) */ - -#include "viotypes.h" -#include "Vio.h" -#include "VioAcceptorFd.h" -#include "VioFd.h" -#include "VioPipe.h" -#include "VioSocket.h" -#ifdef VIO_HAVE_OPENSSL -#include "VioSSL.h" -#include "VioSSLFactoriesFd.h" -#endif /* VIO_HAVE_OPENSSL */ - - -#if VIO_HAVE_NAMESPACES -#define VIO_STD_NS std -#define VIO_STD_NS_USING using namespace std; -#define VIO_NS VirtualIO -#define VIO_NS_BEGIN namespace VIO_NS { -#define VIO_NS_END } -#define VIO_NS_USING using namespace VIO_NS; -#else -#define VIO_STD_NS -#define VIO_STD_NS_USING -#define VIO_NS -#define VIO_NS_BEGIN -#define VIO_NS_END -#define VIO_NS_USING -#endif diff --git a/vio/vio.c b/vio/vio.c new file mode 100644 index 00000000000..bb97f195110 --- /dev/null +++ b/vio/vio.c @@ -0,0 +1,135 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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. +*/ + +#define DONT_MAP_VIO +#include <my_global.h> +#include <mysql_com.h> +#include <violite.h> +#include <errno.h> +#include <my_sys.h> +#include <my_net.h> +#include <m_string.h> + +/* + * Helper to fill most of the Vio* with defaults. + */ + +void vio_reset(Vio* vio, enum enum_vio_type type, + my_socket sd, HANDLE hPipe, + my_bool localhost) +{ + DBUG_ENTER("vio_reset"); + DBUG_PRINT("enter", ("type=%d sd=%d localhost=%d", type, sd, localhost)); + + bzero((char*) vio, sizeof(*vio)); + vio->type = type; + vio->sd = sd; + vio->hPipe = hPipe; + vio->localhost= localhost; +#ifdef HAVE_VIO +#ifdef HAVE_OPENSSL + if (type == VIO_TYPE_SSL) + { + vio->viodelete =vio_ssl_delete; + vio->vioerrno =vio_ssl_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->vioclose =vio_ssl_close; + vio->peer_addr =vio_ssl_peer_addr; + vio->in_addr =vio_ssl_in_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + } + else /* default is VIO_TYPE_TCPIP */ +#endif /* HAVE_OPENSSL */ + { + vio->viodelete =vio_delete; + vio->vioerrno =vio_errno; + vio->read =vio_read; + vio->write =vio_write; + vio->fastsend =vio_fastsend; + vio->viokeepalive =vio_keepalive; + vio->should_retry =vio_should_retry; + vio->vioclose =vio_close; + vio->peer_addr =vio_peer_addr; + vio->in_addr =vio_in_addr; + vio->vioblocking =vio_blocking; + vio->is_blocking =vio_is_blocking; + } +#endif /* HAVE_VIO */ + DBUG_VOID_RETURN; +} + + +/* Open the socket or TCP/IP connection and read the fnctl() status */ + +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(___WIN__) && !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); + vio->fcntl_mode &= ~O_NONBLOCK; +#endif +#else /* !defined(__WIN__) && !defined(__EMX__) */ + { + /* set to blocking mode by default */ + ulong arg=0, r; + r = ioctlsocket(sd,FIONBIO,(void*) &arg, sizeof(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_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE); + strmov(vio->desc, "named pipe"); + } + DBUG_RETURN(vio); +} + +#endif diff --git a/vio/vioelitexx.cc b/vio/vioelitexx.cc deleted file mode 100644 index 0eac28eaf55..00000000000 --- a/vio/vioelitexx.cc +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright Abandoned 2000 Monty Program KB - This file is public domain and comes with NO WARRANTY of any kind */ - -/* - * Renamed of violite.cc to violitexx.cc because of clashes - * with violite.c - * This file implements the same functions as in violite.c, but now using - * the Vio class - */ - -#include "vio-global.h" - -Vio* -vio_new(my_socket sd, enum_vio_type type, my_bool localhost) -{ - return my_reinterpret_cast(Vio*) (new VioSocket(sd, type, localhost)); -} - - -#ifdef __WIN32__ -Vio -*vio_new_win32pipe(HANDLE hPipe) -{ - return my_reinterpret_cast(Vio*) (new VioPipe(hPipe)); -} -#endif diff --git a/vio/violite.h b/vio/violite.h deleted file mode 100644 index fc480f59db1..00000000000 --- a/vio/violite.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright Abandoned 2000 Monty Program KB - This file is public domain and comes with NO WARRANTY of any kind */ - -/* - * Vio Lite. - * Purpose: include file for Vio that will work with C and C++ - */ - -#ifndef vio_violite_h_ -#define vio_violite_h_ - -#include "my_net.h" /* needed because of struct in_addr */ - -#ifdef HAVE_VIO -#include <Vio.h> /* Full VIO interface */ -#else - -/* Simple vio interface in C; The functions are implemented in violite.c */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef Vio_defined -#define Vio_defined -struct st_vio; /* Only C */ -typedef struct st_vio Vio; -#endif - -enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, - VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL}; - -Vio* vio_new(my_socket sd, - enum enum_vio_type type, - my_bool localhost); -#ifdef __WIN__ -Vio* vio_new_win32pipe(HANDLE hPipe); -#endif -void vio_delete(Vio* vio); - -/* - * vio_read and vio_write should have the same semantics - * as read(2) and write(2). - */ -int vio_read( Vio* vio, - gptr buf, int size); -int vio_write( Vio* vio, - const gptr buf, - int size); -/* - * Whenever the socket is set to blocking mode or not. - */ -int vio_blocking( Vio* vio, - my_bool onoff); -my_bool vio_is_blocking( Vio* vio); -/* - * setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. - */ -int vio_fastsend( Vio* vio, - my_bool onoff); -/* - * setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. - */ -int vio_keepalive( Vio* vio, - my_bool onoff); -/* - * Whenever we should retry the last read/write operation. - */ -my_bool vio_should_retry( Vio* vio); -/* - * When the workday is over... - */ -int vio_close( Vio* vio); -/* - * Short text description of the socket for those, who are curious.. - */ -const char* vio_description( Vio* vio); - -/* Return the type of the connection */ - enum enum_vio_type vio_type(Vio* vio); - -/* Return last error number */ -int vio_errno(Vio *vio); - -/* Get socket number */ -my_socket vio_fd(Vio *vio); - -/* - * Remote peer's address and name in text form. - */ -my_bool vio_peer_addr(Vio * vio, char *buf); - -/* Remotes in_addr */ - -void vio_in_addr(Vio *vio, struct in_addr *in); - -#ifdef __cplusplus -} -#endif -#endif /* HAVE_VIO */ -#endif /* vio_violite_h_ */ diff --git a/vio/viosocket.c b/vio/viosocket.c new file mode 100644 index 00000000000..176af25b395 --- /dev/null +++ b/vio/viosocket.c @@ -0,0 +1,331 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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. +*/ + +#define DONT_MAP_VIO +#include <my_global.h> +#include <mysql_com.h> + +#include <errno.h> +#include <violite.h> +#include <my_sys.h> +#include <my_net.h> +#include <m_string.h> + +#ifndef __WIN__ +#define HANDLE void * +#endif + +void vio_delete(Vio* vio) +{ + /* It must be safe to delete null pointers. */ + /* This matches the semantics of C++'s delete operator. */ + if (vio) + { + if (vio->type != VIO_CLOSED) + vio_close(vio); + my_free((gptr) vio,MYF(0)); + } +} + +int vio_errno(Vio *vio __attribute__((unused))) +{ + return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ +} + + +int vio_read(Vio * vio, gptr buf, int size) +{ + int r; + DBUG_ENTER("vio_read"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); +#ifdef __WIN__ + if (vio->type == VIO_TYPE_NAMEDPIPE) + { + DWORD length; + if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) + DBUG_RETURN(-1); + DBUG_RETURN(length); + } + 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 < 0) + { + DBUG_PRINT("vio_error", ("Got error %d during read",errno)); + } +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + + +int vio_write(Vio * vio, const gptr buf, int size) +{ + int r; + DBUG_ENTER("vio_write"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); +#if defined( __WIN__) + if ( vio->type == VIO_TYPE_NAMEDPIPE) + { + DWORD length; + if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) + DBUG_RETURN(-1); + DBUG_RETURN(length); + } + r = send(vio->sd, buf, size, 0); +#else + r = write(vio->sd, buf, size); +#endif /* __WIN__ */ +#ifndef DBUG_OFF + if (r < 0) + { + DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); + } +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%d", 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(HAVE_OPENSSL) +#if !defined(___WIN__) && !defined(__EMX__) +#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); + } +#endif /* !defined(NO_FCNTL_NONBLOCK) */ +#else /* !defined(__WIN__) && !defined(__EMX__) */ +#ifndef __EMX__ + if (vio->type != VIO_TYPE_NAMEDPIPE) +#endif + { + 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, sizeof(arg)); + } +#endif /* !defined(__WIN__) && !defined(__EMX__) */ +#endif /* !defined (HAVE_OPENSSL) */ + 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"); + +#ifdef IPTOS_THROUGHPUT + { +#ifndef __EMX__ + int tos = IPTOS_THROUGHPUT; + if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos))) +#endif /* !__EMX__ */ + { + int nodelay = 1; + if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, + sizeof(nodelay))) { + DBUG_PRINT("warning", + ("Couldn't set socket option for fast send")); + r= -1; + } + } + } +#endif /* IPTOS_THROUGHPUT */ + 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); +} + + +int vio_close(Vio * vio) +{ + int r; + DBUG_ENTER("vio_close"); +#ifdef __WIN__ + if (vio->type == VIO_TYPE_NAMEDPIPE) + { +#if defined(__NT__) && defined(MYSQL_SERVER) + CancelIo(vio->hPipe); + DisconnectNamedPipe(vio->hPipe); +#endif + r=CloseHandle(vio->hPipe); + } + else if (vio->type != VIO_CLOSED) +#endif /* __WIN__ */ + { + r=0; + if (shutdown(vio->sd,2)) + 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) +{ + DBUG_ENTER("vio_peer_addr"); + DBUG_PRINT("enter", ("sd: %d", vio->sd)); + if (vio->localhost) + { + strmov(buf,"127.0.0.1"); + } + else + { + size_socket addrLen = sizeof(struct sockaddr); + if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), + &addrLen) != 0) + { + DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); + DBUG_RETURN(1); + } + my_inet_ntoa(vio->remote.sin_addr,buf); + } + DBUG_PRINT("exit", ("addr: %s", buf)); + DBUG_RETURN(0); +} + + +void vio_in_addr(Vio *vio, struct in_addr *in) +{ + DBUG_ENTER("vio_in_addr"); + if (vio->localhost) + bzero((char*) in, sizeof(*in)); /* This should never be executed */ + else + *in=vio->remote.sin_addr; + DBUG_VOID_RETURN; +} + + +/* Return 0 if there is data to be read */ + +my_bool vio_poll_read(Vio *vio,uint timeout) +{ +#ifndef HAVE_POLL + return 0; +#else + 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 ? 0 : 1); +#endif +} diff --git a/vio/viossl.c b/vio/viossl.c new file mode 100644 index 00000000000..7365bdc3daf --- /dev/null +++ b/vio/viossl.c @@ -0,0 +1,365 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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 <my_global.h> + +#ifdef HAVE_OPENSSL + +#include <mysql_com.h> + +#include <errno.h> +#include <assert.h> +#include <violite.h> +#include <my_sys.h> +#include <my_net.h> +#include <m_string.h> + +#ifndef __WIN__ +#define HANDLE void * +#endif + +static void +report_errors() +{ + unsigned long l; + const char* file; + const char* data; + int line,flags, any_ssl_error = 0; + DBUG_ENTER("report_errors"); + + while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) + { + char buf[200]; + any_ssl_error = 1; + DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), + file,line,(flags&ERR_TXT_STRING)?data:"")) ; + } + if (!any_ssl_error) { + DBUG_PRINT("info", ("No OpenSSL errors.")); + } + DBUG_PRINT("info", ("BTW, errno=%d", socket_errno)); + DBUG_VOID_RETURN; +} + + +void vio_ssl_delete(Vio * vio) +{ + /* It must be safe to delete null pointers. */ + /* This matches the semantics of C++'s delete operator. */ + if (vio) + { + if (vio->type != VIO_CLOSED) + vio_close(vio); + my_free((gptr) vio,MYF(0)); + } +} + +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; + DBUG_ENTER("vio_ssl_read"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d, ssl_=%p", + vio->sd, buf, size, vio->ssl_)); + +#ifndef DBUG_OFF + errno = 0; +#endif /* DBUG_OFF */ + r = SSL_read(vio->ssl_, buf, size); +#ifndef DBUG_OFF + if ( r<= 0) { + r=SSL_get_error(vio->ssl_, r); + DBUG_PRINT("info",("SSL_get_error returned %d",r)); + report_errors(); + } +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + + +int vio_ssl_write(Vio * vio, const gptr buf, int size) +{ + int r; + DBUG_ENTER("vio_ssl_write"); + DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size)); + +#ifndef DBUG_OFF + errno = 0; +#endif /* DBUG_OFF */ + r = SSL_write(vio->ssl_, buf, size); +#ifndef DBUG_OFF + if (r<0) + report_errors(); +#endif /* DBUG_OFF */ + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + + +int vio_ssl_fastsend(Vio * vio __attribute__((unused))) +{ + int r=0; + DBUG_ENTER("vio_ssl_fastsend"); + +#ifdef IPTOS_THROUGHPUT + { +#ifndef __EMX__ + int tos = IPTOS_THROUGHPUT; + if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos))) +#endif /* !__EMX__ */ + { + int nodelay = 1; + if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, + sizeof(nodelay))) { + DBUG_PRINT("warning", + ("Couldn't set socket option for fast send")); + r= -1; + } + } + } +#endif /* IPTOS_THROUGHPUT */ + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + +int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive) +{ + int r=0; + uint opt = 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) + { + if (set_keep_alive) + opt = 1; + 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); +} + + +int vio_ssl_close(Vio * vio) +{ + int r; + DBUG_ENTER("vio_ssl_close"); + r=0; + if (vio->ssl_) + { + r = SSL_shutdown(vio->ssl_); + SSL_free(vio->ssl_); + vio->ssl_= 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) +{ + DBUG_ENTER("vio_ssl_peer_addr"); + DBUG_PRINT("enter", ("sd=%d", vio->sd)); + if (vio->localhost) + { + strmov(buf,"127.0.0.1"); + } + else + { + size_socket addrLen = sizeof(struct sockaddr); + if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)), + &addrLen) != 0) + { + DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno)); + DBUG_RETURN(1); + } + /* FIXME */ +/* my_inet_ntoa(vio->remote.sin_addr,buf); */ + } + 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)); /* This should never be executed */ + else + *in=vio->remote.sin_addr; + DBUG_VOID_RETURN; +} + + +void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) +{ + char *str; + char buf[1024]; + X509* client_cert; + my_bool unused; + DBUG_ENTER("sslaccept"); + DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr)); + + vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); + vio->ssl_=0; + vio->open_=FALSE; + if (!(vio->ssl_ = SSL_new(ptr->ssl_context_))) + { + DBUG_PRINT("error", ("SSL_new failure")); + report_errors(); + DBUG_VOID_RETURN; + } + DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout)); + SSL_clear(vio->ssl_); + vio_blocking(vio, FALSE, &unused); + SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); + SSL_set_fd(vio->ssl_,vio->sd); + SSL_set_accept_state(vio->ssl_); + SSL_do_handshake(vio->ssl_); + vio->open_ = TRUE; +#ifndef DBUF_OFF + DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" + ,SSL_get_cipher_name(vio->ssl_))); + client_cert = SSL_get_peer_certificate (vio->ssl_); + 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); + + str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); + DBUG_PRINT("info",("\t issuer: %s", str)); + free (str); + + X509_free (client_cert); + } else + DBUG_PRINT("info",("Client does not have certificate.")); + + str=SSL_get_shared_ciphers(vio->ssl_, buf, sizeof(buf)); + if(str) + { + DBUG_PRINT("info",("SSL_get_shared_ciphers() returned '%s'",str)); + } + else + { + DBUG_PRINT("info",("no shared ciphers!")); + } + +#endif + DBUG_VOID_RETURN; +} + + +void sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout) +{ + char *str; + X509* server_cert; + my_bool unused; + DBUG_ENTER("sslconnect"); + DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context_)); + + vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE); + vio->ssl_=0; + vio->open_=FALSE; + if (!(vio->ssl_ = SSL_new(ptr->ssl_context_))) + { + DBUG_PRINT("error", ("SSL_new failure")); + report_errors(); + DBUG_VOID_RETURN; + } + DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout)); + SSL_clear(vio->ssl_); + vio_blocking(vio, FALSE, &unused); + SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout); + SSL_set_fd (vio->ssl_, vio->sd); + SSL_set_connect_state(vio->ssl_); + SSL_do_handshake(vio->ssl_); + vio->open_ = TRUE; +#ifndef DBUG_OFF + DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" + ,SSL_get_cipher_name(vio->ssl_))); + server_cert = SSL_get_peer_certificate (vio->ssl_); + if (server_cert != NULL) { + 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_free (server_cert); + } else + DBUG_PRINT("info",("Server does not have certificate.")); +#endif + DBUG_VOID_RETURN; +} + +#endif /* HAVE_OPENSSL */ diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c new file mode 100644 index 00000000000..23a35f540f6 --- /dev/null +++ b/vio/viosslfactories.c @@ -0,0 +1,352 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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 <mysql_com.h> +#include <violite.h> + + +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[]= +{ + 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) + { + char buf[200]; + DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf), + file,line,(flags & ERR_TXT_STRING) ? data : "")) ; + } + 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 != NULL) + { + 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)); + /* FIX stderr */ + ERR_print_errors_fp(stderr); + DBUG_RETURN(0); + } + if (key_file == NULL) + 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)); + /* FIX stderr */ + ERR_print_errors_fp(stderr); + DBUG_RETURN(0); + } + + /* + 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\n")); + DBUG_RETURN(0); + } + } + DBUG_RETURN(1); +} + + +static int +vio_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + char buf[256]; + X509* err_cert; + int err,depth; + + DBUG_ENTER("vio_verify_callback"); + DBUG_PRINT("enter", ("ok=%d, ctx=%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); + + X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf)); + if (!ok) + { + DBUG_PRINT("error",("verify error: num: %d : '%s'\n",err, + X509_verify_cert_error_string(err))); + if (verify_depth >= depth) + { + ok=1; + verify_error=X509_V_OK; + } + else + { + verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; + } + } + 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); +} + + +/************************ VioSSLConnectorFd **********************************/ +struct st_VioSSLConnectorFd * +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; + struct st_VioSSLConnectorFd* ptr; + int result; + DH *dh=NULL; + DBUG_ENTER("new_VioSSLConnectorFd"); + DBUG_PRINT("enter", + ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s", + key_file, cert_file, ca_path, ca_file, cipher)); + + 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; + OpenSSL_add_all_algorithms(); + } + 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_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) + { + DBUG_PRINT("error", ("SSL_CTX_new failed")); + report_errors(); + goto ctor_failure; + } + /* + SSL_CTX_set_options + SSL_CTX_set_info_callback + */ + if (cipher) + { + result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher); + DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + } + SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback); + 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); +ctor_failure: + DBUG_PRINT("exit", ("there was an error")); + my_free((gptr)ptr,MYF(0)); + DBUG_RETURN(0); +} + + +/************************ VioSSLAcceptorFd **********************************/ + +struct st_VioSSLAcceptorFd* +new_VioSSLAcceptorFd(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_FAIL_IF_NO_PEER_CERT | + SSL_VERIFY_CLIENT_ONCE); + struct st_VioSSLAcceptorFd* ptr; + int result; + DH *dh=NULL; + DBUG_ENTER("new_VioSSLAcceptorFd"); + DBUG_PRINT("enter", + ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s", + key_file, cert_file, ca_path, ca_file, cipher)); + + 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; + + if (!ssl_algorithms_added) + { + DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); + ssl_algorithms_added = TRUE; + OpenSSL_add_all_algorithms(); + + } + 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) + { + result=SSL_CTX_set_cipher_list(ptr->ssl_context_, cipher); + DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result)); + } + /* SSL_CTX_set_quiet_shutdown(ctx,1); */ + SSL_CTX_sess_set_cache_size(ptr->ssl_context_,128); + + /* 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_)); + + /* + SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); + */ + 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); + +ctor_failure: + DBUG_PRINT("exit", ("there was an error")); + my_free((gptr) ptr,MYF(0)); + DBUG_RETURN(0); +} + + +#endif /* HAVE_OPENSSL */ diff --git a/vio/viotest-ssl.c b/vio/viotest-ssl.c new file mode 100644 index 00000000000..1a766a3fc97 --- /dev/null +++ b/vio/viotest-ssl.c @@ -0,0 +1,156 @@ +/* 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; either version 2 of the License, or + (at your option) any later version. + + 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> +#ifndef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ // Skip warnings in getopt.h +#endif +#include <my_getopt.h> +//#include "my_readline.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_ENTER("main"); + 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((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)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((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("client:SSL_read"); + } +// printf("*** client cipher %s\n",client_vio->cipher_description()); + xbuf[r] = 0; + printf("client:got %s\n", xbuf); + my_free((gptr)client_vio,MYF(0)); + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + sleep(1); + } else { + const char* s = "Huhuhuh"; + int r = vio_ssl_write(server_vio,(gptr)s, strlen(s)); + if (r<=0) { + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + fatal_error("server:SSL_write"); + } +// printf("*** server cipher %s\n",server_vio->cipher_description()); + my_free((gptr)server_vio,MYF(0)); + my_free((gptr)ssl_acceptor,MYF(0)); + my_free((gptr)ssl_connector,MYF(0)); + sleep(1); + } + return 0; +} +#else /* HAVE_OPENSSL */ + +int main() { +return 0; +} +#endif /* HAVE_OPENSSL */ diff --git a/vio/viotest-ssl.cc b/vio/viotest-ssl.cc deleted file mode 100644 index a3ad92a7c9c..00000000000 --- a/vio/viotest-ssl.cc +++ /dev/null @@ -1,104 +0,0 @@ -#include "all.h" - -#include <sys/types.h> -#include <sys/socket.h> -#include <stdio.h> -#include <unistd.h> - - -void -fatal_error( const char* r) -{ - perror(r); - exit(0); -} - -void -print_usage() -{ - printf("viossltest: testing SSL virtual IO. Usage:\n"); - printf("viossltest 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 sv[2]; - - if (argc<5) - { - print_usage(); - return 1; - } - - if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1) - fatal_error("socketpair"); - - 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); - - VIO_NS::VioSSLAcceptorFd* ssl_acceptor = new VIO_NS::VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path); - VIO_NS::VioSSLConnectorFd* ssl_connector = new VIO_NS::VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path); - - printf("Socketpair: %d , %d\n", sv[0], sv[1]); - - VIO_NS::VioSSL* client_vio = ssl_connector->connect(sv[0]); - VIO_NS::VioSSL* server_vio = ssl_acceptor->accept(sv[1]); - - - int child_pid = fork(); - if (child_pid==-1) { - delete ssl_acceptor; - delete ssl_connector; - fatal_error("fork"); - } - if (child_pid==0) { - //child, therefore, client - char xbuf[100]; - int r = client_vio->read(xbuf, sizeof(xbuf)); - if (r<=0) { - delete ssl_acceptor; - delete ssl_connector; - fatal_error("client:SSL_read"); - } - printf("*** client cipher %s\n",client_vio->cipher_description()); - xbuf[r] = 0; - printf("client:got %s\n", xbuf); - delete client_vio; - delete ssl_acceptor; - delete ssl_connector; - sleep(1); - } else { - const char* s = "Huhuhuh"; - int r = server_vio->write((void *)s, strlen(s)); - if (r<=0) { - delete ssl_acceptor; - delete ssl_connector; - fatal_error("server:SSL_write"); - } - printf("*** server cipher %s\n",server_vio->cipher_description()); - delete server_vio; - delete ssl_acceptor; - delete ssl_connector; - sleep(1); - } -} diff --git a/vio/viotypes.h b/vio/viotypes.h deleted file mode 100644 index 8d36a35c86f..00000000000 --- a/vio/viotypes.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Virtual I/O library -** Written by Andrei Errapart <andreie@no.spam.ee> -*/ - -/* - * Some typedefs to external types. - */ -#ifndef vio_viotypes_h_ -#define vio_viotypes_h_ - -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> - -typedef int vio_bool_t; -typedef void* vio_ptr_t; - -#ifdef __cplusplus -VIO_NS_BEGIN - -typedef vio_ptr_t vio_ptr; -typedef char* vio_cstring; -typedef int32_t vio_int32; -typedef u_int32_t vio_uint32; -typedef vio_bool_t vio_bool; - -VIO_NS_END -#endif /* __cplusplus */ - -#endif /* vio_types_h_ */ - |