From dd5d325b0ac07ef73974b44c6959056030ab68ca Mon Sep 17 00:00:00 2001 From: Sam Voss Date: Mon, 7 Aug 2017 11:26:33 -0500 Subject: [PATCH] hostapd: Add configuration option check_crl_strict Add the ability to ignore time-based CRL errors from OpenSSL by specifying a new configuration parameter, check_crl_strict=0. This causes the following: - This setting does nothing when CRL checking is not enabled. - When CRL is enabled, "strict mode" will cause CRL time errors to not be ignored and will continue behaving as it currently does. - When CRL is enabled, disabling strict mode will cause CRL time errors to be ignored and will allow connections. By default, check_crl_strict is set to 1, or strict mode, to keep current functionality. Signed-off-by: Sam Voss --- eap_example/eap_example_server.c | 2 +- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 7 +++++++ src/ap/ap_config.c | 3 +++ src/ap/ap_config.h | 1 + src/ap/authsrv.c | 3 ++- src/crypto/tls.h | 4 +++- src/crypto/tls_gnutls.c | 2 +- src/crypto/tls_internal.c | 2 +- src/crypto/tls_none.c | 2 +- src/crypto/tls_openssl.c | 14 +++++++++++++- src/crypto/tls_wolfssl.c | 2 +- 12 files changed, 36 insertions(+), 8 deletions(-) diff --git a/eap_example/eap_example_server.c b/eap_example/eap_example_server.c index 052409694..145bb9f7e 100644 --- a/eap_example/eap_example_server.c +++ b/eap_example/eap_example_server.c @@ -88,7 +88,7 @@ static int eap_example_server_init_tls(void) return -1; } - if (tls_global_set_verify(eap_ctx.tls_ctx, 0)) { + if (tls_global_set_verify(eap_ctx.tls_ctx, 0, 1)) { printf("Failed to set check_crl\n"); return -1; } diff --git a/hostapd/config_file.c b/hostapd/config_file.c index b0d92ba38..cb8d26fce 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2489,6 +2489,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, "check_crl_strict") == 0) { + bss->check_crl_strict = 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) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 613455984..e934b9f34 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -904,6 +904,13 @@ eap_server=0 # 2 = check all CRLs in the certificate path #check_crl=1 +# Specify whether to ignore certificate CRL validity time mismatches with +# errors X509_V_ERR_CERT_HAS_EXPIRED and X509_V_ERR_CERT_NOT_YET_VALID. +# +# 0 = ignore errors +# 1 = do not ignore errors (default) +#check_crl_strict=1 + # 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.c b/src/ap/ap_config.c index 0cfba4562..68abb8e32 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -137,6 +137,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) #ifdef CONFIG_HS20 bss->hs20_release = (HS20_VERSION >> 4) + 1; #endif /* CONFIG_HS20 */ + + /* Default to strict CRL checking. */ + bss->check_crl_strict = 1; } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index fbcfe8dee..f0645dcf9 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -389,6 +389,7 @@ struct hostapd_bss_config { char *private_key; char *private_key_passwd; int check_crl; + int check_crl_strict; unsigned int tls_session_lifetime; unsigned int tls_flags; char *ocsp_stapling_response; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index b887608e7..d93b96750 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -231,7 +231,8 @@ int authsrv_init(struct hostapd_data *hapd) } if (tls_global_set_verify(hapd->ssl_ctx, - hapd->conf->check_crl)) { + hapd->conf->check_crl, + hapd->conf->check_crl_strict)) { wpa_printf(MSG_ERROR, "Failed to enable check_crl"); authsrv_deinit(hapd); return -1; diff --git a/src/crypto/tls.h b/src/crypto/tls.h index d6c581d03..dd67cff43 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -324,9 +324,11 @@ int __must_check tls_global_set_params( * @tls_ctx: TLS context data from tls_init() * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, * 2 = verify CRL for all certificates + * @strict: 0 = allow CRL time errors, 1 = do not allow CRL time errors * Returns: 0 on success, -1 on failure */ -int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); +int __must_check tls_global_set_verify(void *tls_ctx, int check_crl, + int strict); /** * tls_connection_set_verify - Set certificate verification options diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c index 5b52adb42..527d01ecf 100644 --- a/src/crypto/tls_gnutls.c +++ b/src/crypto/tls_gnutls.c @@ -848,7 +848,7 @@ fail: } -int tls_global_set_verify(void *ssl_ctx, int check_crl) +int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) { /* TODO */ return 0; diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c index 3d2dcbbb1..9c57ab25c 100644 --- a/src/crypto/tls_internal.c +++ b/src/crypto/tls_internal.c @@ -359,7 +359,7 @@ int tls_global_set_params(void *tls_ctx, } -int tls_global_set_verify(void *tls_ctx, int check_crl) +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) { struct tls_global *global = tls_ctx; global->check_crl = check_crl; diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c index 5d0c6bda1..108e9aa2e 100644 --- a/src/crypto/tls_none.c +++ b/src/crypto/tls_none.c @@ -72,7 +72,7 @@ int tls_global_set_params(void *tls_ctx, } -int tls_global_set_verify(void *tls_ctx, int check_crl) +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) { return -1; } diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 808eb5772..d41f68a00 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -214,10 +214,12 @@ static struct tls_context *tls_global = NULL; struct tls_data { SSL_CTX *ssl; unsigned int tls_session_lifetime; + int check_crl_strict; }; struct tls_connection { struct tls_context *context; + struct tls_data *data; SSL_CTX *ssl_ctx; SSL *ssl; BIO *ssl_in, *ssl_out; @@ -1474,6 +1476,7 @@ struct tls_connection * tls_connection_init(void *ssl_ctx) conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; + conn->data = data; conn->ssl_ctx = ssl; conn->ssl = SSL_new(ssl); if (conn->ssl == NULL) { @@ -1993,6 +1996,13 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) "time mismatch"); preverify_ok = 1; } + if (!preverify_ok && !conn->data->check_crl_strict && + (err == X509_V_ERR_CRL_HAS_EXPIRED || + err == X509_V_ERR_CRL_NOT_YET_VALID)) { + wpa_printf(MSG_DEBUG, + "OpenSSL: Ignore certificate validity CRL time mismatch"); + preverify_ok = 1; + } err_str = X509_verify_cert_error_string(err); @@ -2389,7 +2399,7 @@ static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) } -int tls_global_set_verify(void *ssl_ctx, int check_crl) +int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) { int flags; @@ -2406,6 +2416,8 @@ 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); + + data->check_crl_strict = strict; } return 0; } diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index f86557e02..b59622e5e 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -1549,7 +1549,7 @@ int tls_global_set_params(void *tls_ctx, } -int tls_global_set_verify(void *tls_ctx, int check_crl) +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) { wpa_printf(MSG_DEBUG, "SSL: global set verify: %d", check_crl);