[Commits] [SCM] claws branch, master, updated. 3.10.0-9-g78965aa
colin at claws-mail.org
colin at claws-mail.org
Wed May 28 21:19:42 CEST 2014
The branch master of project "claws" (Claws Mail) has been updated
via 78965aa3b773324d9c1102d686e533379debd149 (commit)
from 7c1bb13b902e8974b364a6e92d88e48c3a2fdcd0 (commit)
- Log -----------------------------------------------------------------
commit 78965aa3b773324d9c1102d686e533379debd149
Author: Colin Leroy <colin at colino.net>
Date: Wed May 28 21:18:34 2014 +0200
Add a per-account preference to allow automatically accepting unknown
and changed SSL certificates, if they're valid (that is, if the root CA
is trusted by the distro).
diff --git a/src/common/session.c b/src/common/session.c
index 25038c9..f1af55b 100644
--- a/src/common/session.c
+++ b/src/common/session.c
@@ -165,6 +165,8 @@ static gint session_connect_cb(SockInfo *sock, gpointer data)
session->sock = sock;
sock->account = session->account;
sock->is_smtp = session->is_smtp;
+ sock->ssl_cert_auto_accept = session->ssl_cert_auto_accept;
+
#ifdef USE_GNUTLS
sock->gnutls_priority = session->gnutls_priority;
@@ -373,6 +375,8 @@ gint session_start_tls(Session *session)
nb_mode = sock_is_nonblocking_mode(session->sock);
+ session->sock->ssl_cert_auto_accept = session->ssl_cert_auto_accept;
+
if (nb_mode)
sock_set_nonblocking_mode(session->sock, FALSE);
diff --git a/src/common/session.h b/src/common/session.h
index 00675c4..98ae50e 100644
--- a/src/common/session.h
+++ b/src/common/session.h
@@ -150,10 +150,10 @@ struct _Session
gpointer recv_data_notify_data;
gpointer send_data_progressive_notify_data;
gpointer send_data_notify_data;
-
+
const void *account;
gboolean is_smtp;
-
+ gboolean ssl_cert_auto_accept;
gint ping_tag;
#ifdef USE_GNUTLS
diff --git a/src/common/socket.h b/src/common/socket.h
index 39c6e2e..59cb230 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -76,9 +76,10 @@ struct _SockInfo
SockFunc callback;
GIOCondition condition;
gchar *canonical_name;
-
+
const void *account;
gboolean is_smtp;
+ gboolean ssl_cert_auto_accept;
};
void refresh_resolvers (void);
diff --git a/src/common/ssl.c b/src/common/ssl.c
index b1812f9..1c7c335 100644
--- a/src/common/ssl.c
+++ b/src/common/ssl.c
@@ -371,7 +371,8 @@ gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method)
return FALSE;
}
- if (!ssl_certificate_check_chain(certs, cert_list_length, sockinfo->hostname, sockinfo->port)) {
+ if (!ssl_certificate_check_chain(certs, cert_list_length, sockinfo->hostname, sockinfo->port,
+ sockinfo->ssl_cert_auto_accept)) {
for (i = 0; i < cert_list_length; i++)
gnutls_x509_crt_deinit(certs[i]);
g_free(certs);
diff --git a/src/common/ssl_certificate.c b/src/common/ssl_certificate.c
index b48d4d4..870ceb0 100644
--- a/src/common/ssl_certificate.c
+++ b/src/common/ssl_certificate.c
@@ -603,6 +603,17 @@ static guint check_cert(SSLCertificate *cert)
}
+static gboolean ssl_certificate_is_valid(SSLCertificate *cert, guint status)
+{
+ gchar *str_status = ssl_certificate_check_signer(cert, status);
+
+ if (str_status != NULL) {
+ g_free(str_status);
+ return FALSE;
+ }
+ return ssl_certificate_check_subject_cn(cert);
+}
+
char *ssl_certificate_check_signer (SSLCertificate *cert, guint status)
{
gnutls_x509_crt_t x509_cert = cert ? cert->x509_cert : NULL;
@@ -667,17 +678,20 @@ static void ssl_certificate_save_chain(gnutls_x509_crt_t *certs, gint len, const
fclose(fp);
}
-gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const gchar *host, gushort port)
+gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status,
+ const gchar *host, gushort port,
+ gboolean accept_if_valid)
{
SSLCertificate *current_cert = NULL;
SSLCertificate *known_cert;
SSLCertHookData cert_hook_data;
gchar *fingerprint;
size_t n;
- unsigned char md[128];
+ unsigned char md[128];
+ gboolean valid = FALSE;
current_cert = ssl_certificate_new(x509_cert, host, port);
-
+
if (current_cert == NULL) {
debug_print("Buggy certificate !\n");
return FALSE;
@@ -693,14 +707,25 @@ gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const
g_free(fingerprint);
+ if (accept_if_valid)
+ valid = ssl_certificate_is_valid(current_cert, status);
+ else
+ valid = FALSE; /* Force check */
+
if (known_cert == NULL) {
+ if (valid) {
+ ssl_certificate_save(current_cert);
+ ssl_certificate_destroy(current_cert);
+ return TRUE;
+ }
+
cert_hook_data.cert = current_cert;
cert_hook_data.old_cert = NULL;
cert_hook_data.expired = FALSE;
cert_hook_data.accept = FALSE;
-
+
hooks_invoke(SSLCERT_ASK_HOOKLIST, &cert_hook_data);
-
+
if (!cert_hook_data.accept) {
ssl_certificate_destroy(current_cert);
return FALSE;
@@ -710,11 +735,18 @@ gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const
return TRUE;
}
} else if (!ssl_certificate_compare (current_cert, known_cert)) {
+ if (valid) {
+ ssl_certificate_save(current_cert);
+ ssl_certificate_destroy(current_cert);
+ ssl_certificate_destroy(known_cert);
+ return TRUE;
+ }
+
cert_hook_data.cert = current_cert;
cert_hook_data.old_cert = known_cert;
cert_hook_data.expired = FALSE;
cert_hook_data.accept = FALSE;
-
+
hooks_invoke(SSLCERT_ASK_HOOKLIST, &cert_hook_data);
if (!cert_hook_data.accept) {
@@ -729,22 +761,22 @@ gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const
}
} else if (gnutls_x509_crt_get_expiration_time(current_cert->x509_cert) < time(NULL)) {
gchar *tmp = g_strdup_printf("%s:%d", current_cert->host, current_cert->port);
-
+
if (warned_expired == NULL)
warned_expired = g_hash_table_new(g_str_hash, g_str_equal);
-
+
if (g_hash_table_lookup(warned_expired, tmp)) {
g_free(tmp);
ssl_certificate_destroy(current_cert);
ssl_certificate_destroy(known_cert);
return TRUE;
}
-
+
cert_hook_data.cert = current_cert;
cert_hook_data.old_cert = NULL;
cert_hook_data.expired = TRUE;
cert_hook_data.accept = FALSE;
-
+
hooks_invoke(SSLCERT_ASK_HOOKLIST, &cert_hook_data);
if (!cert_hook_data.accept) {
@@ -765,7 +797,9 @@ gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const
return TRUE;
}
-gboolean ssl_certificate_check_chain(gnutls_x509_crt_t *certs, gint chain_len, const gchar *host, gushort port)
+gboolean ssl_certificate_check_chain(gnutls_x509_crt_t *certs, gint chain_len,
+ const gchar *host, gushort port,
+ gboolean accept_if_valid)
{
int ncas = 0;
gnutls_x509_crt_t *cas = NULL;
@@ -798,7 +832,8 @@ gboolean ssl_certificate_check_chain(gnutls_x509_crt_t *certs, gint chain_len, c
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
&status);
- result = ssl_certificate_check(certs[0], status, host, port);
+ result = ssl_certificate_check(certs[0], status, host, port,
+ accept_if_valid);
if (result == TRUE) {
ssl_certificate_save_chain(certs, chain_len, host, port);
diff --git a/src/common/ssl_certificate.h b/src/common/ssl_certificate.h
index 9f4ecf0..7089472 100644
--- a/src/common/ssl_certificate.h
+++ b/src/common/ssl_certificate.h
@@ -57,8 +57,8 @@ struct _SSLCertHookData
};
SSLCertificate *ssl_certificate_find (const gchar *host, gushort port, const gchar *fingerprint);
-gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const gchar *host, gushort port);
-gboolean ssl_certificate_check_chain(gnutls_x509_crt_t *certs, gint chain_len, const gchar *host, gushort port);
+gboolean ssl_certificate_check (gnutls_x509_crt_t x509_cert, guint status, const gchar *host, gushort port, gboolean accept_if_valid);
+gboolean ssl_certificate_check_chain(gnutls_x509_crt_t *certs, gint chain_len, const gchar *host, gushort port, gboolean accept_if_valid);
void ssl_certificate_destroy(SSLCertificate *cert);
void ssl_certificate_delete_from_disk(SSLCertificate *cert);
char * readable_fingerprint(unsigned char *src, int len);
diff --git a/src/compose.c b/src/compose.c
index a13e4ea..7833804 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -11565,7 +11565,7 @@ gboolean compose_close(Compose *compose)
}
return TRUE;
}
-
+
if (compose->draft_timeout_tag >= 0) {
g_source_remove(compose->draft_timeout_tag);
compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN;
diff --git a/src/etpan/etpan-ssl.c b/src/etpan/etpan-ssl.c
index f99955b..529bc30 100644
--- a/src/etpan/etpan-ssl.c
+++ b/src/etpan/etpan-ssl.c
@@ -40,7 +40,8 @@
#include "log.h"
#include "prefs_account.h"
-gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port)
+gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port,
+ gboolean accept_if_valid)
{
#if (!defined LIBETPAN_API_CURRENT || LIBETPAN_API_CURRENT < 18)
unsigned char *cert_der = NULL;
@@ -69,7 +70,7 @@ gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port
free(tmp.data);
g_warning("IMAP: can't get cert\n");
return FALSE;
- } else if (ssl_certificate_check(cert, (guint)-1, host, port) == TRUE) {
+ } else if (ssl_certificate_check(cert, (guint)-1, host, port, accept_if_valid) == TRUE) {
free(tmp.data);
gnutls_x509_crt_deinit(cert);
return TRUE;
@@ -121,7 +122,8 @@ gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port
carray_free(certs_der);
if (result == TRUE)
- result = ssl_certificate_check_chain(certs, chain_len, host, port);
+ result = ssl_certificate_check_chain(certs, chain_len, host, port,
+ accept_if_valid);
for (i = 0; i < chain_len; i++)
gnutls_x509_crt_deinit(certs[i]);
diff --git a/src/etpan/etpan-ssl.h b/src/etpan/etpan-ssl.h
index 5607d1a..adb8f9d 100644
--- a/src/etpan/etpan-ssl.h
+++ b/src/etpan/etpan-ssl.h
@@ -31,7 +31,7 @@
#include <libetpan/libetpan.h>
-gboolean etpan_certificate_check(mailstream *imap_stream, const char *host, gint port);
+gboolean etpan_certificate_check(mailstream *imap_stream, const char *host, gint port, gboolean accept_if_valid);
void etpan_connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, void * data);
#endif /* USE_GNUTLS */
diff --git a/src/etpan/imap-thread.c b/src/etpan/imap-thread.c
index 179f352..be7dca5 100644
--- a/src/etpan/imap-thread.c
+++ b/src/etpan/imap-thread.c
@@ -544,11 +544,12 @@ int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
chashdatum key;
chashdatum value;
mailimap * imap, * oldimap;
-
+ gboolean accept_if_valid = FALSE;
+
oldimap = get_imap(folder);
imap = mailimap_new(0, NULL);
-
+
if (oldimap) {
debug_print("deleting old imap %p\n", oldimap);
delete_imap(folder, oldimap);
@@ -559,22 +560,26 @@ int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
value.data = imap;
value.len = 0;
chash_set(session_hash, &key, &value, NULL);
-
+
param.imap = imap;
param.server = server;
param.port = port;
param.account = folder->account;
+ if (folder->account)
+ accept_if_valid = folder->account->ssl_certs_auto_accept;
+
refresh_resolvers();
threaded_run(folder, ¶m, &result, connect_ssl_run);
if ((result.error == MAILIMAP_NO_ERROR_AUTHENTICATED ||
result.error == MAILIMAP_NO_ERROR_NON_AUTHENTICATED) && !etpan_skip_ssl_cert_check) {
- if (etpan_certificate_check(imap->imap_stream, server, port) != TRUE)
+ if (etpan_certificate_check(imap->imap_stream, server, port,
+ accept_if_valid) != TRUE)
result.error = MAILIMAP_ERROR_SSL;
}
debug_print("connect %d with imap %p\n", result.error, imap);
-
+
return result.error;
}
@@ -1094,20 +1099,25 @@ int imap_threaded_starttls(Folder * folder, const gchar *host, int port)
{
struct connect_param param;
struct starttls_result result;
-
+ gboolean accept_if_valid = FALSE;
+
debug_print("imap starttls - begin\n");
-
+
param.imap = get_imap(folder);
param.server = host;
param.port = port;
param.account = folder->account;
+ if (folder->account)
+ accept_if_valid = folder->account->ssl_certs_auto_accept;
+
threaded_run(folder, ¶m, &result, starttls_run);
-
+
debug_print("imap starttls - end\n");
if (result.error == 0 && param.imap && !etpan_skip_ssl_cert_check) {
- if (etpan_certificate_check(param.imap->imap_stream, host, port) != TRUE)
+ if (etpan_certificate_check(param.imap->imap_stream, host, port,
+ accept_if_valid) != TRUE)
return MAILIMAP_ERROR_SSL;
}
return result.error;
diff --git a/src/etpan/nntp-thread.c b/src/etpan/nntp-thread.c
index 7708d31..b721e61 100644
--- a/src/etpan/nntp-thread.c
+++ b/src/etpan/nntp-thread.c
@@ -398,11 +398,12 @@ int nntp_threaded_connect_ssl(Folder * folder, const char * server, int port)
chashdatum key;
chashdatum value;
newsnntp * nntp, * oldnntp;
-
+ gboolean accept_if_valid = FALSE;
+
oldnntp = get_nntp(folder);
nntp = newsnntp_new(0, NULL);
-
+
if (oldnntp) {
debug_print("deleting old nntp %p\n", oldnntp);
delete_nntp(folder, oldnntp);
@@ -413,17 +414,21 @@ int nntp_threaded_connect_ssl(Folder * folder, const char * server, int port)
value.data = nntp;
value.len = 0;
chash_set(session_hash, &key, &value, NULL);
-
+
param.nntp = nntp;
param.server = server;
param.port = port;
param.account = folder->account;
+ if (folder->account)
+ accept_if_valid = folder->account->ssl_certs_auto_accept;
+
refresh_resolvers();
threaded_run(folder, ¶m, &result, connect_ssl_run);
if (result.error == NEWSNNTP_NO_ERROR && !etpan_skip_ssl_cert_check) {
- if (etpan_certificate_check(nntp->nntp_stream, server, port) != TRUE)
+ if (etpan_certificate_check(nntp->nntp_stream, server, port,
+ accept_if_valid) != TRUE)
return -1;
}
debug_print("connect %d with nntp %p\n", result.error, nntp);
diff --git a/src/pop.c b/src/pop.c
index a9a0472..2f7eed7 100644
--- a/src/pop.c
+++ b/src/pop.c
@@ -530,7 +530,7 @@ Session *pop3_session_new(PrefsAccount *account)
SESSION(session)->recv_msg = pop3_session_recv_msg;
SESSION(session)->recv_data_finished = pop3_session_recv_data_finished;
SESSION(session)->send_data_finished = NULL;
-
+ SESSION(session)->ssl_cert_auto_accept = account->ssl_certs_auto_accept;
SESSION(session)->destroy = pop3_session_destroy;
session->state = POP3_READY;
diff --git a/src/prefs_account.c b/src/prefs_account.c
index 9163800..a03f500 100644
--- a/src/prefs_account.c
+++ b/src/prefs_account.c
@@ -269,6 +269,7 @@ typedef struct SSLPage
GtkWidget *entry_out_cert_file;
GtkWidget *entry_out_cert_pass;
+ GtkWidget *ssl_certs_auto_accept_checkbtn;
GtkWidget *use_nonblocking_ssl_checkbtn;
} SSLPage;
@@ -729,6 +730,10 @@ static PrefParam ssl_param[] = {
prefs_account_enum_set_data_from_radiobtn,
prefs_account_enum_set_radiobtn},
+ {"ssl_certs_auto_accept", "0", &tmp_ac_prefs.ssl_certs_auto_accept, P_BOOL,
+ &ssl_page.ssl_certs_auto_accept_checkbtn,
+ prefs_set_data_from_toggle, prefs_set_toggle},
+
{"use_nonblocking_ssl", "1", &tmp_ac_prefs.use_nonblocking_ssl, P_BOOL,
&ssl_page.use_nonblocking_ssl_checkbtn,
prefs_set_data_from_toggle, prefs_set_toggle},
@@ -769,6 +774,9 @@ static PrefParam ssl_param[] = {
{"out_ssl_client_cert_pass", "", &tmp_ac_prefs.out_ssl_client_cert_pass, P_PASSWORD,
NULL, NULL, NULL},
+ {"ssl_certs_auto_accept", "0", &tmp_ac_prefs.ssl_certs_auto_accept, P_BOOL,
+ NULL, NULL, NULL},
+
{"use_nonblocking_ssl", "1", &tmp_ac_prefs.use_nonblocking_ssl, P_BOOL,
NULL, NULL, NULL},
#endif /* USE_GNUTLS */
@@ -2413,6 +2421,7 @@ static void ssl_create_widget_func(PrefsPage * _page,
GtkWidget *entry_out_cert_pass;
GtkWidget *vbox7;
+ GtkWidget *ssl_certs_auto_accept_checkbtn;
GtkWidget *use_nonblocking_ssl_checkbtn;
GtkWidget *hbox;
GtkWidget *hbox_spc;
@@ -2545,6 +2554,9 @@ static void ssl_create_widget_func(PrefsPage * _page,
gtk_widget_show (vbox7);
gtk_box_pack_start (GTK_BOX (vbox1), vbox7, FALSE, FALSE, 0);
+ PACK_CHECK_BUTTON(vbox7, ssl_certs_auto_accept_checkbtn,
+ _("Automatically accept unknown valid SSL certificates"));
+
PACK_CHECK_BUTTON(vbox7, use_nonblocking_ssl_checkbtn,
_("Use non-blocking SSL"));
@@ -2587,6 +2599,7 @@ static void ssl_create_widget_func(PrefsPage * _page,
page->entry_out_cert_file = entry_out_cert_file;
page->entry_out_cert_pass = entry_out_cert_pass;
+ page->ssl_certs_auto_accept_checkbtn = ssl_certs_auto_accept_checkbtn;
page->use_nonblocking_ssl_checkbtn = use_nonblocking_ssl_checkbtn;
tmp_ac_prefs = *ac_prefs;
diff --git a/src/prefs_account.h b/src/prefs_account.h
index 40b9301..dd118c4 100644
--- a/src/prefs_account.h
+++ b/src/prefs_account.h
@@ -86,6 +86,7 @@ struct _PrefsAccount
gchar *in_ssl_client_cert_file;
gchar *in_ssl_client_cert_pass;
+ gboolean ssl_certs_auto_accept;
gboolean use_nonblocking_ssl;
/* Receive */
diff --git a/src/send_message.c b/src/send_message.c
index d51994d..80c0fb7 100644
--- a/src/send_message.c
+++ b/src/send_message.c
@@ -250,6 +250,8 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
if (!ac_prefs->session) {
/* we can't reuse a previously initialised session */
session = smtp_session_new(ac_prefs);
+ session->ssl_cert_auto_accept = ac_prefs->ssl_certs_auto_accept;
+
smtp_session = SMTP_SESSION(session);
if (ac_prefs->set_domain && ac_prefs->domain && strlen(ac_prefs->domain)) {
-----------------------------------------------------------------------
Summary of changes:
src/common/session.c | 4 +++
src/common/session.h | 4 +--
src/common/socket.h | 3 ++-
src/common/ssl.c | 3 ++-
src/common/ssl_certificate.c | 59 +++++++++++++++++++++++++++++++++---------
src/common/ssl_certificate.h | 4 +--
src/compose.c | 2 +-
src/etpan/etpan-ssl.c | 8 +++---
src/etpan/etpan-ssl.h | 2 +-
src/etpan/imap-thread.c | 28 +++++++++++++-------
src/etpan/nntp-thread.c | 13 +++++++---
src/pop.c | 2 +-
src/prefs_account.c | 13 ++++++++++
src/prefs_account.h | 1 +
src/send_message.c | 2 ++
15 files changed, 111 insertions(+), 37 deletions(-)
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list