[Commits] [SCM] claws branch, master, updated. 3.14.0-85-ga05eeae

ticho at claws-mail.org ticho at claws-mail.org
Sun Sep 18 10:50:03 CEST 2016


The branch, master has been updated
       via  a05eeae0e79999d34dd02d733fc83e9d04082b03 (commit)
      from  479b9dc2551d4e04b391231fa46f9e7ef853ac3d (commit)

Summary of changes:
 src/common/socket.h |    5 +++
 src/common/ssl.c    |   89 +++++++++++++++++++++++++++++++++++++++++++++++++--
 src/common/ssl.h    |    4 +++
 3 files changed, 95 insertions(+), 3 deletions(-)


- Log -----------------------------------------------------------------
commit a05eeae0e79999d34dd02d733fc83e9d04082b03
Author: Andrej Kacian <ticho at claws-mail.org>
Date:   Sun Sep 18 10:46:58 2016 +0200

    Fix using client TLS certificates for GnuTLS 3.0 and up.
    
    3.0 introduced new API for setting client certificates,
    gnutls_certificate_set_retrieve_function2().
    
    This fixes bug #3684.

diff --git a/src/common/socket.h b/src/common/socket.h
index fb20233..dc4c5b9 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -61,8 +61,13 @@ struct _SockInfo
 #if USE_GNUTLS
 	gnutls_session_t ssl;
 	gnutls_certificate_credentials_t xcred;
+#if GNUTLS_VERSION_NUMBER < 0x030000
 	gnutls_x509_crt_t client_crt;
 	gnutls_x509_privkey_t client_key;
+#else
+	gnutls_pcert_st client_crt;
+	gnutls_privkey_t client_key;
+#endif /* GNUTLS_VERSION_NUMBER < 0x030000 */
 	gchar *gnutls_priority;
 #endif
 	guint g_source;
