diff options
-rw-r--r-- | camel/ChangeLog | 20 | ||||
-rw-r--r-- | camel/camel-session.c | 25 | ||||
-rw-r--r-- | camel/camel-session.h | 14 | ||||
-rw-r--r-- | camel/camel-tcp-stream-ssl.c | 56 | ||||
-rw-r--r-- | camel/camel-tcp-stream-ssl.h | 9 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 2 |
6 files changed, 121 insertions, 5 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 036bb75729..02b3e967d7 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 d834bad54c..1c3f108616 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 9ae9eec089..d740830d7e 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 42255562bc..e9afb768bc 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 2e7ad343a5..de6eb1a8bc 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 275270ecb6..9d6412eefa 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; |