Patch that restores support for OpenSSL in Camel
- From: Philip Van Hoof <spam pvanhoof be>
- To: tinymail-devel-list gnome org, evolution-patches gnome org
- Cc: Nitin Mahajan nokia com
- Subject: Patch that restores support for OpenSSL in Camel
- Date: Wed, 01 Nov 2006 21:10:51 +0100
Recent Camel does not have support for OpenSSL. Its camel-tcp-stream-
openssl.c implementation is 'really' outdated.
I have fixed this by reimplementing parts of it.
In Tinymail's Camel I have put a check for the OpenSSL library which
will add "-lcrypto -lssl" to the libraries. Those changes are not in
this patch.
The check must also set HAVE_SSL to 1 and HAVE_OPENSSL only to 1 if
Mozilla's NSS is NOT going to be used while OpenSSL was found.
The two together will clash during compilation (they share the same
camel-tcp-stream-ssl.h include file and they share the same API).
ps. I have not yet corrected the certificate handling. But maybe it's
still working and correct?
ps. I have tested this with an IMAPS server. It seems to work.
--
Philip Van Hoof, software developer at x-tend
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
work: vanhoof at x-tend dot be
http://www.pvanhoof.be - http://www.x-tend.be
--- /home/pvanhoof/repos/gnome/cvs/evolution-data-server/camel/camel-tcp-stream-ssl.c 2006-04-12 21:14:13.000000000 +0200
+++ camel/camel-tcp-stream-ssl.c 2006-11-01 20:44:52.000000000 +0100
@@ -29,6 +29,8 @@
#include <config.h>
+#ifndef HAVE_OPENSSL
+
#ifdef HAVE_NSS
#include <unistd.h>
#include <sys/types.h>
@@ -654,7 +656,7 @@
int i;
const char tohex[16] = "0123456789abcdef";
- md5_get_digest (cert->derCert.data, cert->derCert.len, md5sum);
+ md5_get_digest ((const gchar *) cert->derCert.data, cert->derCert.len, md5sum);
for (i=0,f = fingerprint; i<16; i++) {
unsigned int c = md5sum[i];
@@ -672,7 +674,7 @@
fingerprint[47] = 0;
- return g_strdup(fingerprint);
+ return g_strdup((gchar*) fingerprint);
}
/* lookup a cert uses fingerprint to index an on-disk file */
@@ -806,7 +808,7 @@
stream = camel_stream_fs_new_with_name (path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (stream != NULL) {
- if (camel_stream_write (stream, ccert->rawcert->data, ccert->rawcert->len) == -1) {
+ if (camel_stream_write (stream, (const char *) ccert->rawcert->data, ccert->rawcert->len) == -1) {
g_warning ("Could not save cert: %s: %s", path, strerror (errno));
g_unlink (path);
}
@@ -1310,3 +1312,4 @@
}
#endif /* HAVE_NSS */
+#endif /* HAVE_OPENSSL */
--- /home/pvanhoof/repos/gnome/cvs/evolution-data-server/camel/camel-tcp-stream-openssl.c 2005-08-31 06:21:56.000000000 +0200
+++ camel/camel-tcp-stream-openssl.c 2006-11-01 20:57:00.000000000 +0100
@@ -1,6 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Authors: Jeffrey Stedfast <fejj ximian com>
+ * Authors:
+ * Jeffrey Stedfast <fejj ximian com>
+ * Philip Van Hoof <pvanhoof gnome org>
*
* Copyright 2001 Ximian, Inc. (www.ximian.com)
*
@@ -21,9 +23,7 @@
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#ifdef HAVE_OPENSSL
@@ -43,6 +43,7 @@
#include "camel-service.h"
#include "camel-operation.h"
#include "camel-certdb.h"
+#include "camel-i18n.h"
#define d(x)
@@ -58,19 +59,19 @@
static int stream_flush (CamelStream *stream);
static int stream_close (CamelStream *stream);
-static int stream_connect (CamelTcpStream *stream, struct hostent *host, int port);
+static int stream_connect (CamelTcpStream *stream, struct addrinfo *host);
static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
-static CamelTcpAddress *stream_get_local_address (CamelTcpStream *stream);
-static CamelTcpAddress *stream_get_remote_address (CamelTcpStream *stream);
+static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
+static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
-static SSL *open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl);
+static SSL *open_ssl_connection (CamelSession *session, int sockfd, CamelTcpStreamSSL *openssl);
struct _CamelTcpStreamSSLPrivate {
int sockfd;
SSL *ssl;
- CamelService *service;
+ CamelSession *session;
char *expected_host;
gboolean ssl_mode;
guint32 flags;
@@ -156,9 +157,10 @@
}
+
/**
* camel_tcp_stream_ssl_new:
- * @service: camel service
+ * @session: camel session
* @expected_host: host that the stream is expecting to connect with.
* @flags: flags
*
@@ -169,13 +171,13 @@
* Return value: a ssl stream (in ssl mode)
**/
CamelStream *
-camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host, guint32 flags)
+camel_tcp_stream_ssl_new (struct _CamelSession *session, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
- stream->priv->service = service;
+ stream->priv->session = session;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = TRUE;
stream->priv->flags = flags;
@@ -186,7 +188,7 @@
/**
* camel_tcp_stream_ssl_new_raw:
- * @service: camel service
+ * @session: camel session
* @expected_host: host that the stream is expecting to connect with.
* @flags: flags
*
@@ -197,13 +199,13 @@
* Return value: a ssl-capable stream (in non ssl mode)
**/
CamelStream *
-camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host, guint32 flags)
+camel_tcp_stream_ssl_new_raw (struct _CamelSession *session, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
- stream->priv->service = service;
+ stream->priv->session = session;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = FALSE;
stream->priv->flags = flags;
@@ -255,7 +257,7 @@
g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (stream), -1);
if (stream->priv->sockfd != -1 && !stream->priv->ssl_mode) {
- ssl = open_ssl_connection (stream->priv->service, stream->priv->sockfd, stream);
+ ssl = open_ssl_connection (stream->priv->session, stream->priv->sockfd, stream);
if (ssl == NULL) {
stream->priv->sockfd = -1;
return -1;
@@ -282,7 +284,7 @@
errno = EINTR;
return -1;
}
-
+
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
do {
@@ -333,7 +335,7 @@
fcntl (openssl->priv->sockfd, F_SETFL, flags);
errno = error;
}
-
+
return nread;
}
@@ -455,13 +457,9 @@
/* this is a 'cancellable' connect, cancellable from camel_operation_cancel etc */
/* returns -1 & errno == EINTR if the connection was cancelled */
static int
-socket_connect (struct hostent *h, int port)
+socket_connect (struct addrinfo *host)
{
-#ifdef ENABLE_IPv6
- struct sockaddr_in6 sin6;
-#endif
- struct sockaddr_in sin;
- struct sockaddr *saddr;
+ struct sockaddr *saddr = host->ai_addr;
struct timeval tv;
socklen_t len;
int cancel_fd;
@@ -472,27 +470,8 @@
errno = EINTR;
return -1;
}
-
- /* setup connect, we do it using a nonblocking socket so we can poll it */
-#ifdef ENABLE_IPv6
- if (h->h_addrtype == AF_INET6) {
- sin6.sin6_port = htons (port);
- sin6.sin6_family = h->h_addrtype;
- memcpy (&sin6.sin6_addr, h->h_addr, sizeof (sin6.sin6_addr));
- saddr = (struct sockaddr *) &sin6;
- len = sizeof (sin6);
- } else {
-#endif
- sin.sin_port = htons (port);
- sin.sin_family = h->h_addrtype;
- memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
- saddr = (struct sockaddr *) &sin;
- len = sizeof (sin);
-#ifdef ENABLE_IPv6
- }
-#endif
-
- fd = socket (h->h_addrtype, SOCK_STREAM, 0);
+
+ fd = socket (host->ai_family, SOCK_STREAM, 0);
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
@@ -637,11 +616,12 @@
{
unsigned char md5sum[16], fingerprint[40], *f;
CamelTcpStreamSSL *stream;
- CamelService *service;
+ CamelSession *session;
CamelCertDB *certdb = NULL;
CamelCert *ccert = NULL;
char *prompt, *cert_str;
- int err, md5len, i;
+ int err, i;
+ unsigned int md5len;
char buf[257];
X509 *cert;
SSL *ssl;
@@ -655,7 +635,7 @@
if (!stream)
return FALSE;
- service = stream->priv->service;
+ session = stream->priv->session;
cert = X509_STORE_CTX_get_current_cert (ctx);
err = X509_STORE_CTX_get_error (ctx);
@@ -664,13 +644,13 @@
md5len = sizeof (md5sum);
X509_digest (cert, EVP_md5 (), md5sum, &md5len);
for (i = 0, f = fingerprint; i < 16; i++, f += 3)
- sprintf (f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0');
+ sprintf ((char *) f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0');
#define GET_STRING(name) X509_NAME_oneline (name, buf, 256)
certdb = camel_certdb_get_default ();
if (certdb) {
- ccert = camel_certdb_get_cert (certdb, fingerprint);
+ ccert = camel_certdb_get_cert (certdb, (const char *) fingerprint);
if (ccert) {
if (ccert->trust != CAMEL_CERT_TRUST_UNKNOWN) {
ok = ccert->trust != CAMEL_CERT_TRUST_NEVER;
@@ -684,8 +664,8 @@
ccert = camel_certdb_cert_new (certdb);
camel_cert_set_issuer (certdb, ccert, GET_STRING (X509_get_issuer_name (cert)));
camel_cert_set_subject (certdb, ccert, GET_STRING (X509_get_subject_name (cert)));
- camel_cert_set_hostname (certdb, ccert, stream->priv->expected_host);
- camel_cert_set_fingerprint (certdb, ccert, fingerprint);
+ camel_cert_set_hostname (certdb, ccert, (const char *) stream->priv->expected_host);
+ camel_cert_set_fingerprint (certdb, ccert, (const char *) fingerprint);
camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
/* Add the certificate to our db */
@@ -701,11 +681,11 @@
GET_STRING (X509_get_subject_name (cert)),
fingerprint, cert->valid ? _("GOOD") : _("BAD"));
- prompt = g_strdup_printf (_("Bad certificate from %s:\n\n%s\n\n%s\n\n"
- "Do you wish to accept anyway?"),
- service->url->host, cert_str, x509_strerror (err));
+ prompt = g_strdup_printf (_("Bad certificate\n\n%s\n\n%s\n\n"
+ "Do you wish to accept anyway?"),
+ cert_str, x509_strerror (err));
- ok = camel_session_alert_user (service->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE);
+ ok = camel_session_alert_user (session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE);
g_free (prompt);
if (ok && ccert) {
@@ -722,7 +702,7 @@
}
static SSL *
-open_ssl_connection (CamelService *service, int sockfd, CamelTcpStreamSSL *openssl)
+open_ssl_connection (CamelSession *session, int sockfd, CamelTcpStreamSSL *openssl)
{
SSL_CTX *ssl_ctx = NULL;
SSL *ssl = NULL;
@@ -759,8 +739,7 @@
return ssl;
}
-static int
-stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
+static int stream_connect_do (CamelTcpStream *stream, struct addrinfo *host)
{
CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream);
SSL *ssl = NULL;
@@ -768,12 +747,12 @@
g_return_val_if_fail (host != NULL, -1);
- fd = socket_connect (host, port);
+ fd = socket_connect (host);
if (fd == -1)
return -1;
if (openssl->priv->ssl_mode) {
- ssl = open_ssl_connection (openssl->priv->service, fd, openssl);
+ ssl = open_ssl_connection (openssl->priv->session, fd, openssl);
if (!ssl)
return -1;
}
@@ -784,6 +763,18 @@
return 0;
}
+static int
+stream_connect (CamelTcpStream *stream, struct addrinfo *host)
+{
+ while (host) {
+ if (stream_connect_do (stream, host) == 0)
+ return 0;
+ host = host->ai_next;
+ }
+
+ return -1;
+}
+
static int
get_sockopt_level (const CamelSockOptData *data)
@@ -848,7 +839,7 @@
get_sockopt_level (data),
optname,
(void *) &data->value,
- &optlen);
+ (socklen_t *) &optlen);
}
static int
@@ -882,74 +873,26 @@
sizeof (data->value));
}
-#ifdef ENABLE_IPv6
-#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in6))
-#else
-#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in))
-#endif
-
-static CamelTcpAddress *
-stream_get_local_address (CamelTcpStream *stream)
-{
- unsigned char buf[MIN_SOCKADDR_BUFLEN];
-#ifdef ENABLE_IPv6
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf;
-#endif
- struct sockaddr_in *sin = (struct sockaddr_in *) buf;
- struct sockaddr *saddr = (struct sockaddr *) buf;
- gpointer address;
- socklen_t len;
- int family;
-
- len = MIN_SOCKADDR_BUFLEN;
-
- if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
- return NULL;
-
- if (saddr->sa_family == AF_INET) {
- family = CAMEL_TCP_ADDRESS_IPv4;
- address = &sin->sin_addr;
-#ifdef ENABLE_IPv6
- } else if (saddr->sa_family == AF_INET6) {
- family = CAMEL_TCP_ADDRESS_IPv6;
- address = &sin6->sin6_addr;
-#endif
- } else
+static struct sockaddr *
+stream_get_local_address (CamelTcpStream *stream, socklen_t *len)
+{
+ struct sockaddr *saddr = (struct sockaddr *) (malloc (*len));
+
+ if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, len) == -1)
return NULL;
-
- return camel_tcp_address_new (family, sin->sin_port, len, address);
+
+ return saddr;
}
-static CamelTcpAddress *
-stream_get_remote_address (CamelTcpStream *stream)
+static struct sockaddr *
+stream_get_remote_address (CamelTcpStream *stream, socklen_t *len)
{
- unsigned char buf[MIN_SOCKADDR_BUFLEN];
-#ifdef ENABLE_IPv6
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf;
-#endif
- struct sockaddr_in *sin = (struct sockaddr_in *) buf;
- struct sockaddr *saddr = (struct sockaddr *) buf;
- gpointer address;
- socklen_t len;
- int family;
-
- len = MIN_SOCKADDR_BUFLEN;
-
- if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
- return NULL;
-
- if (saddr->sa_family == AF_INET) {
- family = CAMEL_TCP_ADDRESS_IPv4;
- address = &sin->sin_addr;
-#ifdef ENABLE_IPv6
- } else if (saddr->sa_family == AF_INET6) {
- family = CAMEL_TCP_ADDRESS_IPv6;
- address = &sin6->sin6_addr;
-#endif
- } else
+ struct sockaddr *saddr = (struct sockaddr *) (malloc (*len));
+
+ if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, len) == -1)
return NULL;
-
- return camel_tcp_address_new (family, sin->sin_port, len, address);
+
+ return saddr;
}
#endif /* HAVE_OPENSSL */
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]