From 416d8fa6cd84e6b25886c1c2fcbf2b0dbce58b7f Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Mon, 7 May 2001 20:33:25 +0000 Subject: Add support for using OpenSSL. 2001-05-04 Jeffrey Stedfast * providers/smtp/camel-smtp-transport.c (connect_to_server): Add support for using OpenSSL. * camel-remote-store.c (remote_connect): Add support for using the OpenSSL implementation. * camel-tcp-stream-ssl.c (ssl_bad_cert): Hmmmm, don't pass in a NULL as the last argument to alert_user - prototype doesn't take that argument anymore? * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_finalize): (ssl_verify): Use a global hash table to try and lookup the CamelTcpStreamOpenSSL object given the ssl context since OpenSSL doesn't think one needs to pass data around, we should all be living in a world of global variables, duh! svn path=/trunk/; revision=9697 --- camel/ChangeLog | 18 +++++++ camel/Makefile.am | 4 +- camel/camel-remote-store.c | 20 +++++-- camel/camel-tcp-stream-openssl.c | 82 +++++++++++++++++++++-------- camel/camel-tcp-stream-openssl.h | 2 +- camel/providers/smtp/Makefile.am | 1 + camel/providers/smtp/camel-smtp-transport.c | 12 ++++- 7 files changed, 109 insertions(+), 30 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index 5f8125c189..d52e0eafe7 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,21 @@ +2001-05-04 Jeffrey Stedfast + + * providers/smtp/camel-smtp-transport.c (connect_to_server): Add + support for using OpenSSL. + + * camel-remote-store.c (remote_connect): Add support for using the + OpenSSL implementation. + + * camel-tcp-stream-ssl.c (ssl_bad_cert): Hmmmm, don't pass in a + NULL as the last argument to alert_user - prototype doesn't take + that argument anymore? + + * camel-tcp-stream-openssl.c (camel_tcp_stream_openssl_finalize): + (ssl_verify): Use a global hash table to try and lookup the + CamelTcpStreamOpenSSL object given the ssl context since OpenSSL + doesn't think one needs to pass data around, we should all be + living in a world of global variables, duh! + 2001-05-06 Dan Winship * Makefile.am (libcamelinclude_HEADERS): Fix another build diff --git a/camel/Makefile.am b/camel/Makefile.am index cf6a0b48e3..dda2cb13f0 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -15,6 +15,7 @@ INCLUDES = -I.. -I$(srcdir)/.. \ $(KRB4_CFLAGS) \ $(NSPR_CFLAGS) \ $(NSS_CFLAGS) \ + $(OPENSSL_CFLAGS) \ -DCAMEL_PROVIDERDIR=\""$(providerdir)"\" \ -DG_LOG_DOMAIN=\"camel\" @@ -179,7 +180,8 @@ libcamel_la_LIBADD = $(top_builddir)/e-util/libeutil.la \ $(GAL_LIBS) \ $(KRB4_LDFLAGS) \ $(NSPR_LDFLAGS) \ - $(NSS_LDFLAGS) + $(NSS_LDFLAGS) \ + $(OPENSSL_LDFLAGS) noinst_HEADERS = \ diff --git a/camel/camel-remote-store.c b/camel/camel-remote-store.c index a0f142e889..767a0fbe51 100644 --- a/camel/camel-remote-store.c +++ b/camel/camel-remote-store.c @@ -46,10 +46,15 @@ #include "camel-stream-buffer.h" #include "camel-tcp-stream.h" #include "camel-tcp-stream-raw.h" -#if HAVE_NSS + +#ifdef HAVE_NSS #include "camel-tcp-stream-ssl.h" #endif +#ifdef HAVE_OPENSSL +#include "camel-tcp-stream-openssl.h" +#endif + #include "camel-url.h" #include "string-utils.h" @@ -223,14 +228,21 @@ remote_connect (CamelService *service, CamelException *ex) else port = store->default_port; +#if defined(HAVE_NSS) || defined(HAVE_OPENSSL) + if (store->use_ssl) { #ifdef HAVE_NSS - if (store->use_ssl) + /* this is the preferred SSL implementation */ tcp_stream = camel_tcp_stream_ssl_new (service, service->url->host); - else +#else + /* use openssl... */ + tcp_stream = camel_tcp_stream_openssl_new (service, service->url->host); +#endif /* HAVE_NSS */ + } else { tcp_stream = camel_tcp_stream_raw_new (); + } #else tcp_stream = camel_tcp_stream_raw_new (); -#endif /* HAVE_NSS */ +#endif /* HAVE_NSS || HAVE_OPENSSL */ ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); camel_free_host(h); diff --git a/camel/camel-tcp-stream-openssl.c b/camel/camel-tcp-stream-openssl.c index c59705ae8a..0312e65b44 100644 --- a/camel/camel-tcp-stream-openssl.c +++ b/camel/camel-tcp-stream-openssl.c @@ -25,7 +25,11 @@ #endif #ifdef HAVE_OPENSSL -#include + +#include "camel-tcp-stream-openssl.h" + +#include +#include #include #include #include @@ -33,11 +37,25 @@ #include #include #include -#include "camel-tcp-stream-openssl.h" +#include "camel-session.h" +#include "camel-service.h" #include "camel-operation.h" +#ifdef ENABLE_THREADS +#include +#endif static CamelTcpStreamClass *parent_class = NULL; +static GHashTable *openssl_table = NULL; +#ifdef ENABLE_THREADS +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +#define OPENSSL_TABLE_LOCK() pthread_mutex_lock (&lock) +#define OPENSSL_TABLE_UNLOCK() pthread_mutex_unlock (&lock) +#else +#define OPENSSL_TABLE_LOCK +#define OPENSSL_TABLE_UNLOCK +#endif + /* Returns the class for a CamelTcpStreamOpenSSL */ #define CTSR_CLASS(so) CAMEL_TCP_STREAM_OPENSSL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) @@ -98,8 +116,16 @@ camel_tcp_stream_openssl_finalize (CamelObject *object) if (stream->priv->ssl) { SSL_shutdown (stream->priv->ssl); - if (stream->priv->ssl->ctx) + if (stream->priv->ssl->ctx) { + OPENSSL_TABLE_LOCK (); + g_hash_table_remove (openssl_table, stream->priv->ssl->ctx); + if (g_hash_table_size (openssl_table) == 0) { + g_hash_table_destroy (openssl_table); + openssl_table = NULL; + } + OPENSSL_TABLE_UNLOCK (); SSL_CTX_free (stream->priv->ssl->ctx); + } SSL_free (stream->priv->ssl); } @@ -376,30 +402,35 @@ socket_connect (struct hostent *h, int port) static int ssl_verify (int ok, X509_STORE_CTX *ctx) { - char *str, buf[256]; + CamelTcpStreamOpenSSL *stream; X509 *cert; int err; + OPENSSL_TABLE_LOCK (); + stream = CAMEL_TCP_STREAM_OPENSSL (g_hash_table_lookup (openssl_table, ctx)); + OPENSSL_TABLE_UNLOCK (); + cert = X509_STORE_CTX_get_current_cert (ctx); err = X509_STORE_CTX_get_error (ctx); - str = X509_NAME_oneline (X509_get_subject_name (cert), buf, 256); - if (str) { - if (ok) - d(fprintf (stderr, "CamelTcpStreamSSL: depth=%d %s\n", ctx->error_depth, buf)); - else - d(fprintf (stderr, "CamelTcpStreamSSL: depth=%d error=%d %s\n", - ctx->error_depth, err, buf)); - } - - if (!ok) { - switch (err) { - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - /* FIXME: get user's response */ - ok = 1; - } + if (!ok && stream) { + CamelService *service = stream->priv->service; + char *prompt, *cert_str; + char buf[257]; + +#define GET_STRING(name) X509_NAME_oneline(name, buf, 256) + + cert_str = g_strdup_printf (_("Issuer: %s\n" + "Subject: %s"), + GET_STRING (X509_get_issuer_name (cert)), + GET_STRING (X509_get_subject_name (cert))); + + prompt = g_strdup_printf (_("Bad certificate from %s:\n\n%s\n\n" + "Do you wish to accept anyway?"), + service->url->host, cert_str); + + ok = camel_session_alert_user (service->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE); + g_free (prompt); } return ok; @@ -445,13 +476,20 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port) if (fd == -1) return -1; - ssl = open_ssl_connection (stream->priv->service, sockfd); + ssl = open_ssl_connection (openssl->priv->service, fd); if (!ssl) return -1; openssl->priv->sockfd = fd; openssl->priv->ssl = ssl; + OPENSSL_TABLE_LOCK (); + if (!openssl_table) + openssl_table = g_hash_table_new (g_direct_hash, g_direct_equal); + + g_hash_table_insert (openssl_table, ssl->ctx, openssl); + OPENSSL_TABLE_UNLOCK (); + return 0; } diff --git a/camel/camel-tcp-stream-openssl.h b/camel/camel-tcp-stream-openssl.h index 0103332c3f..6eab9465a4 100644 --- a/camel/camel-tcp-stream-openssl.h +++ b/camel/camel-tcp-stream-openssl.h @@ -55,7 +55,7 @@ typedef struct { CamelType camel_tcp_stream_openssl_get_type (void); /* public methods */ -CamelStream *camel_tcp_stream_openssl_new (void); +CamelStream *camel_tcp_stream_openssl_new (CamelService *service, const char *expected_host); #ifdef __cplusplus } diff --git a/camel/providers/smtp/Makefile.am b/camel/providers/smtp/Makefile.am index 74597f57f5..fcc2b06f9d 100644 --- a/camel/providers/smtp/Makefile.am +++ b/camel/providers/smtp/Makefile.am @@ -19,6 +19,7 @@ INCLUDES = \ $(GTK_INCLUDEDIR) \ $(NSPR_CFLAGS) \ $(NSS_CFLAGS) \ + $(OPENSSL_CFLAGS) \ -DG_LOG_DOMAIN=\"camel-smtp-provider\" libcamelsmtp_la_SOURCES = \ diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c index e6f0b8cafa..2d07a26b85 100644 --- a/camel/providers/smtp/camel-smtp-transport.c +++ b/camel/providers/smtp/camel-smtp-transport.c @@ -53,6 +53,9 @@ #include "camel-tcp-stream-ssl.h" #include #endif +#ifdef HAVE_OPENSSL +#include "camel-tcp-stream-openssl.h" +#endif #include "camel-session.h" #include "camel-exception.h" #include "camel-sasl.h" @@ -243,16 +246,21 @@ connect_to_server (CamelService *service, CamelException *ex) port = service->url->port ? service->url->port : SMTP_PORT; -#ifdef HAVE_NSS +#if defined(HAVE_NSS) || defined(HAVE_OPENSSL) if (transport->use_ssl) { port = service->url->port ? service->url->port : 465; +#ifdef HAVE_NSS + /* use the preferred implementation - NSS */ tcp_stream = camel_tcp_stream_ssl_new (service, service->url->host); +#else + tcp_stream = camel_tcp_stream_openssl_new (service, service->url->host); +#endif /* HAVE_NSS */ } else { tcp_stream = camel_tcp_stream_raw_new (); } #else tcp_stream = camel_tcp_stream_raw_new (); -#endif /* HAVE_NSS */ +#endif /* HAVE_NSS || HAVE_OPENSSL */ ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port); camel_free_host(h); -- cgit v1.2.3