Index: configure.ac =================================================================== RCS file: /cvsroot/gaim/gaim/configure.ac,v retrieving revision 1.377 diff -u -p -r1.377 configure.ac --- configure.ac 11 Feb 2006 17:15:18 -0000 1.377 +++ configure.ac 13 Feb 2006 03:51:46 -0000 @@ -950,6 +950,11 @@ AC_ARG_ENABLE(nss, [enable_nss="$enableval"], [enable_nss="yes"]) +AC_ARG_ENABLE(openssl, + [ --enable-openssl=[yes,no,statuc] Attempt to use Mozilla libnss for OpenSSL support [default=yes]], + [enable_openssl="$enableval"], + [enable_openssl="yes"]) + msg_ssl="None (MSN will not work without SSL!)" dnl # @@ -1304,12 +1309,95 @@ fi AM_CONDITIONAL(USE_NSS, test "x$enable_nss" = "xyes") -if test "x$msg_nss" != "x" -a "x$msg_gnutls" != "x"; then - msg_ssl="$msg_nss and $msg_gnutls" +dnl # +dnl # Check for OpenSSL if it's specified. +dnl # +if test "x$enable_openssl" != "xno"; then + enable_openssl="no" + prefix=`eval echo $prefix` + + AC_ARG_WITH(openssl-includes, + [ --with-openssl-includes=PREFIX Location of OpenSSL includes.], + [ with_openssl_includes="$withval" ], + [ with_openssl_includes="$prefix/include" ]) + + have_openssl_includes="no" + + if test "x$with_openssl_includes" != "xno"; then + CPPFLAGS_save="$CPPFLAGS" + + AC_MSG_CHECKING(for OpenSSL includes) + AC_MSG_RESULT("") + + CPPFLAGS="$CPPFLAGS -I$with_openssl_includes" + AC_CHECK_HEADERS(openssl/ssl.h, [ openssl_includes="yes" ]) + CPPFLAGS="$CPPFLAGS_save" + + if test "x$openssl_includes" != "xno" -a \ + "x$openssl_includes" != "x"; then + have_openssl_includes="yes" + + OPENSSL_CFLAGS="-I$with_openssl_includes" + else + OPENSSL_CFLAGS="" + fi + else + AC_MSG_CHECKING(for OPENSSL includes) + AC_MSG_RESULT(no) + fi + + AC_ARG_WITH(openssl-libs, + [ --with-openssl-libs=PREFIX Location of OpenSSL libraries.], + [ with_openssl_libs="$withval" ]) + + if test "x$with_openssl_libs" != "xno" -a \ + "x$have_openssl_includes" != "xno"; then + + LDFLAGS_save="$LDFLAGS" + + case $with_openssl_libs in + ""|-L*) ;; + *) with_openssl_libs="-L$with_gnutls_libs" ;; + esac + + AC_CACHE_CHECK([for OpenSSL libraries], openssl_libs, + [ + LDFLAGS="$LDFLAGS $with_gnutls_libs -lssl -lcrypto" + AC_TRY_LINK_FUNC(SSL_library_init, openssl_libs="yes", openssl_libs="no") + LDFLAGS="$LDFLAGS_save" + ]) + + if test "x$openssl_libs" != "xno"; then + AC_DEFINE(HAVE_OPENSSL, 1, [Define if you have OpenSSL]) + AC_DEFINE(HAVE_SSL) + msg_openssl="OPENSSL" + OPENSSL_LIBS="$with_openssl_libs -lssl -lcrypto" + + enable_openssl="yes" + else + OPENSSL_CFLAGS="" + OPENSSL_LIBS="" + fi + else + AC_MSG_CHECKING(for OpenSSL libraries) + AC_MSG_RESULT(no) + fi +else + OPENSSL_CFLAGS="" + OPENSSL_LIBS="" +fi + +AC_SUBST(OPENSSL_CFLAGS) +AC_SUBST(OPENSSL_LIBS) + +if test "x$msg_nss" != "x" -a "x$msg_gnutls" != "x" -a "x$msg_openssl" != "x"; then + msg_ssl="$msg_nss / $msg_gnutls / $msg_openssl" elif test "x$msg_nss" != "x"; then msg_ssl=$msg_nss elif test "x$msg_gnutls" != "x"; then msg_ssl=$msg_gnutls +elif test "x$msg_openssl" != "x"; then + msg_ssl=$msg_openssl fi dnl Check for Tcl Index: plugins/ssl/Makefile.am =================================================================== RCS file: /cvsroot/gaim/gaim/plugins/ssl/Makefile.am,v retrieving revision 1.5 diff -u -p -r1.5 Makefile.am --- plugins/ssl/Makefile.am 29 Apr 2005 17:04:25 -0000 1.5 +++ plugins/ssl/Makefile.am 13 Feb 2006 03:51:46 -0000 @@ -6,20 +6,23 @@ plugindir = $(libdir)/gaim ssl_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) ssl_gnutls_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) ssl_nss_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) - +ssl_openssl_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) if PLUGINS plugin_LTLIBRARIES = \ ssl.la \ ssl-gnutls.la \ - ssl-nss.la + ssl-nss.la \ + ssl-openssl.la ssl_la_SOURCES = ssl.c ssl_gnutls_la_SOURCES = ssl-gnutls.c ssl_nss_la_SOURCES = ssl-nss.c +ssl_openssl_la_SOURCES = ssl-openssl.c ssl_gnutls_la_LIBADD = $(GNUTLS_LIBS) ssl_nss_la_LIBADD = $(NSS_LIBS) +ssl_openssl_la_LIBADD = $(OPENSSL_LIBS) endif # PLUGINS @@ -31,4 +34,5 @@ AM_CPPFLAGS = \ $(GTK_CFLAGS) \ $(PLUGIN_CFLAGS) \ $(NSS_CFLAGS) \ - $(GNUTLS_CFLAGS) + $(GNUTLS_CFLAGS) \ + $(OPENSSL_CFLAGS) --- /dev/null 2006-02-11 01:39:15.000000000 +0800 +++ plugins/ssl/ssl-openssl.c 2006-02-13 11:50:37.000000000 +0800 @@ -0,0 +1,313 @@ +/* + * OpenSSL SSL-plugin for gaim + * + * Copyright (c) 2004, 2006 Jim Huang + * Copyright (C) 2003 Matthew Luckie + * + * 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. + * + * This plugin is released under the GPL with the additional exemption + * that compiling, linking, and/or using OpenSSL is allowed. + * + * 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 + * + * ********************* + * + * This code was written to link in with the gaim ssl plugin system. + * It was written using the ssl-nss.c and ssl-gnutls.c files as documentation + * as to how to use the gaim ssl plugin mechanism. That code was written by + * ChipX86. + * + * This code is not supported by the gaim team. If you have SSL-related + * problems with any service, disable this plugin and use one of the ssl + * plugins that ships with gaim before contacting them for support. + * + * The OpenSSL webpage at http://www.openssl.org/support/faq.html#LEGAL2 + * says that you may use this code on systems that normally include OpenSSL. + */ + +#include "internal.h" +#include "debug.h" +#include "plugin.h" +#include "sslconn.h" +#include "version.h" + +#define SSL_OPENSSL_PLUGIN_ID "ssl-openssl" + +#ifdef HAVE_OPENSSL + +#include +#include + +typedef struct +{ + SSL *ssl; + SSL_CTX *ssl_ctx; +} GaimSslOpensslData; + +#define GAIM_SSL_OPENSSL_DATA(gsc) ((GaimSslOpensslData *)gsc->private_data) + +/* + * ssl_openssl_init + * + * load the error strings we might want to use eventually, and init the + * openssl library + */ +static gboolean ssl_openssl_init(void) +{ + /* + * load the error number to string strings so that we can make sense + * of ssl issues while debugging this code + */ + SSL_load_error_strings(); + + /* + * we need to initialise the openssl library + * we do not seed the random number generator, although we probably + * should in gaim-win32. + */ + SSL_library_init(); + + return TRUE; +} + +/* + * ssl_openssl_uninit + * + * couldn't find anything to match the call to SSL_library_init in the man + * pages, i wonder if there actually is anything we need to call + */ +static void ssl_openssl_uninit(void) +{ + ERR_free_strings(); + return; +} + +/* + * ssl_openssl_connect_cb + * + * given a socket, put an openssl connection around it. + */ +static void ssl_openssl_connect_cb(gpointer data, gint source, GaimInputCondition cond) +{ + GaimSslConnection *gsc = (GaimSslConnection *)data; + GaimSslOpensslData *openssl_data; + + /* + * we need a valid file descriptor to associate the SSL connection with. + */ + if(source < 0) + { + return; + } + + gsc->fd = source; + + /* + * allocate some memory to store variables for the openssl connection. + * the memory comes zero'd from g_new0 so we don't need to null the + * pointers held in this struct. + */ + openssl_data = g_new0(GaimSslOpensslData, 1); + gsc->private_data = openssl_data; + + /* + * allocate a new SSL_CTX object + */ + openssl_data->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); + if(openssl_data->ssl_ctx == NULL) + { + gaim_debug_error("openssl", "SSL_CTX_new failed\n"); + if(gsc->error_cb != NULL) + { + gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); + } + + gaim_ssl_close(gsc); + return; + } + + /* + * allocate a new SSL object + */ + openssl_data->ssl = SSL_new(openssl_data->ssl_ctx); + if(openssl_data->ssl == NULL) + { + gaim_debug_error("openssl", "SSL_new failed\n"); + if(gsc->error_cb != NULL) + { + gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); + } + + gaim_ssl_close(gsc); + return; + } + + /* + * now we associate the file descriptor we have with the SSL connection + */ + if(SSL_set_fd(openssl_data->ssl, source) == 0) + { + gaim_debug_error("openssl", "SSL_set_fd failed\n"); + if(gsc->error_cb != NULL) + { + gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); + } + + gaim_ssl_close(gsc); + return; + } + + /* + * finally, do the negotiation that sets up the SSL connection between + * here and there. + */ + if(SSL_connect(openssl_data->ssl) <= 0) + { + gaim_debug_error("openssl", "SSL_connect failed\n"); + if(gsc->error_cb != NULL) + { + gsc->error_cb(gsc, GAIM_SSL_HANDSHAKE_FAILED, gsc->connect_cb_data); + } + + gaim_ssl_close(gsc); + return; + } + + /* SSL connected now */ + gsc->connect_cb(gsc->connect_cb_data, gsc, cond); + return; +} + +static void ssl_openssl_close(GaimSslConnection *gsc) +{ + GaimSslOpensslData *openssl_data = GAIM_SSL_OPENSSL_DATA(gsc); + int i; + + if(openssl_data == NULL) + { + return; + } + + if(openssl_data->ssl != NULL) + { + i = SSL_shutdown(openssl_data->ssl); + if(i == 0) SSL_shutdown(openssl_data->ssl); + SSL_free(openssl_data->ssl); + } + + if(openssl_data->ssl_ctx != NULL) + { + SSL_CTX_free(openssl_data->ssl_ctx); + } + + g_free(openssl_data); + + return; +} + +static size_t ssl_openssl_read(GaimSslConnection *gsc, void *data, size_t len) +{ + GaimSslOpensslData *openssl_data = GAIM_SSL_OPENSSL_DATA(gsc); + int i; + + i = SSL_read(openssl_data->ssl, data, len); + if(i < 0) i = 0; + + return i; +} + +static size_t ssl_openssl_write(GaimSslConnection *gsc, const void *data, size_t len) +{ + GaimSslOpensslData *openssl_data = GAIM_SSL_OPENSSL_DATA(gsc); + int s = 0; + + if(openssl_data != NULL) + { + s = SSL_write(openssl_data->ssl, data, len); + } + + if(s < 0) + { + s = 0; + } + + return s; +} + +static GaimSslOps ssl_ops = +{ + ssl_openssl_init, + ssl_openssl_uninit, + ssl_openssl_connect_cb, + ssl_openssl_close, + ssl_openssl_read, + ssl_openssl_write +}; + +#endif /* HAVE_OPENSSL */ + +static gboolean plugin_load(GaimPlugin *plugin) +{ +#ifdef HAVE_OPENSSL + gaim_ssl_set_ops(&ssl_ops); + return TRUE; +#else + return FALSE; +#endif +} + +static gboolean plugin_unload(GaimPlugin *plugin) +{ +#ifdef HAVE_OPENSSL + gaim_ssl_set_ops(NULL); +#endif + + return TRUE; +} + +static GaimPluginInfo info = +{ + GAIM_PLUGIN_MAGIC, + GAIM_MAJOR_VERSION, + GAIM_MINOR_VERSION, + GAIM_PLUGIN_STANDARD, /**< type */ + NULL, /**< ui_requirement */ + GAIM_PLUGIN_FLAG_INVISIBLE, /**< flags */ + NULL, /**< dependencies */ + GAIM_PRIORITY_DEFAULT, /**< priority */ + + SSL_OPENSSL_PLUGIN_ID, /**< id */ + N_("OpenSSL"), /**< name */ + VERSION, /**< version */ + + N_("Provides SSL support through OpenSSL."), /**< description */ + N_("Provides SSL support through OpenSSL."), + "Jim Huang ", + GAIM_WEBSITE, /**< homepage */ + + plugin_load, /**< load */ + plugin_unload, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + NULL, /**< extra_info */ + NULL, /**< prefs_info */ + NULL /**< actions */ +}; + +static void init_plugin(GaimPlugin *plugin) +{ +} + +GAIM_INIT_PLUGIN(ssl_openssl, init_plugin, info)