From fba011bf008443ee5130f1426aa65e11245cd84a Mon Sep 17 00:00:00 2001
From: JP Rosevear <jpr@src.gnome.org>
Date: Tue, 11 Jan 2005 00:00:07 +0000
Subject: Kill dead files

svn path=/trunk/; revision=28342
---
 camel/camel-tcp-stream-ssl.c | 1257 ------------------------------------------
 1 file changed, 1257 deletions(-)
 delete mode 100644 camel/camel-tcp-stream-ssl.c

(limited to 'camel/camel-tcp-stream-ssl.c')

diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
deleted file mode 100644
index a818fbc8b4..0000000000
--- a/camel/camel-tcp-stream-ssl.c
+++ /dev/null
@@ -1,1257 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- *  Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- *  Copyright 2001 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-/* NOTE: This is the default implementation of CamelTcpStreamSSL,
- * used when the Mozilla NSS libraries are used. If you configured
- * OpenSSL support instead, then this file won't be compiled and
- * the CamelTcpStreamSSL implementation in camel-tcp-stream-openssl.c
- * will be used instead.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_NSS
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-
-#include <nspr.h>
-#include <prio.h>
-#include <prerror.h>
-#include <prerr.h>
-#include <secerr.h>
-#include <sslerr.h>
-#include "nss.h"    /* Don't use <> here or it will include the system nss.h instead */
-#include <ssl.h>
-#include <cert.h>
-#include <certdb.h>
-#include <pk11func.h>
-
-/* this is commented because otherwise we get an error about the
-   redefinition of MD5Context...yay */
-/*#include <libedataserver/md5-utils.h>*/
-
-#include "camel-tcp-stream-ssl.h"
-#include "camel-stream-fs.h"
-#include "camel-session.h"
-#include "camel-certdb.h"
-#include "camel-operation.h"
-#include "camel-i18n.h"
-
-/* from md5-utils.h */
-void md5_get_digest (const char *buffer, int buffer_size, unsigned char digest[16]);
-
-#define IO_TIMEOUT (PR_TicksPerSecond() * 4 * 60)
-#define CONNECT_TIMEOUT (PR_TicksPerSecond () * 4 * 60)
-
-static CamelTcpStreamClass *parent_class = NULL;
-
-/* Returns the class for a CamelTcpStreamSSL */
-#define CTSS_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so))
-
-static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n);
-static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n);
-static int stream_flush  (CamelStream *stream);
-static int stream_close  (CamelStream *stream);
-
-static PRFileDesc *enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd);
-
-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 struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
-static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
-
-struct _CamelTcpStreamSSLPrivate {
-	PRFileDesc *sockfd;
-	
-	struct _CamelSession *session;
-	char *expected_host;
-	gboolean ssl_mode;
-	guint32 flags;
-};
-
-static void
-camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_class)
-{
-	CamelTcpStreamClass *camel_tcp_stream_class =
-		CAMEL_TCP_STREAM_CLASS (camel_tcp_stream_ssl_class);
-	CamelStreamClass *camel_stream_class =
-		CAMEL_STREAM_CLASS (camel_tcp_stream_ssl_class);
-	
-	parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ()));
-	
-	/* virtual method overload */
-	camel_stream_class->read = stream_read;
-	camel_stream_class->write = stream_write;
-	camel_stream_class->flush = stream_flush;
-	camel_stream_class->close = stream_close;
-	
-	camel_tcp_stream_class->connect = stream_connect;
-	camel_tcp_stream_class->getsockopt = stream_getsockopt;
-	camel_tcp_stream_class->setsockopt = stream_setsockopt;
-	camel_tcp_stream_class->get_local_address  = stream_get_local_address;
-	camel_tcp_stream_class->get_remote_address = stream_get_remote_address;
-}
-
-static void
-camel_tcp_stream_ssl_init (gpointer object, gpointer klass)
-{
-	CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
-	
-	stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1);
-}
-
-static void
-camel_tcp_stream_ssl_finalize (CamelObject *object)
-{
-	CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
-	
-	if (stream->priv->sockfd != NULL)
-		PR_Close (stream->priv->sockfd);
-
-	if (stream->priv->session)
-		camel_object_unref(stream->priv->session);
-
-	g_free (stream->priv->expected_host);
-	
-	g_free (stream->priv);
-}
-
-
-CamelType
-camel_tcp_stream_ssl_get_type (void)
-{
-	static CamelType type = CAMEL_INVALID_TYPE;
-	
-	if (type == CAMEL_INVALID_TYPE) {
-		type = camel_type_register (camel_tcp_stream_get_type (),
-					    "CamelTcpStreamSSL",
-					    sizeof (CamelTcpStreamSSL),
-					    sizeof (CamelTcpStreamSSLClass),
-					    (CamelObjectClassInitFunc) camel_tcp_stream_ssl_class_init,
-					    NULL,
-					    (CamelObjectInitFunc) camel_tcp_stream_ssl_init,
-					    (CamelObjectFinalizeFunc) camel_tcp_stream_ssl_finalize);
-	}
-	
-	return type;
-}
-
-
-/**
- * camel_tcp_stream_ssl_new:
- * @session: active session
- * @expected_host: host that the stream is expected to connect with.
- * @flags: ENABLE_SSL2, ENABLE_SSL3 and/or ENABLE_TLS
- *
- * Since the SSL certificate authenticator may need to prompt the
- * user, a CamelSession is needed. @expected_host is needed as a
- * protection against an MITM attack.
- *
- * Return value: a ssl stream (in ssl mode)
- **/
-CamelStream *
-camel_tcp_stream_ssl_new (CamelSession *session, const char *expected_host, guint32 flags)
-{
-	CamelTcpStreamSSL *stream;
-
-	g_assert(CAMEL_IS_SESSION(session));
-
-	stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-	
-	stream->priv->session = session;
-	camel_object_ref(session);
-	stream->priv->expected_host = g_strdup (expected_host);
-	stream->priv->ssl_mode = TRUE;
-	stream->priv->flags = flags;
-	
-	return CAMEL_STREAM (stream);
-}
-
-
-/**
- * camel_tcp_stream_ssl_new_raw:
- * @session: active session
- * @expected_host: host that the stream is expected to connect with.
- * @flags: ENABLE_SSL2, ENABLE_SSL3 and/or ENABLE_TLS
- *
- * Since the SSL certificate authenticator may need to prompt the
- * user, a CamelSession is needed. @expected_host is needed as a
- * protection against an MITM attack.
- *
- * Return value: a ssl-capable stream (in non ssl mode)
- **/
-CamelStream *
-camel_tcp_stream_ssl_new_raw (CamelSession *session, const char *expected_host, guint32 flags)
-{
-	CamelTcpStreamSSL *stream;
-
-	g_assert(CAMEL_IS_SESSION(session));
-	
-	stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
-	
-	stream->priv->session = session;
-	camel_object_ref(session);
-	stream->priv->expected_host = g_strdup (expected_host);
-	stream->priv->ssl_mode = FALSE;
-	stream->priv->flags = flags;
-	
-	return CAMEL_STREAM (stream);
-}
-
-
-static void
-set_errno (int code)
-{
-	/* FIXME: this should handle more. */
-	switch (code) {
-	case PR_INVALID_ARGUMENT_ERROR:
-		errno = EINVAL;
-		break;
-	case PR_PENDING_INTERRUPT_ERROR:
-		errno = EINTR;
-		break;
-	case PR_IO_PENDING_ERROR:
-		errno = EAGAIN;
-		break;
-	case PR_WOULD_BLOCK_ERROR:
-		errno = EWOULDBLOCK;
-		break;
-	case PR_IN_PROGRESS_ERROR:
-		errno = EINPROGRESS;
-		break;
-	case PR_ALREADY_INITIATED_ERROR:
-		errno = EALREADY;
-		break;
-	case PR_NETWORK_UNREACHABLE_ERROR:
-		errno = EHOSTUNREACH;
-		break;
-	case PR_CONNECT_REFUSED_ERROR:
-		errno = ECONNREFUSED;
-		break;
-	case PR_CONNECT_TIMEOUT_ERROR:
-	case PR_IO_TIMEOUT_ERROR:
-		errno = ETIMEDOUT;
-		break;
-	case PR_NOT_CONNECTED_ERROR:
-		errno = ENOTCONN;
-		break;
-	case PR_CONNECT_RESET_ERROR:
-		errno = ECONNRESET;
-		break;
-	case PR_IO_ERROR:
-	default:
-		errno = EIO;
-		break;
-	}
-}
-
-
-/**
- * camel_tcp_stream_ssl_enable_ssl:
- * @ssl: ssl stream
- *
- * Toggles an ssl-capable stream into ssl mode (if it isn't already).
- *
- * Returns 0 on success or -1 on fail.
- **/
-int
-camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl)
-{
-	PRFileDesc *fd;
-	
-	g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (ssl), -1);
-	
-	if (ssl->priv->sockfd && !ssl->priv->ssl_mode) {
-		if (!(fd = enable_ssl (ssl, NULL))) {
-			set_errno (PR_GetError ());
-			return -1;
-		}
-		
-		ssl->priv->sockfd = fd;
-		
-		if (SSL_ResetHandshake (fd, FALSE) == SECFailure) {
-			set_errno (PR_GetError ());
-			return -1;
-		}
-		
-		if (SSL_ForceHandshake (fd) == -1) {
-			set_errno (PR_GetError ());
-			return -1;
-		}
-	}
-	
-	ssl->priv->ssl_mode = TRUE;
-	
-	return 0;
-}
-
-
-static ssize_t
-stream_read (CamelStream *stream, char *buffer, size_t n)
-{
-	CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
-	PRFileDesc *cancel_fd;
-	ssize_t nread;
-	
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-	
-	cancel_fd = camel_operation_cancel_prfd (NULL);
-	if (cancel_fd == NULL) {
-		do {
-			nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n);
-			if (nread == -1)
-				set_errno (PR_GetError ());
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-	} else {
-		PRSocketOptionData sockopts;
-		PRPollDesc pollfds[2];
-		gboolean nonblock;
-		int error;
-		
-		/* get O_NONBLOCK options */
-		sockopts.option = PR_SockOpt_Nonblocking;
-		PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-		sockopts.option = PR_SockOpt_Nonblocking;
-		nonblock = sockopts.value.non_blocking;
-		sockopts.value.non_blocking = TRUE;
-		PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-
-		pollfds[0].fd = tcp_stream_ssl->priv->sockfd;
-		pollfds[0].in_flags = PR_POLL_READ;
-		pollfds[1].fd = cancel_fd;
-		pollfds[1].in_flags = PR_POLL_READ;
-		
-		do {
-			PRInt32 res;
-
-			pollfds[0].out_flags = 0;
-			pollfds[1].out_flags = 0;
-			nread = -1;
-
-			res = PR_Poll(pollfds, 2, IO_TIMEOUT);
-			if (res == -1)
-				set_errno(PR_GetError());
-			else if (res == 0)
-				errno = ETIMEDOUT;
-			else if (pollfds[1].out_flags == PR_POLL_READ) {
-				errno = EINTR;
-				goto failed;
-			} else {
-				do {
-					nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n);
-					if (nread == -1)
-						set_errno (PR_GetError ());
-				} while (nread == -1 && errno == EINTR);
-			}
-		} while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-		
-		/* restore O_NONBLOCK options */
-	failed:
-		error = errno;
-		sockopts.option = PR_SockOpt_Nonblocking;
-		sockopts.value.non_blocking = nonblock;
-		PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-		errno = error;
-	}
-	
-	return nread;
-}
-
-static ssize_t
-stream_write (CamelStream *stream, const char *buffer, size_t n)
-{
-	CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream);
-	ssize_t w, written = 0;
-	PRFileDesc *cancel_fd;
-	
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-	
-	cancel_fd = camel_operation_cancel_prfd (NULL);
-	if (cancel_fd == NULL) {
-		do {
-			do {
-				w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written);
-				if (w == -1)
-					set_errno (PR_GetError ());
-			} while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
-			
-			if (w > 0)
-				written += w;
-		} while (w != -1 && written < n);
-	} else {
-		PRSocketOptionData sockopts;
-		PRPollDesc pollfds[2];
-		gboolean nonblock;
-		int error;
-		
-		/* get O_NONBLOCK options */
-		sockopts.option = PR_SockOpt_Nonblocking;
-		PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-		sockopts.option = PR_SockOpt_Nonblocking;
-		nonblock = sockopts.value.non_blocking;
-		sockopts.value.non_blocking = TRUE;
-		PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-		
-		pollfds[0].fd = tcp_stream_ssl->priv->sockfd;
-		pollfds[0].in_flags = PR_POLL_WRITE;
-		pollfds[1].fd = cancel_fd;
-		pollfds[1].in_flags = PR_POLL_READ;
-		
-		do {
-			PRInt32 res;
-
-			pollfds[0].out_flags = 0;
-			pollfds[1].out_flags = 0;
-			w = -1;
-
-			res = PR_Poll (pollfds, 2, IO_TIMEOUT);
-			if (res == -1) {
-				set_errno(PR_GetError());
-				if (errno == EINTR)
-					w = 0;
-			} else if (res == 0)
-				errno = ETIMEDOUT;
-			else if (pollfds[1].out_flags == PR_POLL_READ) {
-				errno = EINTR;
-			} else {
-				do {
-					w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written);
-					if (w == -1)
-						set_errno (PR_GetError ());
-				} while (w == -1 && errno == EINTR);
-				
-				if (w == -1) {
-					if (errno == EAGAIN || errno == EWOULDBLOCK)
-						w = 0;
-				} else
-					written += w;
-			}
-		} while (w != -1 && written < n);
-		
-		/* restore O_NONBLOCK options */
-		error = errno;
-		sockopts.option = PR_SockOpt_Nonblocking;
-		sockopts.value.non_blocking = nonblock;
-		PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts);
-		errno = error;
-	}
-	
-	if (w == -1)
-		return -1;
-	
-	return written;
-}
-
-static int
-stream_flush (CamelStream *stream)
-{
-	/*return PR_Sync (((CamelTcpStreamSSL *)stream)->priv->sockfd);*/
-	return 0;
-}
-
-static int
-stream_close (CamelStream *stream)
-{
-	if (PR_Close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == PR_FAILURE)
-		return -1;
-	
-	((CamelTcpStreamSSL *)stream)->priv->sockfd = NULL;
-	
-	return 0;
-}
-
-#if 0
-/* Since this is default implementation, let NSS handle it. */
-static SECStatus
-ssl_get_client_auth (void *data, PRFileDesc *sockfd,
-		     struct CERTDistNamesStr *caNames,
-		     struct CERTCertificateStr **pRetCert,
-		     struct SECKEYPrivateKeyStr **pRetKey) 
-{
-	SECStatus status = SECFailure;
-	SECKEYPrivateKey *privkey;
-	CERTCertificate *cert;
-	void *proto_win;
-	
-	proto_win = SSL_RevealPinArg (sockfd);
-	
-	if ((char *) data) {
-		cert = PK11_FindCertFromNickname ((char *) data, proto_win);
-		if (cert) {
-			privKey = PK11_FindKeyByAnyCert (cert, proto_win);
-			if (privkey) {
-				status = SECSuccess;
-			} else {
-				CERT_DestroyCertificate (cert);
-			}
-		}
-	} else {
-		/* no nickname given, automatically find the right cert */
-		CERTCertNicknames *names;
-		int i;
-		
-		names = CERT_GetCertNicknames (CERT_GetDefaultCertDB (), 
-					       SEC_CERT_NICKNAMES_USER,
-					       proto_win);
-		
-		if (names != NULL) {
-			for (i = 0; i < names->numnicknames; i++) {
-				cert = PK11_FindCertFromNickname (names->nicknames[i], 
-								  proto_win);
-				if (!cert)
-					continue;
-				
-				/* Only check unexpired certs */
-				if (CERT_CheckCertValidTimes (cert, PR_Now (), PR_FALSE) != secCertTimeValid) {
-					CERT_DestroyCertificate (cert);
-					continue;
-				}
-				
-				status = NSS_CmpCertChainWCANames (cert, caNames);
-				if (status == SECSuccess) {
-					privkey = PK11_FindKeyByAnyCert (cert, proto_win);
-					if (privkey)
-						break;
-					
-					status = SECFailure;
-					break;
-				}
-				
-				CERT_FreeNicknames (names);
-			}
-		}
-	}
-	
-	if (status == SECSuccess) {
-		*pRetCert = cert;
-		*pRetKey  = privkey;
-	}
-	
-	return status;
-}
-#endif
-
-#if 0
-/* Since this is the default NSS implementation, no need for us to use this. */
-static SECStatus
-ssl_auth_cert (void *data, PRFileDesc *sockfd, PRBool checksig, PRBool is_server)
-{
-	CERTCertificate *cert;
-	SECStatus status;
-	void *pinarg;
-	char *host;
-	
-	cert = SSL_PeerCertificate (sockfd);
-	pinarg = SSL_RevealPinArg (sockfd);
-	status = CERT_VerifyCertNow ((CERTCertDBHandle *)data, cert,
-				     checksig, certUsageSSLClient, pinarg);
-	
-	if (status != SECSuccess)
-		return SECFailure;
-	
-	/* Certificate is OK.  Since this is the client side of an SSL
-	 * connection, we need to verify that the name field in the cert
-	 * matches the desired hostname.  This is our defense against
-	 * man-in-the-middle attacks.
-	 */
-	
-	/* SSL_RevealURL returns a hostname, not a URL. */
-	host = SSL_RevealURL (sockfd);
-	
-	if (host && *host) {
-		status = CERT_VerifyCertName (cert, host);
-	} else {
-		PR_SetError (SSL_ERROR_BAD_CERT_DOMAIN, 0);
-		status = SECFailure;
-	}
-	
-	if (host)
-		PR_Free (host);
-	
-	return secStatus;
-}
-#endif
-
-CamelCert *camel_certdb_nss_cert_get(CamelCertDB *certdb, CERTCertificate *cert);
-CamelCert *camel_certdb_nss_cert_add(CamelCertDB *certdb, CERTCertificate *cert);
-void camel_certdb_nss_cert_set(CamelCertDB *certdb, CamelCert *ccert, CERTCertificate *cert);
-
-static char *
-cert_fingerprint(CERTCertificate *cert)
-{
-	unsigned char md5sum[16], fingerprint[50], *f;
-	int i;
-	const char tohex[16] = "0123456789abcdef";
-
-	md5_get_digest (cert->derCert.data, cert->derCert.len, md5sum);
-	for (i=0,f = fingerprint; i<16; i++) {
-		unsigned int c = md5sum[i];
-
-		*f++ = tohex[(c >> 4) & 0xf];
-		*f++ = tohex[c & 0xf];
-		*f++ = ':';
-	}
-
-	fingerprint[47] = 0;
-
-	return g_strdup(fingerprint);
-}
-
-/* lookup a cert uses fingerprint to index an on-disk file */
-CamelCert *
-camel_certdb_nss_cert_get(CamelCertDB *certdb, CERTCertificate *cert)
-{
-	char *fingerprint, *path;
-	CamelCert *ccert;
-	struct stat st;
-	size_t nread;
-	ssize_t n;
-	int fd;
-	
-	fingerprint = cert_fingerprint (cert);
-	ccert = camel_certdb_get_cert (certdb, fingerprint);
-	if (ccert == NULL) {
-		g_free (fingerprint);
-		return ccert;
-	}
-	
-	if (ccert->rawcert == NULL) {
-		path = g_strdup_printf ("%s/.camel_certs/%s", getenv ("HOME"), fingerprint);
-		if (stat (path, &st) == -1
-		    || (fd = open (path, O_RDONLY)) == -1) {
-			g_warning ("could not load cert %s: %s", path, strerror (errno));
-			g_free (fingerprint);
-			g_free (path);
-			camel_cert_set_trust (certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
-			camel_certdb_touch (certdb);
-			
-			return ccert;
-		}
-		g_free(path);
-		
-		ccert->rawcert = g_byte_array_new ();
-		g_byte_array_set_size (ccert->rawcert, st.st_size);
-		
-		nread = 0;
-		do {
-			do {
-				n = read (fd, ccert->rawcert->data + nread, st.st_size - nread);
-			} while (n == -1 && errno == EINTR);
-			
-			if (n > 0)
-				nread += n;
-		} while (nread < st.st_size && n != -1);
-		
-		close (fd);
-		
-		if (nread != st.st_size) {
-			g_warning ("cert size read truncated %s: %d != %ld", path, nread, st.st_size);
-			g_byte_array_free(ccert->rawcert, TRUE);
-			ccert->rawcert = NULL;
-			g_free(fingerprint);
-			camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
-			camel_certdb_touch(certdb);
-
-			return ccert;
-		}
-	}
-
-	g_free(fingerprint);
-	if (ccert->rawcert->len != cert->derCert.len
-	    || memcmp(ccert->rawcert->data, cert->derCert.data, cert->derCert.len) != 0) {
-		g_warning("rawcert != derCer");
-		camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
-		camel_certdb_touch(certdb);
-	}
-
-	return ccert;
-}
-
-/* add a cert to the certdb */
-CamelCert *
-camel_certdb_nss_cert_add(CamelCertDB *certdb, CERTCertificate *cert)
-{
-	CamelCert *ccert;
-	char *fingerprint;
-
-	fingerprint = cert_fingerprint(cert);
-
-	ccert = camel_certdb_cert_new(certdb);
-	camel_cert_set_issuer(certdb, ccert, CERT_NameToAscii(&cert->issuer));
-	camel_cert_set_subject(certdb, ccert, CERT_NameToAscii(&cert->subject));
-	/* hostname is set in caller */
-	/*camel_cert_set_hostname(certdb, ccert, ssl->priv->expected_host);*/
-	camel_cert_set_fingerprint(certdb, ccert, fingerprint);
-	camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_UNKNOWN);
-	g_free(fingerprint);
-
-	camel_certdb_nss_cert_set(certdb, ccert, cert);
-
-	camel_certdb_add(certdb, ccert);
-
-	return ccert;
-}
-
-/* set the 'raw' cert (& save it) */
-void
-camel_certdb_nss_cert_set(CamelCertDB *certdb, CamelCert *ccert, CERTCertificate *cert)
-{
-	char *dir, *path, *fingerprint;
-	CamelStream *stream;
-	struct stat st;
-	
-	fingerprint = ccert->fingerprint;
-	
-	if (ccert->rawcert == NULL)
-		ccert->rawcert = g_byte_array_new ();
-	
-	g_byte_array_set_size (ccert->rawcert, cert->derCert.len);
-	memcpy (ccert->rawcert->data, cert->derCert.data, cert->derCert.len);
-	
-	dir = g_strdup_printf ("%s/.camel_certs", getenv ("HOME"));
-	if (stat (dir, &st) == -1 && mkdir (dir, 0700) == -1) {
-		g_warning ("Could not create cert directory '%s': %s", dir, strerror (errno));
-		g_free (dir);
-		return;
-	}
-	
-	path = g_strdup_printf ("%s/%s", dir, fingerprint);
-	g_free (dir);
-	
-	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) {
-			g_warning ("Could not save cert: %s: %s", path, strerror (errno));
-			unlink (path);
-		}
-		camel_stream_close (stream);
-		camel_object_unref (stream);
-	} else {
-		g_warning ("Could not save cert: %s: %s", path, strerror (errno));
-	}
-	
-	g_free (path);
-}
-
-
-#if 0
-/* used by the mozilla-like code below */
-static char *
-get_nickname(CERTCertificate *cert)
-{
-	char *server, *nick = NULL;
-	int i;
-	PRBool status = PR_TRUE;
-
-	server = CERT_GetCommonName(&cert->subject);
-	if (server == NULL)
-		return NULL;
-
-	for (i=1;status == PR_TRUE;i++) {
-		if (nick) {
-			g_free(nick);
-			nick = g_strdup_printf("%s #%d", server, i);
-		} else {
-			nick = g_strdup(server);
-		}
-		status = SEC_CertNicknameConflict(server, &cert->derSubject, cert->dbhandle);
-	}
-
-	return nick;
-}
-#endif
-
-static SECStatus
-ssl_bad_cert (void *data, PRFileDesc *sockfd)
-{
-	gboolean accept;
-	CamelCertDB *certdb = NULL;
-	CamelCert *ccert = NULL;
-	char *prompt, *cert_str, *fingerprint;
-	CamelTcpStreamSSL *ssl;
-	CERTCertificate *cert;
-	SECStatus status = SECFailure;
-
-	g_return_val_if_fail (data != NULL, SECFailure);
-	g_return_val_if_fail (CAMEL_IS_TCP_STREAM_SSL (data), SECFailure);
-
-	ssl = data;
-	
-	cert = SSL_PeerCertificate (sockfd);
-	if (cert == NULL)
-		return SECFailure;
-
-	certdb = camel_certdb_get_default();
-	ccert = camel_certdb_nss_cert_get(certdb, cert);
-	if (ccert == NULL) {
-		ccert = camel_certdb_nss_cert_add(certdb, cert);
-		camel_cert_set_hostname(certdb, ccert, ssl->priv->expected_host);
-	}
-
-	if (ccert->trust == CAMEL_CERT_TRUST_UNKNOWN) {
-		status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL);
-		fingerprint = cert_fingerprint(cert);
-		cert_str = g_strdup_printf (_("Issuer:            %s\n"
-					      "Subject:           %s\n"
-					      "Fingerprint:       %s\n"
-					      "Signature:         %s"),
-					    CERT_NameToAscii (&cert->issuer),
-					    CERT_NameToAscii (&cert->subject),
-					    fingerprint, status == SECSuccess?_("GOOD"):_("BAD"));
-		g_free(fingerprint);
-
-		/* construct our user prompt */
-		prompt = g_strdup_printf (_("SSL Certificate check for %s:\n\n%s\n\nDo you wish to accept?"),
-					  ssl->priv->expected_host, cert_str);
-		g_free (cert_str);
-	
-		/* query the user to find out if we want to accept this certificate */
-		accept = camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE);
-		g_free(prompt);
-		if (accept) {
-			camel_certdb_nss_cert_set(certdb, ccert, cert);
-			camel_cert_set_trust(certdb, ccert, CAMEL_CERT_TRUST_FULLY);
-			camel_certdb_touch(certdb);
-		}
-	} else {
-		accept = ccert->trust != CAMEL_CERT_TRUST_NEVER;
-	}
-
-	camel_certdb_cert_unref(certdb, ccert);
-	camel_object_unref(certdb);
-
-	return accept ? SECSuccess : SECFailure;
-
-#if 0
-	int i, error;
-	CERTCertTrust trust;
-	SECItem *certs[1];
-	int go = 1;
-	char *host, *nick;
-
-	error = PR_GetError();
-
-	/* This code is basically what mozilla does - however it doesn't seem to work here
-	   very reliably :-/ */
-	while (go && status != SECSuccess) {
-		char *prompt = NULL;
-
-		printf("looping, error '%d'\n", error);
-
-		switch(error) {
-		case SEC_ERROR_UNKNOWN_ISSUER:
-		case SEC_ERROR_CA_CERT_INVALID:
-		case SEC_ERROR_UNTRUSTED_ISSUER:
-		case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
-			/* add certificate */
-			printf("unknown issuer, adding ... \n");
-			prompt = g_strdup_printf(_("Certificate problem: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
-			if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
-
-				nick = get_nickname(cert);
-				if (NULL == nick) {
-					g_free(prompt);
-					status = SECFailure;
-					break;
-				}
-
-				printf("adding cert '%s'\n", nick);
-
-				if (!cert->trust) {
-					cert->trust = (CERTCertTrust*)PORT_ArenaZAlloc(cert->arena, sizeof(CERTCertTrust));
-					CERT_DecodeTrustString(cert->trust, "P");
-				}
-		
-				certs[0] = &cert->derCert;
-				/*CERT_ImportCerts (cert->dbhandle, certUsageSSLServer, 1, certs, NULL, TRUE, FALSE, nick);*/
-				CERT_ImportCerts(cert->dbhandle, certUsageUserCertImport, 1, certs, NULL, TRUE, FALSE, nick);
-				g_free(nick);
-
-				printf(" cert type %08x\n", cert->nsCertType);
-
-				memset((void*)&trust, 0, sizeof(trust));
-				if (CERT_GetCertTrust(cert, &trust) != SECSuccess) {
-					CERT_DecodeTrustString(&trust, "P");
-				}
-				trust.sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
-				if (CERT_ChangeCertTrust(cert->dbhandle, cert, &trust) != SECSuccess) {
-					printf("couldn't change cert trust?\n");
-				}
-
-				/*status = SECSuccess;*/
-#if 1
-				/* re-verify? */
-				status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLServer, NULL);
-				error = PR_GetError();
-				printf("re-verify status %d, error %d\n", status, error);
-#endif
-
-				printf(" cert type %08x\n", cert->nsCertType);
-			} else {
-				printf("failed/cancelled\n");
-				go = 0;
-			}
-
-			break;
-		case SSL_ERROR_BAD_CERT_DOMAIN:
-			printf("bad domain\n");
-
-			prompt = g_strdup_printf(_("Bad certificate domain: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
-			if (camel_session_alert_user (ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
-				host = SSL_RevealURL(sockfd);
-				status = CERT_AddOKDomainName(cert, host);
-				printf("add ok domain name : %s\n", status == SECFailure?"fail":"ok");
-				error = PR_GetError();
-				if (status == SECFailure)
-					go = 0;
-			} else {
-				go = 0;
-			}
-
-			break;
-			
-		case SEC_ERROR_EXPIRED_CERTIFICATE:
-			printf("expired\n");
-
-			prompt = g_strdup_printf(_("Certificate expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
-			if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
-				cert->timeOK = PR_TRUE;
-				status = CERT_VerifyCertNow(cert->dbhandle, cert, TRUE, certUsageSSLClient, NULL);
-				error = PR_GetError();
-				if (status == SECFailure)
-					go = 0;
-			} else {
-				go = 0;
-			}
-
-			break;
-
-		case SEC_ERROR_CRL_EXPIRED:
-			printf("crl expired\n");
-
-			prompt = g_strdup_printf(_("Certificate revocation list expired: %s\nIssuer: %s"), cert->subjectName, cert->issuerName);
-
-			if (camel_session_alert_user(ssl->priv->session, CAMEL_SESSION_ALERT_WARNING, prompt, TRUE)) {
-				host = SSL_RevealURL(sockfd);
-				status = CERT_AddOKDomainName(cert, host);
-			}
-
-			go = 0;
-			break;
-
-		default:
-			printf("generic error\n");
-			go = 0;
-			break;
-		}
-
-		g_free(prompt);
-	}
-
-	CERT_DestroyCertificate(cert);
-
-	return status;
-#endif
-}
-
-static PRFileDesc *
-enable_ssl (CamelTcpStreamSSL *ssl, PRFileDesc *fd)
-{
-	PRFileDesc *ssl_fd;
-	
-	ssl_fd = SSL_ImportFD (NULL, fd ? fd : ssl->priv->sockfd);
-	if (!ssl_fd)
-		return NULL;
-	
-	SSL_OptionSet (ssl_fd, SSL_SECURITY, PR_TRUE);
-	if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL2)
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_TRUE);
-	else
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL2, PR_FALSE);
-	if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_SSL3)
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_TRUE);
-	else
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_SSL3, PR_FALSE);
-	if (ssl->priv->flags & CAMEL_TCP_STREAM_SSL_ENABLE_TLS)
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_TRUE);
-	else
-		SSL_OptionSet (ssl_fd, SSL_ENABLE_TLS, PR_FALSE);
-	
-	SSL_SetURL (ssl_fd, ssl->priv->expected_host);
-	
-	/*SSL_GetClientAuthDataHook (sslSocket, ssl_get_client_auth, (void *) certNickname);*/
-	/*SSL_AuthCertificateHook (ssl_fd, ssl_auth_cert, (void *) CERT_GetDefaultCertDB ());*/
-	SSL_BadCertHook (ssl_fd, ssl_bad_cert, ssl);
-	
-	ssl->priv->ssl_mode = TRUE;
-	
-	return ssl_fd;
-}
-
-static int
-sockaddr_to_praddr(struct sockaddr *s, int len, PRNetAddr *addr)
-{
-	/* We assume the ip addresses are the same size - they have to be anyway.
-	   We could probably just use memcpy *shrug* */
-
-	memset(addr, 0, sizeof(*addr));
-
-	if (s->sa_family == AF_INET) {
-		struct sockaddr_in *sin = (struct sockaddr_in *)s;
-
-		if (len < sizeof(*sin))
-			return -1;
-
-		addr->inet.family = PR_AF_INET;
-		addr->inet.port = sin->sin_port;
-		memcpy(&addr->inet.ip, &sin->sin_addr, sizeof(addr->inet.ip));
-
-		return 0;
-	}
-#ifdef ENABLE_IPv6
-	else if (s->sa_family == PR_AF_INET6) {
-		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)s;
-
-		if (len < sizeof(*sin))
-			return -1;
-
-		addr->ipv6.family = PR_AF_INET6;
-		addr->ipv6.port = sin->sin6_port;
-		addr->ipv6.flowinfo = sin->sin6_flowinfo;
-		memcpy(&addr->ipv6.ip, &sin->sin6_addr, sizeof(addr->ipv6.ip));
-		addr->ipv6.scope_id = sin->sin6_scope_id;
-
-		return 0;
-	}
-#endif
-
-	return -1;
-}
-
-static int
-socket_connect(CamelTcpStream *stream, struct addrinfo *host)
-{
-	CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
-	PRNetAddr netaddr;
-	PRFileDesc *fd, *cancel_fd;
-
-	if (sockaddr_to_praddr(host->ai_addr, host->ai_addrlen, &netaddr) != 0) {
-		errno = EINVAL;
-		return -1;
-	}
-	
-	fd = PR_OpenTCPSocket(netaddr.raw.family);
-	if (fd == NULL) {
-		set_errno (PR_GetError ());
-		return -1;
-	}
-	
-	if (ssl->priv->ssl_mode) {
-		PRFileDesc *ssl_fd;
-		
-		ssl_fd = enable_ssl (ssl, fd);
-		if (ssl_fd == NULL) {
-			int errnosave;
-			
-			set_errno (PR_GetError ());
-			errnosave = errno;
-			PR_Close (fd);
-			errno = errnosave;
-			
-			return -1;
-		}
-		
-		fd = ssl_fd;
-	}
-
-	cancel_fd = camel_operation_cancel_prfd(NULL);
-
-	if (PR_Connect (fd, &netaddr, cancel_fd?0:CONNECT_TIMEOUT) == PR_FAILURE) {
-		int errnosave;
-		
-		set_errno (PR_GetError ());
-		if (errno == EINPROGRESS || (cancel_fd && errno == ETIMEDOUT)) {
-			gboolean connected = FALSE;
-			PRPollDesc poll[2];
-
-			poll[0].fd = fd;
-			poll[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
-			poll[1].fd = cancel_fd;
-			poll[1].in_flags = PR_POLL_READ;
-			
-			do {
-				poll[0].out_flags = 0;
-				poll[1].out_flags = 0;
-
-				if (PR_Poll (poll, cancel_fd?2:1, CONNECT_TIMEOUT) == PR_FAILURE) {
-					set_errno (PR_GetError ());
-					goto exception;
-				}
-				
-				if (poll[1].out_flags == PR_POLL_READ) {
-					errno = EINTR;
-					goto exception;
-				}
-
-				if (PR_ConnectContinue(fd, poll[0].out_flags) == PR_FAILURE) {
-					set_errno (PR_GetError ());
-					if (errno != EINPROGRESS)
-						goto exception;
-				} else {
-					connected = TRUE;
-				}
-			} while (!connected);
-		} else {
-		exception:
-			errnosave = errno;
-			PR_Close (fd);
-			ssl->priv->sockfd = NULL;
-			errno = errnosave;
-			
-			return -1;
-		}
-		
-		errno = 0;
-	}
-	
-	ssl->priv->sockfd = fd;
-
-	return 0;
-}
-
-static int
-stream_connect(CamelTcpStream *stream, struct addrinfo *host)
-{
-	while (host) {
-		if (socket_connect(stream, host) == 0)
-			return 0;
-		host = host->ai_next;
-	}
-
-	return -1;
-}
-
-static int
-stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data)
-{
-	PRSocketOptionData sodata;
-	
-	memset ((void *) &sodata, 0, sizeof (sodata));
-	memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
-	
-	if (PR_GetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
-		return -1;
-	
-	memcpy ((void *) data, (void *) &sodata, sizeof (CamelSockOptData));
-	
-	return 0;
-}
-
-static int
-stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
-{
-	PRSocketOptionData sodata;
-	
-	memset ((void *) &sodata, 0, sizeof (sodata));
-	memcpy ((void *) &sodata, (void *) data, sizeof (CamelSockOptData));
-	
-	if (PR_SetSocketOption (((CamelTcpStreamSSL *)stream)->priv->sockfd, &sodata) == PR_FAILURE)
-		return -1;
-	
-	return 0;
-}
-
-static struct sockaddr *
-sockaddr_from_praddr(PRNetAddr *addr, socklen_t *len)
-{
-	/* We assume the ip addresses are the same size - they have to be anyway */
-
-	if (addr->raw.family == PR_AF_INET) {
-		struct sockaddr_in *sin = g_malloc0(sizeof(*sin));
-
-		sin->sin_family = AF_INET;
-		sin->sin_port = addr->inet.port;
-		memcpy(&sin->sin_addr, &addr->inet.ip, sizeof(sin->sin_addr));
-		*len = sizeof(*sin);
-
-		return (struct sockaddr *)sin;
-	}
-#ifdef ENABLE_IPv6
-	else if (addr->raw.family == PR_AF_INET6) {
-		struct sockaddr_in6 *sin = g_malloc0(sizeof(*sin));
-
-		sin->sin6_family = AF_INET6;
-		sin->sin6_port = addr->ipv6.port;
-		sin->sin6_flowinfo = addr->ipv6.flowinfo;
-		memcpy(&sin->sin6_addr, &addr->ipv6.ip, sizeof(sin->sin6_addr));
-		sin->sin6_scope_id = addr->ipv6.scope_id;
-		*len = sizeof(*sin);
-
-		return (struct sockaddr *)sin;		
-	}
-#endif
-
-	return NULL;
-}
-
-static struct sockaddr *
-stream_get_local_address(CamelTcpStream *stream, socklen_t *len)
-{
-	PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
-	PRNetAddr addr;
-	
-	if (PR_GetSockName(sockfd, &addr) != PR_SUCCESS)
-		return NULL;
-
-	return sockaddr_from_praddr(&addr, len);
-}
-
-static struct sockaddr *
-stream_get_remote_address (CamelTcpStream *stream, socklen_t *len)
-{
-	PRFileDesc *sockfd = CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd;
-	PRNetAddr addr;
-	
-	if (PR_GetPeerName(sockfd, &addr) != PR_SUCCESS)
-		return NULL;
-
-	return sockaddr_from_praddr(&addr, len);
-}
-
-#endif /* HAVE_NSS */
-- 
cgit