diff --git a/src/common/ssl.c b/src/common/ssl.c
index 6649878..7637bf0 100644
--- a/src/common/ssl.c
+++ b/src/common/ssl.c
@@ -63,6 +63,10 @@ typedef struct _thread_data {
 #define DEFAULT_GNUTLS_PRIORITY "NORMAL"
 #endif
 
+#if GNUTLS_VERSION_NUMBER < 0x030000
+/* GnuTLS 3.0 introduced new API for certificate callback,
+ * gnutls_certificate_set_retrieve_function2() */
+
 #if GNUTLS_VERSION_NUMBER <= 0x020c00
 static int gnutls_client_cert_cb(gnutls_session_t session,
                                const gnutls_datum_t *req_ca_rdn, int nreqs,
@@ -73,7 +77,7 @@ static int gnutls_cert_cb(gnutls_session_t session,
                                const gnutls_datum_t *req_ca_rdn, int nreqs,
                                const gnutls_pk_algorithm_t *sign_algos,
                                int sign_algos_length, gnutls_retr2_st *st)
-#endif
+#endif /* GNUTLS_VERSION_NUMBER <= 0x020c00 */
 {
 	SSLClientCertHookData hookdata;
 	SockInfo *sockinfo = (SockInfo *)gnutls_session_get_ptr(session);
@@ -121,6 +125,72 @@ static int gnutls_cert_cb(gnutls_session_t session,
 	return 0;
 }
 
+#else /* GNUTLS_VERSION_NUMBER < 0x030000 */
+
+static int gnutls_cert_cb(gnutls_session_t session,
+		const gnutls_datum_t *req_ca_rdn,
+		int nreqs,
+		const gnutls_pk_algorithm_t *pk_algos,
+		int pk_algos_length,
+		gnutls_pcert_st **pcert,
+		unsigned int *pcert_length,
+		gnutls_privkey_t *privkey)
+{
+	SSLClientCertHookData hookdata;
+	SockInfo *sockinfo = (SockInfo *)gnutls_session_get_ptr(session);
+	gnutls_datum_t tmp;
+	int r;
+
+	hookdata.account = sockinfo->account;
+	hookdata.cert_path = NULL;
+	hookdata.password = NULL;
+	hookdata.is_smtp = sockinfo->is_smtp;
+	hooks_invoke(SSLCERT_GET_CLIENT_CERT_HOOKLIST, &hookdata);
+
+	if (hookdata.cert_path == NULL) {
+		g_free(hookdata.password);
+		return 0;
+	}
+
+	if ((r = gnutls_load_file(hookdata.cert_path, &tmp)) != 0) {
+		debug_print("couldn't load file '%s': %d\n",
+				hookdata.cert_path, r);
+		g_free(hookdata.password);
+		return 0;
+	}
+	debug_print("trying to load client cert+key from file '%s'\n",
+			hookdata.cert_path);
+
+	if ((r = gnutls_pcert_import_x509_raw(&sockinfo->client_crt, &tmp,
+				GNUTLS_X509_FMT_PEM, 0)) != 0) {
+		debug_print("couldn't import x509 cert from PEM file '%s': %d\n",
+				hookdata.cert_path, r);
+		g_free(hookdata.password);
+		return 0;
+	}
+	debug_print("loaded client certificate...\n");
+
+	gnutls_privkey_init(&sockinfo->client_key);
+	if ((r = gnutls_privkey_import_x509_raw(sockinfo->client_key, &tmp,
+				GNUTLS_X509_FMT_PEM, hookdata.password, 0)) != 0) {
+		debug_print("couldn't import x509 pkey from PEM file '%s': %d\n",
+				hookdata.cert_path, r);
+		g_free(hookdata.password);
+		gnutls_privkey_deinit(sockinfo->client_key);
+		return 0;
+	}
+	debug_print("loaded client private key...\n");
+
+	gnutls_free(tmp.data);
+
+	*pcert_length = 1;
+	*pcert = &sockinfo->client_crt;
+	*privkey = sockinfo->client_key;
+
+	return 0;
+}
+#endif /* GNUTLS_VERSION_NUMBER < 0x030000 */
+
 const gchar *claws_ssl_get_cert_file(void)
 {
 #ifndef G_OS_WIN32
@@ -357,11 +427,18 @@ gboolean ssl_init_socket(SockInfo *sockinfo)
 	gnutls_certificate_set_verify_flags (xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
 
 	gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) GINT_TO_POINTER(sockinfo->sock));
+
 	gnutls_session_set_ptr(session, sockinfo);
-#if GNUTLS_VERSION_NUMBER <= 0x020c00
+
+#if GNUTLS_VERSION_NUMBER < 0x030000
+#  if GNUTLS_VERSION_NUMBER <= 0x020c00
 	gnutls_certificate_client_set_retrieve_function(xcred, gnutls_client_cert_cb);
-#else
+#  else
 	gnutls_certificate_set_retrieve_function(xcred, gnutls_cert_cb);
+#  endif
+#else
+	debug_print("setting certificate callback function\n");
+	gnutls_certificate_set_retrieve_function2(xcred, gnutls_cert_cb);
 #endif
 
 #if GNUTLS_VERSION_NUMBER < 0x030107
@@ -412,12 +489,18 @@ void ssl_done_socket(SockInfo *sockinfo)
 		if (sockinfo->xcred)
 			gnutls_certificate_free_credentials(sockinfo->xcred);
 		gnutls_deinit(sockinfo->ssl);
+#if GNUTLS_VERSION_NUMBER < 0x030000
 		if (sockinfo->client_crt)
 			gnutls_x509_crt_deinit(sockinfo->client_crt);
 		if (sockinfo->client_key)
 			gnutls_x509_privkey_deinit(sockinfo->client_key);
 		sockinfo->client_key = NULL;
 		sockinfo->client_crt = NULL;
+#else
+		gnutls_pcert_deinit(&sockinfo->client_crt);
+		gnutls_privkey_deinit(sockinfo->client_key);
+#endif
+		sockinfo->client_key = NULL;
 		sockinfo->xcred = NULL;
 		sockinfo->ssl = NULL;
 	}
diff --git a/src/common/ssl.h b/src/common/ssl.h
index 3d6523a..625976b 100644
--- a/src/common/ssl.h
+++ b/src/common/ssl.h
@@ -35,6 +35,10 @@ typedef enum {
 
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
+#if GNUTLS_VERSION_NUMBER >= 0x030000
+#include <gnutls/abstract.h>
+#endif
+
 #include "socket.h"
 
 void ssl_init				(void);

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list