isync

mailbox synchronization program
git clone https://git.code.sf.net/p/isync/isync
Log | Files | Refs | README | LICENSE

commit 481c12a8b31c6dd7eba048e8f42d0b9653110621
parent cfaa4848dd7c72e628fcc81a4c4532c9be226144
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Wed, 29 Jul 2020 20:23:54 +0200

handle CertificateFile more cleanly

properly distribute the certificates between the SSL context's trust
store and our host cert list.

as a drive-by, clean up some nasty type casts at the cost of including
a second OpenSSL header into socket.h.

Diffstat:
Msrc/common.h | 1+
Msrc/socket.c | 36++++++++++++++++++++++++++++--------
Msrc/socket.h | 3++-
Msrc/util.c | 2+-
4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/src/common.h b/src/common.h @@ -172,6 +172,7 @@ int ATTR_PRINTFLIKE(2, 0) nfvasprintf( char **str, const char *fmt, va_list va ) int ATTR_PRINTFLIKE(2, 3) nfasprintf( char **str, const char *fmt, ... ); int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, ... ); void ATTR_NORETURN oob( void ); +void ATTR_NORETURN oom( void ); char *expand_strdup( const char *s ); diff --git a/src/socket.c b/src/socket.c @@ -194,7 +194,6 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock ) int i; long err; X509 *cert; - STACK_OF(X509_OBJECT) *trusted; cert = SSL_get_peer_certificate( sock->ssl ); if (!cert) { @@ -202,9 +201,8 @@ verify_cert_host( const server_conf_t *conf, conn_t *sock ) return -1; } - trusted = (STACK_OF(X509_OBJECT) *)sock->conf->trusted_certs; - for (i = 0; i < sk_X509_OBJECT_num( trusted ); i++) { - if (!X509_cmp( cert, X509_OBJECT_get0_X509( sk_X509_OBJECT_value( trusted, i ) ) )) { + for (i = 0; i < sk_X509_num( sock->conf->trusted_certs ); i++) { + if (!X509_cmp( cert, sk_X509_value( sock->conf->trusted_certs, i ) )) { X509_free( cert ); return 0; } @@ -273,11 +271,33 @@ DIAG_POP return 0; } - if (conf->cert_file && !SSL_CTX_load_verify_locations( mconf->SSLContext, conf->cert_file, NULL )) { - print_ssl_errors( "loading certificate file '%s'", conf->cert_file ); - return 0; + if (!(mconf->trusted_certs = sk_X509_new_null())) + oom(); + if (conf->cert_file) { + X509_STORE *store; + if (!(store = X509_STORE_new())) + oom(); + if (!X509_STORE_load_locations( store, conf->cert_file, NULL )) { + print_ssl_errors( "loading certificate file '%s'", conf->cert_file ); + return 0; + } + STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects( store ); + for (int i = 0; i < sk_X509_OBJECT_num( objs ); i++) { + X509 *cert = X509_OBJECT_get0_X509( sk_X509_OBJECT_value( objs, i ) ); + if (cert) { + if (X509_check_ca( cert )) { + if (!X509_STORE_add_cert( SSL_CTX_get_cert_store( mconf->SSLContext ), cert )) + oom(); + } else { + X509_up_ref( cert ); // Locking failure assumed impossible + if (!sk_X509_push( mconf->trusted_certs, cert )) + oom(); + } + } + } + X509_STORE_free( store ); } - mconf->trusted_certs = (_STACK *)sk_X509_OBJECT_dup( X509_STORE_get0_objects( SSL_CTX_get_cert_store( mconf->SSLContext ) ) ); + if (mconf->system_certs && !SSL_CTX_set_default_verify_paths( mconf->SSLContext )) { ulong err; while ((err = ERR_get_error())) diff --git a/src/socket.h b/src/socket.h @@ -31,6 +31,7 @@ #ifdef HAVE_LIBSSL # include <openssl/ssl.h> +# include <openssl/x509.h> enum { TLSv1 = 4, @@ -55,7 +56,7 @@ typedef struct { /* these are actually variables and are leaked at the end */ char ssl_ctx_valid; - _STACK *trusted_certs; + STACK_OF(X509) *trusted_certs; SSL_CTX *SSLContext; #endif } server_conf_t; diff --git a/src/util.c b/src/util.c @@ -353,7 +353,7 @@ nfsnprintf( char *buf, int blen, const char *fmt, ... ) return ret; } -static void ATTR_NORETURN +void oom( void ) { fputs( "Fatal: Out of memory\n", stderr );