talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit dda3675203030f329d527c697e14342c9c13a75c
parent b0c17cd08e482dbda407dabdc952dfcf5d8fdb6e
Author: Colin Leroy <colin@colino.net>
Date:   Wed, 23 Apr 2014 09:42:55 +0200

Implement certificate chain retrieval and passing. CAs are not loaded
yet.

Diffstat:
Msrc/common/ssl_certificate.c | 17+++++++++++++++++
Msrc/common/ssl_certificate.h | 1+
Msrc/etpan/etpan-ssl.c | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/src/common/ssl_certificate.c b/src/common/ssl_certificate.c @@ -647,6 +647,23 @@ 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 result = FALSE; + gint status; + + gnutls_x509_crt_list_verify (certs, + chain_len, + NULL, 0, + NULL, 0, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, + &status); + + result = ssl_certificate_check(certs[0], status, host, port); + + return result; +} + gnutls_x509_crt_t ssl_certificate_get_x509_from_pem_file(const gchar *file) { gnutls_x509_crt_t x509 = NULL; diff --git a/src/common/ssl_certificate.h b/src/common/ssl_certificate.h @@ -58,6 +58,7 @@ 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); 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/etpan/etpan-ssl.c b/src/etpan/etpan-ssl.c @@ -26,6 +26,7 @@ #ifdef USE_GNUTLS #ifdef HAVE_LIBETPAN #include <libetpan/libetpan.h> +#include <libetpan/libetpan_version.h> #include <gnutls/gnutls.h> #include <gnutls/x509.h> #include <stdlib.h> @@ -33,6 +34,7 @@ #include <glib/gi18n.h> #include <errno.h> +#include "etpan-ssl.h" #include "ssl_certificate.h" #include "utils.h" #include "log.h" @@ -40,6 +42,7 @@ gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port) { +#if (!defined LIBETPAN_API_CURRENT || LIBETPAN_API_CURRENT < 18) unsigned char *cert_der = NULL; int len; gnutls_x509_crt_t cert = NULL; @@ -75,6 +78,56 @@ gboolean etpan_certificate_check(mailstream *stream, const char *host, gint port gnutls_x509_crt_deinit(cert); return FALSE; } +#else + carray *certs_der = NULL; + gint chain_len = 0, i; + gnutls_x509_crt_t *certs = NULL; + gboolean result; + + if (stream == NULL) + return FALSE; + + certs_der = mailstream_get_certificate_chain(stream); + if (!certs_der) { + g_warning("could not get certs"); + return FALSE; + } + chain_len = carray_count(certs_der); + + certs = malloc(sizeof(gnutls_x509_crt_t) * chain_len); + if (certs == NULL) { + g_warning("could not allocate certs"); + return FALSE; + } + + result = TRUE; + for (i = 0; i < chain_len; i++) { + MMAPString *cert_str = carray_get(certs_der, i); + gnutls_datum_t tmp; + + tmp.data = malloc(cert_str->len); + memcpy(tmp.data, cert_str->str, cert_str->len); + tmp.size = cert_str->len; + + mmap_string_free(cert_str); + + gnutls_x509_crt_init(&certs[i]); + if (gnutls_x509_crt_import(certs[i], &tmp, GNUTLS_X509_FMT_DER) < 0) + result = FALSE; + + free(tmp.data); + } + + carray_free(certs_der); + + if (result == TRUE) + result = ssl_certificate_check_chain(certs, chain_len, host, port); + + for (i = 0; i < chain_len; i++) + gnutls_x509_crt_deinit(certs[i]); + + return result; +#endif } void etpan_connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, void * data)