aboutsummaryrefslogtreecommitdiff
path: root/libsylph/ssl.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-12-12 10:02:57 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-12-12 10:02:57 +0000
commita8d64a7a84ace27e2a92cf571ee11a138ab37a0e (patch)
tree77bdd43c28dd45cdf0095a6db8cc4eee5c8b1b40 /libsylph/ssl.c
parent087fa7f20b75990b3a6d4ecf065845bf1d25c509 (diff)
implemented SSL certificate dialog.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1415 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph/ssl.c')
-rw-r--r--libsylph/ssl.c88
1 files changed, 80 insertions, 8 deletions
diff --git a/libsylph/ssl.c b/libsylph/ssl.c
index d2721276..7b3c5c17 100644
--- a/libsylph/ssl.c
+++ b/libsylph/ssl.c
@@ -1,6 +1,6 @@
/*
* LibSylph -- E-Mail client library
- * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -31,8 +31,13 @@
#include "utils.h"
#include "ssl.h"
-static SSL_CTX *ssl_ctx_SSLv23;
-static SSL_CTX *ssl_ctx_TLSv1;
+static SSL_CTX *ssl_ctx_SSLv23 = NULL;
+static SSL_CTX *ssl_ctx_TLSv1 = NULL;
+
+static GSList *trust_list = NULL;
+static GSList *reject_list = NULL;
+
+static SSLVerifyFunc verify_ui_func = NULL;
void ssl_init(void)
{
@@ -76,12 +81,25 @@ void ssl_init(void)
void ssl_done(void)
{
+ GSList *cur;
+
+ for (cur = trust_list; cur != NULL; cur = cur->next)
+ X509_free((X509 *)cur->data);
+ g_slist_free(trust_list);
+ trust_list = NULL;
+ for (cur = reject_list; cur != NULL; cur = cur->next)
+ X509_free((X509 *)cur->data);
+ g_slist_free(reject_list);
+ reject_list = NULL;
+
if (ssl_ctx_SSLv23) {
SSL_CTX_free(ssl_ctx_SSLv23);
+ ssl_ctx_SSLv23 = NULL;
}
if (ssl_ctx_TLSv1) {
SSL_CTX_free(ssl_ctx_TLSv1);
+ ssl_ctx_TLSv1 = NULL;
}
}
@@ -90,6 +108,14 @@ gboolean ssl_init_socket(SockInfo *sockinfo)
return ssl_init_socket_with_method(sockinfo, SSL_METHOD_SSLv23);
}
+static gint x509_cmp_func(gconstpointer a, gconstpointer b)
+{
+ const X509 *xa = a;
+ const X509 *xb = b;
+
+ return X509_issuer_and_serial_cmp(xa, xb);
+}
+
gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method)
{
X509 *server_cert;
@@ -158,14 +184,55 @@ gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method)
}
verify_result = SSL_get_verify_result(sockinfo->ssl);
- if (verify_result == X509_V_OK)
+ if (verify_result == X509_V_OK) {
debug_print("SSL verify OK\n");
- else
- g_warning("%s: SSL certificate verify failed (%ld: %s)\n",
- sockinfo->hostname, verify_result,
- X509_verify_cert_error_string(verify_result));
+ X509_free(server_cert);
+ return TRUE;
+ } else if (g_slist_find_custom(trust_list, server_cert,
+ x509_cmp_func)) {
+ log_message("SSL certificate of %s previously accepted\n", sockinfo->hostname);
+ X509_free(server_cert);
+ return TRUE;
+ } else if (g_slist_find_custom(reject_list, server_cert,
+ x509_cmp_func)) {
+ log_message("SSL certificate of %s previously rejected\n", sockinfo->hostname);
+ X509_free(server_cert);
+ return FALSE;
+ }
+
+ g_warning("%s: SSL certificate verify failed (%ld: %s)\n",
+ sockinfo->hostname, verify_result,
+ X509_verify_cert_error_string(verify_result));
+
+ if (verify_ui_func) {
+ gint res;
+
+ res = verify_ui_func(sockinfo, sockinfo->hostname,
+ server_cert, verify_result);
+ /* 0: accept 1: temporarily accept -1: reject */
+ if (res < 0) {
+ debug_print("SSL certificate of %s rejected\n",
+ sockinfo->hostname);
+ reject_list = g_slist_prepend
+ (reject_list, X509_dup(server_cert));
+ X509_free(server_cert);
+ return FALSE;
+ } else if (res > 0) {
+ debug_print("Temporarily accept SSL certificate of %s\n", sockinfo->hostname);
+ trust_list = g_slist_prepend
+ (trust_list, X509_dup(server_cert));
+ } else {
+ debug_print("Permanently accept SSL certificate of %s\n", sockinfo->hostname);
+ trust_list = g_slist_prepend
+ (trust_list, X509_dup(server_cert));
+ }
+ }
X509_free(server_cert);
+ } else {
+ g_warning("%s: couldn't get SSL certificate\n",
+ sockinfo->hostname);
+ return FALSE;
}
return TRUE;
@@ -178,4 +245,9 @@ void ssl_done_socket(SockInfo *sockinfo)
}
}
+void ssl_set_verify_func(SSLVerifyFunc func)
+{
+ verify_ui_func = func;
+}
+
#endif /* USE_SSL */