X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fcore%2Fnetwork-openssl.c;fp=apps%2Firssi%2Fsrc%2Fcore%2Fnetwork-openssl.c;h=0000000000000000000000000000000000000000;hb=f9d9c92fcc179ff82ae7aa5f724440215f194827;hp=68fb8ea82776b837f4b00c618a06ea5963104b1e;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=crypto.git diff --git a/apps/irssi/src/core/network-openssl.c b/apps/irssi/src/core/network-openssl.c deleted file mode 100644 index 68fb8ea8..00000000 --- a/apps/irssi/src/core/network-openssl.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - network-ssl.c : SSL support - - Copyright (C) 2002 vjt - - 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 "module.h" -#include "network.h" -#include "misc.h" - -#ifdef HAVE_OPENSSL - -#include -#include -#include -#include -#include - -/* ssl i/o channel object */ -typedef struct -{ - GIOChannel pad; - gint fd; - GIOChannel *giochan; - SSL *ssl; - SSL_CTX *ctx; - unsigned int got_cert:1; - unsigned int verify:1; -} GIOSSLChannel; - -static SSL_CTX *ssl_ctx = NULL; - -static void irssi_ssl_free(GIOChannel *handle) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - g_io_channel_unref(chan->giochan); - SSL_free(chan->ssl); - if (chan->ctx != ssl_ctx) - SSL_CTX_free(chan->ctx); - g_free(chan); -} - -static gboolean irssi_ssl_verify(SSL *ssl, SSL_CTX *ctx, X509 *cert) -{ - if (SSL_get_verify_result(ssl) != X509_V_OK) { - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int n; - char *str; - - g_warning("Could not verify SSL servers certificate:"); - if ((str = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)) == NULL) - g_warning(" Could not get subject-name from peer certificate"); - else { - g_warning(" Subject : %s", str); - free(str); - } - if ((str = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0)) == NULL) - g_warning(" Could not get issuer-name from peer certificate"); - else { - g_warning(" Issuer : %s", str); - free(str); - } - if (! X509_digest(cert, EVP_md5(), md, &n)) - g_warning(" Could not get fingerprint from peer certificate"); - else { - char hex[] = "0123456789ABCDEF"; - char fp[EVP_MAX_MD_SIZE*3]; - if (n < sizeof(fp)) { - unsigned int i; - for (i = 0; i < n; i++) { - fp[i*3+0] = hex[(md[i] >> 4) & 0xF]; - fp[i*3+1] = hex[(md[i] >> 0) & 0xF]; - fp[i*3+2] = i == n - 1 ? '\0' : ':'; - } - g_warning(" MD5 Fingerprint : %s", fp); - } - } - return FALSE; - } - return TRUE; -} - - -#if GLIB_MAJOR_VERSION < 2 - -static GIOError ssl_errno(gint e) -{ - switch(e) - { - case EINVAL: - return G_IO_ERROR_INVAL; - case EINTR: - case EAGAIN: - return G_IO_ERROR_AGAIN; - default: - return G_IO_ERROR_INVAL; - } - /*UNREACH*/ - return G_IO_ERROR_INVAL; -} - -static GIOError irssi_ssl_cert_step(GIOSSLChannel *chan) -{ - X509 *cert; - gint err; - switch(err = SSL_do_handshake(chan->ssl)) - { - case 1: - if(!(cert = SSL_get_peer_certificate(chan->ssl))) - { - g_warning("SSL server supplied no certificate"); - return G_IO_ERROR_INVAL; - } - if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) { - X509_free(cert); - return G_IO_ERROR_INVAL; - } - X509_free(cert); - return G_IO_ERROR_NONE; - default: - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_ERROR_AGAIN; - return ssl_errno(errno); - } - /*UNREACH*/ - return G_IO_ERROR_INVAL; -} - -static GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; - - if(! chan->got_cert) - { - gint cert_err = irssi_ssl_cert_step(chan); - if(cert_err != G_IO_ERROR_NONE) - return cert_err; - } - - err = SSL_read(chan->ssl, buf, len); - if(err < 0) - { - *ret = 0; - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_ERROR_AGAIN; - return ssl_errno(errno); - } - else - { - *ret = err; - return G_IO_ERROR_NONE; - } - /*UNREACH*/ - return -1; -} - -static GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint *ret) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; - - if(chan->got_cert) - { - gint cert_err = irssi_ssl_cert_step(chan); - if(cert_err != G_IO_ERROR_NONE) - return cert_err; - } - - - err = SSL_write(chan->ssl, (const char *)buf, len); - if(err < 0) - { - *ret = 0; - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_ERROR_AGAIN; - return ssl_errno(errno); - } - else - { - *ret = err; - return G_IO_ERROR_NONE; - } - /*UNREACH*/ - return G_IO_ERROR_INVAL; -} - -static GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - GIOError e; - e = g_io_channel_seek(chan->giochan, offset, type); - return (e == G_IO_ERROR_NONE) ? G_IO_ERROR_NONE : G_IO_ERROR_INVAL; -} - -static void irssi_ssl_close(GIOChannel *handle) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - g_io_channel_close(chan->giochan); -} - -static guint irssi_ssl_create_watch(GIOChannel *handle, gint priority, GIOCondition cond, - GIOFunc func, gpointer data, GDestroyNotify notify) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - - return chan->giochan->funcs->io_add_watch(handle, priority, cond, func, data, notify); -} - -/* ssl function pointers */ -static GIOFuncs irssi_ssl_channel_funcs = -{ - irssi_ssl_read, - irssi_ssl_write, - irssi_ssl_seek, - irssi_ssl_close, - irssi_ssl_create_watch, - irssi_ssl_free -}; - -#else /* GLIB_MAJOR_VERSION < 2 */ - -static GIOStatus ssl_errno(gint e) -{ - switch(e) - { - case EINVAL: - return G_IO_STATUS_ERROR; - case EINTR: - case EAGAIN: - return G_IO_STATUS_AGAIN; - default: - return G_IO_STATUS_ERROR; - } - /*UNREACH*/ - return G_IO_STATUS_ERROR; -} - -static GIOStatus irssi_ssl_cert_step(GIOSSLChannel *chan) -{ - X509 *cert; - gint err; - switch(err = SSL_do_handshake(chan->ssl)) - { - case 1: - if(!(cert = SSL_get_peer_certificate(chan->ssl))) - { - g_warning("SSL server supplied no certificate"); - return G_IO_STATUS_ERROR; - } - if (chan->verify && ! irssi_ssl_verify(chan->ssl, chan->ctx, cert)) { - X509_free(cert); - return G_IO_STATUS_ERROR; - } - X509_free(cert); - return G_IO_STATUS_NORMAL; - default: - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_STATUS_AGAIN; - return ssl_errno(errno); - } - /*UNREACH*/ - return G_IO_STATUS_ERROR; -} - -static GIOStatus irssi_ssl_read(GIOChannel *handle, gchar *buf, gsize len, gsize *ret, GError **gerr) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; - - if(! chan->got_cert) - { - gint cert_err = irssi_ssl_cert_step(chan); - if(cert_err != G_IO_STATUS_NORMAL) - return cert_err; - } - - err = SSL_read(chan->ssl, buf, len); - if(err < 0) - { - *ret = 0; - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_STATUS_AGAIN; - return ssl_errno(errno); - } - else - { - *ret = err; - return G_IO_STATUS_NORMAL; - } - /*UNREACH*/ - return G_IO_STATUS_ERROR; -} - -static GIOStatus irssi_ssl_write(GIOChannel *handle, const gchar *buf, gsize len, gsize *ret, GError **gerr) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - gint err; - - if(! chan->got_cert) - { - gint cert_err = irssi_ssl_cert_step(chan); - if(cert_err != G_IO_STATUS_NORMAL) - return cert_err; - } - - err = SSL_write(chan->ssl, (const char *)buf, len); - if(err < 0) - { - *ret = 0; - if(SSL_get_error(chan->ssl, err) == SSL_ERROR_WANT_READ) - return G_IO_STATUS_AGAIN; - return ssl_errno(errno); - } - else - { - *ret = err; - return G_IO_STATUS_NORMAL; - } - /*UNREACH*/ - return G_IO_STATUS_ERROR; -} - -static GIOStatus irssi_ssl_seek(GIOChannel *handle, gint64 offset, GSeekType type, GError **gerr) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - GIOError e; - e = g_io_channel_seek(chan->giochan, offset, type); - return (e == G_IO_ERROR_NONE) ? G_IO_STATUS_NORMAL : G_IO_STATUS_ERROR; -} - -static GIOStatus irssi_ssl_close(GIOChannel *handle, GError **gerr) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - g_io_channel_close(chan->giochan); - - return G_IO_STATUS_NORMAL; -} - -static GSource *irssi_ssl_create_watch(GIOChannel *handle, GIOCondition cond) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - - return chan->giochan->funcs->io_create_watch(handle, cond); -} - -static GIOStatus irssi_ssl_set_flags(GIOChannel *handle, GIOFlags flags, GError **gerr) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - - return chan->giochan->funcs->io_set_flags(handle, flags, gerr); -} - -static GIOFlags irssi_ssl_get_flags(GIOChannel *handle) -{ - GIOSSLChannel *chan = (GIOSSLChannel *)handle; - - return chan->giochan->funcs->io_get_flags(handle); -} - -static GIOFuncs irssi_ssl_channel_funcs = { - irssi_ssl_read, - irssi_ssl_write, - irssi_ssl_seek, - irssi_ssl_close, - irssi_ssl_create_watch, - irssi_ssl_free, - irssi_ssl_set_flags, - irssi_ssl_get_flags -}; - -#endif - -static gboolean irssi_ssl_init(void) -{ - SSL_library_init(); - SSL_load_error_strings(); - - ssl_ctx = SSL_CTX_new(SSLv23_client_method()); - if(!ssl_ctx) - { - g_error("Initialization of the SSL library failed"); - return FALSE; - } - - return TRUE; - -} - -static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, const char *mycert, const char *mypkey, const char *cafile, const char *capath, gboolean verify) -{ - GIOSSLChannel *chan; - GIOChannel *gchan; - int err, fd; - SSL *ssl; - X509 *cert = NULL; - SSL_CTX *ctx = NULL; - - g_return_val_if_fail(handle != NULL, NULL); - - if(!ssl_ctx && !irssi_ssl_init()) - return NULL; - - if(!(fd = g_io_channel_unix_get_fd(handle))) - return NULL; - - if (mycert && *mycert) { - char *scert = NULL, *spkey = NULL; - if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { - g_error("Could not allocate memory for SSL context"); - return NULL; - } - scert = convert_home(mycert); - if (mypkey && *mypkey) - spkey = convert_home(mypkey); - if (! SSL_CTX_use_certificate_file(ctx, scert, SSL_FILETYPE_PEM)) - g_warning("Loading of client certificate '%s' failed", mycert); - else if (! SSL_CTX_use_PrivateKey_file(ctx, spkey ? spkey : scert, SSL_FILETYPE_PEM)) - g_warning("Loading of private key '%s' failed", mypkey ? mypkey : mycert); - else if (! SSL_CTX_check_private_key(ctx)) - g_warning("Private key does not match the certificate"); - g_free(scert); - g_free(spkey); - } - - if ((cafile && *cafile) || (capath && *capath)) { - char *scafile = NULL; - char *scapath = NULL; - if (! ctx && (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { - g_error("Could not allocate memory for SSL context"); - return NULL; - } - if (cafile && *cafile) - scafile = convert_home(cafile); - if (capath && *capath) - scapath = convert_home(capath); - if (! SSL_CTX_load_verify_locations(ctx, scafile, scapath)) { - g_warning("Could not load CA list for verifying SSL server certificate"); - g_free(scafile); - g_free(scapath); - SSL_CTX_free(ctx); - return NULL; - } - g_free(scafile); - g_free(scapath); - verify = TRUE; - } - - if (ctx == NULL) - ctx = ssl_ctx; - - if(!(ssl = SSL_new(ctx))) - { - g_warning("Failed to allocate SSL structure"); - return NULL; - } - - if(!(err = SSL_set_fd(ssl, fd))) - { - g_warning("Failed to associate socket to SSL stream"); - SSL_free(ssl); - if (ctx != ssl_ctx) - SSL_CTX_free(ctx); - return NULL; - } - - if((err = SSL_connect(ssl)) <= 0) - { - switch(err = SSL_get_error(ssl, err)) - { - case SSL_ERROR_SYSCALL: - if(errno == EINTR || errno == EAGAIN) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - break; - default: - SSL_free(ssl); - if (ctx != ssl_ctx) - SSL_CTX_free(ctx); - return NULL; - } - } - else if(!(cert = SSL_get_peer_certificate(ssl))) - { - g_warning("SSL server supplied no certificate"); - if (ctx != ssl_ctx) - SSL_CTX_free(ctx); - SSL_free(ssl); - return NULL; - } - else - { - if (verify && ! irssi_ssl_verify(ssl, ctx, cert)) { - SSL_free(ssl); - if (ctx != ssl_ctx) - SSL_CTX_free(ctx); - return NULL; - } - X509_free(cert); - } - - chan = g_new0(GIOSSLChannel, 1); - chan->fd = fd; - chan->giochan = handle; - chan->ssl = ssl; - chan->ctx = ctx; - chan->got_cert = cert != NULL; - chan->verify = verify; - - gchan = (GIOChannel *)chan; - gchan->funcs = &irssi_ssl_channel_funcs; - g_io_channel_init(gchan); - - return gchan; -} - -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) -{ - GIOChannel *handle, *ssl_handle; - - handle = net_connect_ip(ip, port, my_ip); - ssl_handle = irssi_ssl_get_iochannel(handle, cert, pkey, cafile, capath, verify); - if (ssl_handle == NULL) - g_io_channel_unref(handle); - return ssl_handle; -} - -#else /* HAVE_OPENSSL */ - -GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, const char *cert, const char *pkey, const char *cafile, const char *capath, gboolean verify) -{ - g_warning("Connection failed: SSL support not enabled in this build."); - errno = ENOSYS; - return NULL; -} - -#endif /* ! HAVE_OPENSSL */