From patchwork Mon May 21 16:39:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Voss X-Patchwork-Id: 917735 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=rockwellcollins.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="L1rT4V+T"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40qPf449fCz9s37 for ; Tue, 22 May 2018 02:40:28 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=H8gaJWJVQFDl3DQywrXfSCAG/IvoSKBhjMemnpymax4=; b=L1r T4V+ToQ6TzpRmvJ0FqhTEBAWELJcSLtLLqg1A2R474YxorWTD/yRxvBfjEI9s5N1aOPjLzIrto0C2 CXKyI1lvE/aCzC3NDkfCUmY3/++GPlzBRuWe0mFT/tD/tYbhaPXJQnCGu9oWXe7ae0nMcUZXKD4tV kjQi+nW6UjgnRtLXqcLAL7dRhnw4a/tnP9inu82HXl2zIposTG7n4vpagIP0qGODVEpwbzdh6ki2A jYkK6QgxZZ9ywp8Lo++2VpQgByOXKe05/0CCKbRfomhl3Bfd7MCcKoL6c2DR2ub0lCu73OiAw5PmH xVAYwhwamzpPz0yv0nuxeZW7psyedTw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKnr2-0007IU-Pb; Mon, 21 May 2018 16:40:12 +0000 Received: from da1vs04.rockwellcollins.com ([205.175.227.52]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKnqz-00063V-RQ for hostap@lists.infradead.org; Mon, 21 May 2018 16:40:11 +0000 Received: from ofwda1n02.rockwellcollins.com (HELO ciulimr02.rockwellcollins.com) ([205.175.227.14]) by da1vs04.rockwellcollins.com with ESMTP; 21 May 2018 11:39:55 -0500 X-Received: from largo.rockwellcollins.com (unknown [192.168.140.76]) by ciulimr02.rockwellcollins.com (Postfix) with ESMTP id 95FDC2007A; Mon, 21 May 2018 11:39:54 -0500 (CDT) From: Sam Voss To: hostap@lists.infradead.org Subject: [PATCH] crl_reload_interval: Add reload crl support Date: Mon, 21 May 2018 11:39:45 -0500 Message-Id: <1526920785-39066-1-git-send-email-sam.voss@rockwellcollins.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180521_094010_032270_A00E99F5 X-CRM114-Status: GOOD ( 20.70 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [205.175.227.52 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paresh Chaudhary , Sam Voss MIME-Version: 1.0 Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Paresh Chaudhary This patch has been added new flag 'crl_reload_interval' to reload crl. This can be used to reload ca_cert file on every new tls session if difference between last reload and current reload time(seconds) greater-than crl_reload_interval. Note: If interval time > 0 and < 300 then crl_reload_interval will reset to 300 seconds. For this support 'check_crl' should be 1 or 2. Signed-off-by: Paresh Chaudhary Signed-off-by: Sam Voss --- hostapd/config_file.c | 2 + hostapd/hostapd.conf | 9 +++++ src/ap/ap_config.h | 1 + src/ap/authsrv.c | 9 +++++ src/crypto/tls.h | 11 ++++++ src/crypto/tls_openssl.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 131 insertions(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 5079f69..5116857 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2131,6 +2131,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->private_key_passwd = os_strdup(pos); } else if (os_strcmp(buf, "check_crl") == 0) { bss->check_crl = atoi(pos); + } else if (os_strcmp(buf, "crl_reload_interval") == 0) { + bss->crl_reload_interval = atoi(pos); } else if (os_strcmp(buf, "tls_session_lifetime") == 0) { bss->tls_session_lifetime = atoi(pos); } else if (os_strcmp(buf, "ocsp_stapling_response") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index fa9a855..3f1c325 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -795,6 +795,15 @@ eap_server=0 # 2 = check all CRLs in the certificate path #check_crl=1 +# crl reload interval in seconds +# This can be used to reload ca_cert file on every new tls session if difference +# between last reload and current reload time(seconds) greater-than +# crl_reload_interval +# Note: If interval time > 0 and < 300 then crl_reload_interval will reset to +# 300 seconds. For this support 'check_crl' should be 1 or 2. +# 0 = do not reload CRLS (default) +#crl_reload_interval = 300 + # TLS Session Lifetime in seconds # This can be used to allow TLS sessions to be cached and resumed with an # abbreviated handshake when using EAP-TLS/TTLS/PEAP. diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 8c8f7e2..63d3786 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -352,6 +352,7 @@ struct hostapd_bss_config { char *private_key; char *private_key_passwd; int check_crl; + unsigned int crl_reload_interval; unsigned int tls_session_lifetime; char *ocsp_stapling_response; char *ocsp_stapling_response_multi; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index cdb49cd..c16d679 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -157,6 +157,15 @@ int authsrv_init(struct hostapd_data *hapd) os_memset(&conf, 0, sizeof(conf)); conf.tls_session_lifetime = hapd->conf->tls_session_lifetime; + if (hapd->conf->crl_reload_interval > 0 && hapd->conf->check_crl <=0) { + wpa_printf(MSG_INFO, "Failed to enable crl reload functionality," + "It's depend on check_crl."); + } + if (hapd->conf->check_crl > 0 && hapd->conf->crl_reload_interval > 0) { + conf.crl_reload_interval = hapd->conf->crl_reload_interval; + wpa_printf(MSG_INFO, "Enabled crl reload functionality"); + } + hapd->ssl_ctx = tls_init(&conf); if (hapd->ssl_ctx == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize TLS"); diff --git a/src/crypto/tls.h b/src/crypto/tls.h index 11d504a..adbc9d9 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -8,6 +8,7 @@ #ifndef TLS_H #define TLS_H +#include struct tls_connection; @@ -80,6 +81,7 @@ struct tls_config { int cert_in_cb; const char *openssl_ciphers; unsigned int tls_session_lifetime; + unsigned int crl_reload_interval; void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); @@ -224,6 +226,15 @@ void tls_deinit(void *tls_ctx); int tls_get_errors(void *tls_ctx); /** + * tls_crl_cert_reload - Reload crl cert and init new store + * @ca_cert : ca_cert file + * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, + * 2 = verify CRL for all certificates + * Returns : store pointer on success and NULL on failure + */ +X509_STORE *tls_crl_cert_reload(const char *ca_cert, int check_crl); + +/** * tls_connection_init - Initialize a new TLS connection * @tls_ctx: TLS context data from tls_init() * Returns: Connection context data, conn for other function calls diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 23ac64b..7575688 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -7,6 +7,7 @@ */ #include "includes.h" +#include #ifndef CONFIG_SMARTCARD #ifndef OPENSSL_NO_ENGINE @@ -188,6 +189,8 @@ struct tls_context { void *cb_ctx; int cert_in_cb; char *ocsp_stapling_response; + int check_crl; + const char *ca_cert; }; static struct tls_context *tls_global = NULL; @@ -196,6 +199,10 @@ static struct tls_context *tls_global = NULL; struct tls_data { SSL_CTX *ssl; unsigned int tls_session_lifetime; + unsigned int crl_reload_interval; + unsigned int crl_last_reload; + X509_STORE *old_x509_store; + pthread_mutex_t mutex; }; struct tls_connection { @@ -966,8 +973,15 @@ void * tls_init(const struct tls_config *conf) return NULL; } data->ssl = ssl; - if (conf) + if (conf) { data->tls_session_lifetime = conf->tls_session_lifetime; + data->crl_reload_interval = conf->crl_reload_interval; + if (data->crl_reload_interval > 0 && data->crl_reload_interval < 300) { + wpa_printf(MSG_INFO, + "crl reload interval is set too low, reset it to 300"); + data->crl_reload_interval = 300; + } + } SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3); @@ -1026,6 +1040,9 @@ void * tls_init(const struct tls_config *conf) return NULL; } + /* Init mutex */ + pthread_mutex_init(&data->mutex, NULL); + return data; } @@ -1058,6 +1075,7 @@ void tls_deinit(void *ssl_ctx) tls_global = NULL; } + pthread_mutex_destroy(&data->mutex); os_free(data); } @@ -1331,8 +1349,39 @@ struct tls_connection * tls_connection_init(void *ssl_ctx) SSL_CTX *ssl = data->ssl; struct tls_connection *conn; long options; + X509_STORE *new_cert_store; + time_t now; struct tls_context *context = SSL_CTX_get_app_data(ssl); + /* Get current time */ + now = time(NULL); + + /* Replace X509 store if it is time to update crl */ + /* Replace X509 store if difference between current time and previous store + * reload time greater-than crl_reload_interval */ + if (data->crl_reload_interval > 0 && data->crl_last_reload + + data->crl_reload_interval <= now) { + pthread_mutex_lock(&data->mutex); + /* recheck data->crl_last_reload because it may be inaccurate + * without mutex */ + if (data->crl_last_reload + data->crl_reload_interval <= now) { + wpa_printf(MSG_INFO, "Flushing X509 store with ca_cert file"); + new_cert_store = (X509_STORE *)tls_crl_cert_reload + (tls_global->ca_cert, tls_global->check_crl); + if (new_cert_store == NULL) { + wpa_printf(MSG_ERROR, + "Error replacing X509 store with ca_cert file"); + } else { + /*Free old store */ + if (data->old_x509_store) X509_STORE_free(data->old_x509_store); + data->old_x509_store = ssl->cert_store; + ssl->cert_store = new_cert_store; + data->crl_last_reload = now; + } + } + pthread_mutex_unlock(&data->mutex); + } + conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; @@ -2159,6 +2208,37 @@ static int tls_connection_ca_cert(struct tls_data *data, } +X509_STORE *tls_crl_cert_reload(const char *ca_cert, int check_crl) +{ + int flags; + X509_STORE *store; + + store = X509_STORE_new(); + if (store == NULL) { + wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " + "certificate store", __func__); + return NULL; + } + + if (ca_cert) { + if (!X509_STORE_load_locations(store, ca_cert, NULL)) { + tls_show_errors(MSG_WARNING, __func__, + "Failed to load root certificates"); + return NULL; + } + } + + if (check_crl) + flags = X509_V_FLAG_CRL_CHECK; + if (check_crl == 2) + flags |= X509_V_FLAG_CRL_CHECK_ALL; + + X509_STORE_set_flags(store, flags); + + return store; +} + + static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) { SSL_CTX *ssl_ctx = data->ssl; @@ -2179,6 +2259,13 @@ static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_cert)); #endif /* OPENSSL_NO_STDIO */ + + if (NULL == tls_global) { + tls_show_errors(MSG_INFO, __func__, "Failed setting " + "ca_cert in tls_global context."); + } else { + tls_global->ca_cert = ca_cert; + } } return 0; @@ -2202,6 +2289,17 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl) if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); + + if (NULL == tls_global) { + tls_show_errors(MSG_INFO, __func__, "Failed setting " + "check crl mode in tls_global context."); + } else { + tls_global->check_crl = check_crl; + } + + /* Store crl last reload time */ + data->crl_last_reload = time(NULL); + data->old_x509_store = NULL; } return 0; }