forked from PsychoticNinja/irssi
GLIB2 support for SSL code. Patch by vjt@users.sf.net
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2973 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
f42df98fc8
commit
9f089f360d
@ -428,11 +428,6 @@ if test "x$enable_ssl" = xyes; then
|
|||||||
])
|
])
|
||||||
CFLAGS=$save_CFLAGS
|
CFLAGS=$save_CFLAGS
|
||||||
|
|
||||||
if test "x`echo $GLIB_LIBS|grep glib-2.0`" != "x"; then
|
|
||||||
ssl_error="GLIB2 and OpenSSL don't work together currently, SSL is disabled"
|
|
||||||
enable_openssl=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$enable_openssl" = xyes; then
|
if test "x$enable_openssl" = xyes; then
|
||||||
AC_DEFINE(HAVE_OPENSSL)
|
AC_DEFINE(HAVE_OPENSSL)
|
||||||
|
|
||||||
|
@ -29,23 +29,6 @@
|
|||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
/* ssl read */
|
|
||||||
GIOError irssi_ssl_read(GIOChannel *, gchar *, guint, guint *);
|
|
||||||
/* ssl write */
|
|
||||||
GIOError irssi_ssl_write(GIOChannel *, gchar *, guint, guint*);
|
|
||||||
/* ssl seek */
|
|
||||||
GIOError irssi_ssl_seek(GIOChannel *, gint, GSeekType);
|
|
||||||
/* ssl close */
|
|
||||||
void irssi_ssl_close(GIOChannel *);
|
|
||||||
#if GLIB_MAJOR_VERSION < 2
|
|
||||||
/* ssl create watch */
|
|
||||||
guint irssi_ssl_create_watch(GIOChannel *, gint, GIOCondition, GIOFunc, gpointer, GDestroyNotify);
|
|
||||||
#else
|
|
||||||
GSource *irssi_ssl_create_watch(GIOChannel *, GIOCondition);
|
|
||||||
#endif
|
|
||||||
/* ssl free */
|
|
||||||
void irssi_ssl_free(GIOChannel *);
|
|
||||||
|
|
||||||
/* ssl i/o channel object */
|
/* ssl i/o channel object */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -56,23 +39,20 @@ typedef struct
|
|||||||
X509 *cert;
|
X509 *cert;
|
||||||
} GIOSSLChannel;
|
} GIOSSLChannel;
|
||||||
|
|
||||||
/* ssl function pointers */
|
static void irssi_ssl_free(GIOChannel *handle)
|
||||||
GIOFuncs irssi_ssl_channel_funcs =
|
|
||||||
{
|
{
|
||||||
irssi_ssl_read,
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
irssi_ssl_write,
|
g_io_channel_unref(chan->giochan);
|
||||||
irssi_ssl_seek,
|
SSL_free(chan->ssl);
|
||||||
irssi_ssl_close,
|
g_free(chan);
|
||||||
irssi_ssl_create_watch,
|
}
|
||||||
irssi_ssl_free
|
|
||||||
};
|
|
||||||
|
|
||||||
SSL_CTX *ssl_ctx = NULL;
|
#if GLIB_MAJOR_VERSION < 2
|
||||||
|
|
||||||
#ifdef G_CAN_INLINE
|
#ifdef G_CAN_INLINE
|
||||||
G_INLINE_FUNC
|
G_INLINE_FUNC
|
||||||
#endif
|
#endif
|
||||||
gint ssl_errno(gint e)
|
static GIOError ssl_errno(gint e)
|
||||||
{
|
{
|
||||||
switch(e)
|
switch(e)
|
||||||
{
|
{
|
||||||
@ -85,10 +65,10 @@ gint ssl_errno(gint e)
|
|||||||
return G_IO_ERROR_INVAL;
|
return G_IO_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
/*UNREACH*/
|
/*UNREACH*/
|
||||||
return -1;
|
return G_IO_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean irssi_ssl_cert_step(GIOSSLChannel *chan)
|
static GIOError irssi_ssl_cert_step(GIOSSLChannel *chan)
|
||||||
{
|
{
|
||||||
gint err;
|
gint err;
|
||||||
switch(err = SSL_do_handshake(chan->ssl))
|
switch(err = SSL_do_handshake(chan->ssl))
|
||||||
@ -106,10 +86,10 @@ gboolean irssi_ssl_cert_step(GIOSSLChannel *chan)
|
|||||||
return ssl_errno(errno);
|
return ssl_errno(errno);
|
||||||
}
|
}
|
||||||
/*UNREACH*/
|
/*UNREACH*/
|
||||||
return -1;
|
return G_IO_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret)
|
static GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
gint err;
|
gint err;
|
||||||
@ -138,7 +118,7 @@ GIOError irssi_ssl_read(GIOChannel *handle, gchar *buf, guint len, guint *ret)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint *ret)
|
static GIOError irssi_ssl_write(GIOChannel *handle, const gchar *buf, guint len, guint *ret)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
gint err;
|
gint err;
|
||||||
@ -165,10 +145,10 @@ GIOError irssi_ssl_write(GIOChannel *handle, gchar *buf, guint len, guint *ret)
|
|||||||
return G_IO_ERROR_NONE;
|
return G_IO_ERROR_NONE;
|
||||||
}
|
}
|
||||||
/*UNREACH*/
|
/*UNREACH*/
|
||||||
return -1;
|
return G_IO_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type)
|
static GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
GIOError e;
|
GIOError e;
|
||||||
@ -176,38 +156,186 @@ GIOError irssi_ssl_seek(GIOChannel *handle, gint offset, GSeekType type)
|
|||||||
return (e == G_IO_ERROR_NONE) ? G_IO_ERROR_NONE : G_IO_ERROR_INVAL;
|
return (e == G_IO_ERROR_NONE) ? G_IO_ERROR_NONE : G_IO_ERROR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void irssi_ssl_close(GIOChannel *handle)
|
static void irssi_ssl_close(GIOChannel *handle)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
g_io_channel_close(chan->giochan);
|
g_io_channel_close(chan->giochan);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GLIB_MAJOR_VERSION < 2
|
static guint irssi_ssl_create_watch(GIOChannel *handle, gint priority, GIOCondition cond,
|
||||||
guint irssi_ssl_create_watch(GIOChannel *handle, gint priority, GIOCondition cond,
|
|
||||||
GIOFunc func, gpointer data, GDestroyNotify notify)
|
GIOFunc func, gpointer data, GDestroyNotify notify)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
|
|
||||||
return chan->giochan->funcs->io_add_watch(handle, priority, cond, func, data, notify);
|
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 */
|
||||||
|
|
||||||
|
#ifdef G_CAN_INLINE
|
||||||
|
G_INLINE_FUNC
|
||||||
#else
|
#else
|
||||||
GSource *irssi_ssl_create_watch(GIOChannel *handle, GIOCondition cond)
|
static
|
||||||
|
#endif
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
gint err;
|
||||||
|
switch(err = SSL_do_handshake(chan->ssl))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if(!(chan->cert = SSL_get_peer_certificate(chan->ssl)))
|
||||||
|
{
|
||||||
|
g_warning("SSL server supplied no certificate");
|
||||||
|
return G_IO_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
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, guint len, guint *ret, GError **gerr)
|
||||||
|
{
|
||||||
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
|
gint err;
|
||||||
|
|
||||||
|
if(chan->cert == NULL)
|
||||||
|
{
|
||||||
|
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->cert == NULL)
|
||||||
|
{
|
||||||
|
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;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
|
|
||||||
return chan->giochan->funcs->io_create_watch(handle, cond);
|
return chan->giochan->funcs->io_create_watch(handle, cond);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void irssi_ssl_free(GIOChannel *handle)
|
static GIOStatus irssi_ssl_set_flags(GIOChannel *handle, GIOFlags flags, GError **gerr)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
GIOSSLChannel *chan = (GIOSSLChannel *)handle;
|
||||||
g_io_channel_unref(chan->giochan);
|
|
||||||
SSL_free(chan->ssl);
|
return chan->giochan->funcs->io_set_flags(handle, flags, gerr);
|
||||||
g_free(chan);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean irssi_ssl_init(void)
|
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 SSL_CTX *ssl_ctx = NULL;
|
||||||
|
|
||||||
|
static gboolean irssi_ssl_init(void)
|
||||||
{
|
{
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
@ -223,7 +351,7 @@ gboolean irssi_ssl_init(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle)
|
||||||
{
|
{
|
||||||
GIOSSLChannel *chan;
|
GIOSSLChannel *chan;
|
||||||
GIOChannel *gchan;
|
GIOChannel *gchan;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user