summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@ximian.com>2001-01-16 07:19:49 +0000
committerJeffrey Stedfast <fejj@src.gnome.org>2001-01-16 07:19:49 +0000
commit35782d7a57f28ed5f1650a026e4acbde6088c5ec (patch)
treecba030c486c5f70a21c450fa73e1d3bab15ab917
parentfc27855d5c99a07ae00f83730c01fd5a80d5c9dc (diff)
downloadevolution-data-server-35782d7a57f28ed5f1650a026e4acbde6088c5ec.tar.gz
Ugh, this design is ugly like my butt.
2001-01-16 Jeffrey Stedfast <fejj@ximian.com> Ugh, this design is ugly like my butt. * camel-session.c (camel_session_query_cert_authenticator): New function which will be useful when we integrate SSL. * camel-tcp-stream-ssl.c (ssl_auth_cert): Callback to authenticate a certificate. (ssl_bad_cert): Callback that gets the reason the certificate is bad and then calls camel's cert-authenticator callback to notify the user and to allow the user to override the check. (stream_connect): Set the URL we expect to connect with and setup the auth_cert and bad_cert callbacks. (camel_tcp_stream_ssl_new): Now takes a CamelSession and a expected_host argument that it will use for certificate authentication. (camel_tcp_stream_ssl_finalize): Unref the session and free the expected_host.
-rw-r--r--camel/ChangeLog20
-rw-r--r--camel/camel-session.c25
-rw-r--r--camel/camel-session.h14
-rw-r--r--camel/camel-tcp-stream-ssl.c56
-rw-r--r--camel/camel-tcp-stream-ssl.h9
-rw-r--r--camel/providers/imap/camel-imap-store.c2
6 files changed, 121 insertions, 5 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 036bb7572..02b3e967d 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,23 @@
+2001-01-16 Jeffrey Stedfast <fejj@ximian.com>
+
+ Ugh, this design is ugly like my butt.
+
+ * camel-session.c (camel_session_query_cert_authenticator): New
+ function which will be useful when we integrate SSL.
+
+ * camel-tcp-stream-ssl.c (ssl_auth_cert): Callback to authenticate
+ a certificate.
+ (ssl_bad_cert): Callback that gets the reason the certificate is
+ bad and then calls camel's cert-authenticator callback to notify
+ the user and to allow the user to override the check.
+ (stream_connect): Set the URL we expect to connect with and setup
+ the auth_cert and bad_cert callbacks.
+ (camel_tcp_stream_ssl_new): Now takes a CamelSession and a
+ expected_host argument that it will use for certificate
+ authentication.
+ (camel_tcp_stream_ssl_finalize): Unref the session and free the
+ expected_host.
+
2001-01-16 Not Zed <NotZed@Ximian.com>
* camel-folder-summary.c (camel_folder_summary_decode_string):
diff --git a/camel/camel-session.c b/camel/camel-session.c
index d834bad54..1c3f10861 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -436,6 +436,31 @@ camel_session_query_authenticator (CamelSession *session,
service, item, ex);
}
+#ifdef U_CANT_TOUCH_THIS
+/**
+ * camel_session_query_cert_authenticator:
+ * @session: session object
+ * @prompt: prompt to query user with
+ *
+ * This function is used by SSL to discuss certificate authentication
+ * information with the application and/or user. Allows the user to
+ * override the SSL certificate authenticator, which, at this point,
+ * must have failed to authenticate the server.
+ *
+ * UI should be a Yes/No prompt probably defaulting to No.
+ *
+ * Return value: TRUE if the user decides that the SSL connection
+ * should continue with the untrusted server or FALSE otherwise.
+ **/
+gboolean
+camel_session_query_cert_authenticator (CamelSession *session,
+ char *prompt)
+{
+ return session->cert_authenticator (prompt);
+}
+#endif /* U_CANT_TOUCH_THIS */
+
+
/**
* camel_session_register_timeout: Register a timeout to be called
* periodically.
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 9ae9eec08..d740830d7 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -51,6 +51,12 @@ typedef char *(*CamelAuthCallback) (CamelAuthCallbackMode mode,
char *data, gboolean secret,
CamelService *service, char *item,
CamelException *ex);
+
+#ifdef U_CANT_TOUCH_THIS
+/* this is just a guess as to what we'll actually need */
+typedef gboolean (*CamelBadCertCallback) (char *data);
+#endif
+
typedef gboolean (*CamelTimeoutCallback) (gpointer data);
typedef guint (*CamelTimeoutRegisterCallback) (guint32 interval,
CamelTimeoutCallback cb,
@@ -64,6 +70,9 @@ struct _CamelSession
char *storage_path;
CamelAuthCallback authenticator;
+#ifdef U_CANT_TOUCH_THIS
+ CamelBadCertCallback cert_authenticator;
+#endif
CamelTimeoutRegisterCallback registrar;
CamelTimeoutRemoveCallback remover;
@@ -118,6 +127,11 @@ char * camel_session_query_authenticator (CamelSession *session,
char *item,
CamelException *ex);
+#ifdef U_CANT_TOUCH_THIS
+gboolean camel_session_query_cert_authenticator (CamelSession *session,
+ char *prompt);
+#endif
+
guint camel_session_register_timeout (CamelSession *session,
guint32 interval,
CamelTimeoutCallback callback,
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 42255562b..e9afb768b 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -44,6 +44,12 @@ static int stream_connect (CamelTcpStream *stream, struct hostent *host, int
static int stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
+/* callbacks */
+
+static SECStatus ssl_bad_cert (void *data, PRFileDesc *fd);
+static SECStatus ssl_auth_cert (void *data, PRFileDesc *fd, PRBool checksig, PRBool is_server);
+
+
static void
camel_tcp_stream_ssl_class_init (CamelTcpStreamSSLClass *camel_tcp_stream_ssl_class)
{
@@ -71,6 +77,8 @@ camel_tcp_stream_ssl_init (gpointer object, gpointer klass)
CamelTcpStreamSSL *stream = CAMEL_TCP_STREAM_SSL (object);
stream->sockfd = NULL;
+ stream->session = NULL;
+ stream->expected_host = NULL;
}
static void
@@ -80,6 +88,9 @@ camel_tcp_stream_ssl_finalize (CamelObject *object)
if (stream->sockfd != NULL)
PR_Close (stream->sockfd);
+
+ camel_object_unref (CAMEL_OBJECT (stream->session));
+ g_free (stream->expected_host);
}
@@ -105,16 +116,26 @@ camel_tcp_stream_ssl_get_type (void)
/**
* camel_tcp_stream_ssl_new:
+ * @session: camel session
+ * @expected_host: host that the stream is expected to connect with.
+ *
+ * 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 tcp stream
**/
CamelStream *
-camel_tcp_stream_ssl_new ()
+camel_tcp_stream_ssl_new (CamelSession *session, const char *expected_host)
{
CamelTcpStreamSSL *stream;
stream = CAMEL_TCP_STREAM_SSL (camel_object_new (camel_tcp_stream_ssl_get_type ()));
+ camel_object_ref (CAMEL_OBJECT (session));
+ stream->session = session;
+ stream->expected_host = g_strdup (expected_host);
+
return CAMEL_STREAM (stream);
}
@@ -167,6 +188,34 @@ stream_close (CamelStream *stream)
}
+static SECStatus
+ssl_auth_cert (void *data, PRFileDesc *fd, PRBool checksig, PRBool is_server)
+{
+ return SSL_AuthCertificate (NULL, fd, TRUE, FALSE);
+}
+
+static SECStatus
+ssl_bad_cert (void *data, PRFileDesc *fd)
+{
+ CamelSession *session;
+ char *string;
+ PRInt32 len;
+
+ g_return_val_if_fail (data != NULL, SECFailure);
+ g_return_val_if_fail (CAMEL_IS_SESSION (data), SECFailure);
+
+ /* FIXME: International issues here?? */
+ len = PR_GetErrorTextLen (PR_GetError ());
+ string = g_malloc0 (len);
+ PR_GetErrorText (string);
+
+ session = CAMEL_SESSION (data);
+ if (camel_session_query_cert_authenticator (session, string))
+ return SECSuccess;
+
+ return SECFailure;
+}
+
static int
stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
{
@@ -186,6 +235,8 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
fd = PR_OpenTCPSocket (host->h_addrtype);
ssl_fd = SSL_ImportFD (NULL, fd);
+ SSL_SetUrl (ssl_fd, ssl->expected_host);
+
if (ssl_fd == NULL || PR_Connect (ssl_fd, &netaddr, timeout) == PR_FAILURE) {
if (ssl_fd != NULL)
PR_Close (ssl_fd);
@@ -193,6 +244,9 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
return -1;
}
+ SSL_AuthCertificateHook (ssl_fd, ssl_auth_cert, NULL);
+ SSL_BadCertHook (ssl_fd, ssl_bad_cert, ssl->session);
+
ssl->sockfd = ssl_fd;
return 0;
diff --git a/camel/camel-tcp-stream-ssl.h b/camel/camel-tcp-stream-ssl.h
index 2e7ad343a..de6eb1a8b 100644
--- a/camel/camel-tcp-stream-ssl.h
+++ b/camel/camel-tcp-stream-ssl.h
@@ -31,8 +31,8 @@ extern "C" {
#endif /* __cplusplus */
#include <camel/camel-tcp-stream.h>
-#include <mozilla/nsprpub/prio.h>
-#include <mozilla/nsprpub/prnetdb.h>
+#include <camel/camel-session.h>
+#include <nspr.h>
#define CAMEL_TCP_STREAM_SSL_TYPE (camel_tcp_stream_ssl_get_type ())
#define CAMEL_TCP_STREAM_SSL(obj) (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_SSL_TYPE, CamelTcpStreamSSL))
@@ -44,6 +44,9 @@ struct _CamelTcpStreamSSL
CamelTcpStream parent_object;
PRFileDesc *sockfd;
+
+ CamelSession *session;
+ char *expected_host;
};
typedef struct {
@@ -57,7 +60,7 @@ typedef struct {
CamelType camel_tcp_stream_ssl_get_type (void);
/* public methods */
-CamelStream *camel_tcp_stream_ssl_new (void);
+CamelStream *camel_tcp_stream_ssl_new (CamelSession *session, const char *expected_host);
#ifdef __cplusplus
}
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 275270ecb..9d6412eef 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -313,7 +313,7 @@ static gboolean
imap_connect (CamelService *service, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelSession *session = camel_service_get_session (CAMEL_SERVICE (store));
+ CamelSession *session = camel_service_get_session (service);
char *result, *errbuf = NULL, *name;
CamelImapResponse *response;
gboolean authenticated = FALSE;