]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
crl_reload_interval: Add CRL reloading support
authorJared Bents <jared.bents@rockwellcollins.com>
Wed, 16 Jan 2019 15:15:01 +0000 (09:15 -0600)
committerJouni Malinen <j@w1.fi>
Sun, 27 Jan 2019 16:45:07 +0000 (18:45 +0200)
This patch adds a new flag 'crl_reload_interval' to reload CRL
periodically. This can be used to reload ca_cert file and the included
CRL information on every new TLS session if difference between the last
reload and the current time in seconds is greater than
crl_reload_interval.

This reloading is used for cases where check_crl is 1 or 2 and the CRL
is included in the ca_file.

Signed-off-by: Paresh Chaudhary <paresh.chaudhary@rockwellcollins.com>
Signed-off-by: Jared Bents <jared.bents@rockwellcollins.com>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/authsrv.c
src/crypto/tls.h
src/crypto/tls_openssl.c

index e2ca2789b7f3c370aa838dc91342d3b379c6686a..aeec1d9e25d662452f6e8c1567076ec3d9866648 100644 (file)
@@ -2505,6 +2505,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                bss->check_crl = atoi(pos);
        } else if (os_strcmp(buf, "check_crl_strict") == 0) {
                bss->check_crl_strict = 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, "tls_flags") == 0) {
index 739d367728a9f21f5b07e9caff243f0a84feb460..ab37f03b54a65a9ff23d11fcb47ca6e0a1fe110a 100644 (file)
@@ -922,7 +922,8 @@ eap_server=0
 # valid CRL signed by the CA is required to be included in the ca_cert file.
 # This can be done by using PEM format for CA certificate and CRL and
 # concatenating these into one file. Whenever CRL changes, hostapd needs to be
-# restarted to take the new CRL into use.
+# restarted to take the new CRL into use. Alternatively, crl_reload_interval can
+# be used to configure periodic updating of the loaded CRL information.
 # 0 = do not verify CRLs (default)
 # 1 = check the CRL of the user certificate
 # 2 = check all CRLs in the certificate path
@@ -935,6 +936,16 @@ eap_server=0
 # 1 = do not ignore errors (default)
 #check_crl_strict=1
 
+# CRL reload interval in seconds
+# This can be used to reload ca_cert file and the included CRL on every new TLS
+# session if difference between last reload and the current reload time in
+# seconds is greater than crl_reload_interval.
+# Note: If interval time is very short, CPU overhead may be negatively affected
+# and it is advised to not go below 300 seconds.
+# This is applicable only with check_crl values 1 and 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.
index 8ca80d3f82264f219700ea9c817ebe8aa4924b50..6963df460217c95a196392bbc39657e448d93693 100644 (file)
@@ -392,6 +392,7 @@ struct hostapd_bss_config {
        char *private_key_passwd;
        int check_crl;
        int check_crl_strict;
+       unsigned int crl_reload_interval;
        unsigned int tls_session_lifetime;
        unsigned int tls_flags;
        char *ocsp_stapling_response;
index d93b967508641cee0baeaf335368838e24fca97c..1bb3d9f6ff7cd38e5bc81d8decee79c283f1310d 100644 (file)
@@ -201,6 +201,16 @@ 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,
+                                  "Cannot enable CRL reload functionality - it depends on check_crl being set");
+               } else if (hapd->conf->crl_reload_interval > 0) {
+                       conf.crl_reload_interval =
+                               hapd->conf->crl_reload_interval;
+                       wpa_printf(MSG_INFO,
+                                  "Enabled CRL reload functionality");
+               }
                conf.tls_flags = hapd->conf->tls_flags;
                conf.event_cb = authsrv_tls_event;
                conf.cb_ctx = hapd;
index e13444a6c78613da8421fb2d1bd66e8f1229439d..413cccddc84dc012247e5c6d91271ccdd1666ebc 100644 (file)
@@ -82,6 +82,7 @@ struct tls_config {
        int cert_in_cb;
        const char *openssl_ciphers;
        unsigned int tls_session_lifetime;
+       unsigned int crl_reload_interval;
        unsigned int tls_flags;
 
        void (*event_cb)(void *ctx, enum tls_event ev,
index 705fa29a3ec056fd548be74ee601091d22559c5e..99caa68bddcd674df68ead3fae2c3aa31f5869ce 100644 (file)
@@ -214,7 +214,11 @@ static struct tls_context *tls_global = NULL;
 struct tls_data {
        SSL_CTX *ssl;
        unsigned int tls_session_lifetime;
+       int check_crl;
        int check_crl_strict;
+       char *ca_cert;
+       unsigned int crl_reload_interval;
+       struct os_reltime crl_last_reload;
 };
 
 struct tls_connection {
@@ -305,6 +309,37 @@ static void tls_show_errors(int level, const char *func, const char *txt)
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
+static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl)
+{
+       int flags;
+       X509_STORE *store;
+
+       store = X509_STORE_new();
+       if (!store) {
+               wpa_printf(MSG_DEBUG,
+                          "OpenSSL: %s - failed to allocate new certificate store",
+                          __func__);
+               return NULL;
+       }
+
+       if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) {
+               tls_show_errors(MSG_WARNING, __func__,
+                               "Failed to load root certificates");
+               X509_STORE_free(store);
+               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;
+}
+
+
 #ifdef CONFIG_NATIVE_WINDOWS
 
 /* Windows CryptoAPI and access to certificate stores */
@@ -993,8 +1028,10 @@ 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;
+       }
 
        SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
        SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
@@ -1076,6 +1113,7 @@ void tls_deinit(void *ssl_ctx)
                os_free(context);
        if (data->tls_session_lifetime > 0)
                SSL_CTX_flush_sessions(ssl, 0);
+       os_free(data->ca_cert);
        SSL_CTX_free(ssl);
 
        tls_openssl_ref_count--;
@@ -1471,8 +1509,28 @@ 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;
+       struct os_reltime now;
        struct tls_context *context = SSL_CTX_get_app_data(ssl);
 
+       /* Replace X509 store if it is time to update CRL. */
+       if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 &&
+           os_reltime_expired(&now, &data->crl_last_reload,
+                              data->crl_reload_interval)) {
+               wpa_printf(MSG_INFO,
+                          "OpenSSL: Flushing X509 store with ca_cert file");
+               new_cert_store = tls_crl_cert_reload(data->ca_cert,
+                                                    data->check_crl);
+               if (!new_cert_store) {
+                       wpa_printf(MSG_ERROR,
+                                  "OpenSSL: Error replacing X509 store with ca_cert file");
+               } else {
+                       /* Replace old store */
+                       SSL_CTX_set_cert_store(ssl, new_cert_store);
+                       data->crl_last_reload = now;
+               }
+       }
+
        conn = os_zalloc(sizeof(*conn));
        if (conn == NULL)
                return NULL;
@@ -2393,6 +2451,9 @@ 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 */
+
+               os_free(data->ca_cert);
+               data->ca_cert = os_strdup(ca_cert);
        }
 
        return 0;
@@ -2417,7 +2478,9 @@ int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
                        flags |= X509_V_FLAG_CRL_CHECK_ALL;
                X509_STORE_set_flags(cs, flags);
 
+               data->check_crl = check_crl;
                data->check_crl_strict = strict;
+               os_get_reltime(&data->crl_last_reload);
        }
        return 0;
 }