crl_reload_interval: Add CRL reloading support
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>
This commit is contained in:
parent
0eb34f8f28
commit
159a7fbdea
6 changed files with 90 additions and 2 deletions
|
@ -2505,6 +2505,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->check_crl = atoi(pos);
|
bss->check_crl = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "check_crl_strict") == 0) {
|
} else if (os_strcmp(buf, "check_crl_strict") == 0) {
|
||||||
bss->check_crl_strict = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
|
||||||
bss->tls_session_lifetime = atoi(pos);
|
bss->tls_session_lifetime = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "tls_flags") == 0) {
|
} else if (os_strcmp(buf, "tls_flags") == 0) {
|
||||||
|
|
|
@ -922,7 +922,8 @@ eap_server=0
|
||||||
# valid CRL signed by the CA is required to be included in the ca_cert file.
|
# 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
|
# 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
|
# 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)
|
# 0 = do not verify CRLs (default)
|
||||||
# 1 = check the CRL of the user certificate
|
# 1 = check the CRL of the user certificate
|
||||||
# 2 = check all CRLs in the certificate path
|
# 2 = check all CRLs in the certificate path
|
||||||
|
@ -935,6 +936,16 @@ eap_server=0
|
||||||
# 1 = do not ignore errors (default)
|
# 1 = do not ignore errors (default)
|
||||||
#check_crl_strict=1
|
#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
|
# TLS Session Lifetime in seconds
|
||||||
# This can be used to allow TLS sessions to be cached and resumed with an
|
# This can be used to allow TLS sessions to be cached and resumed with an
|
||||||
# abbreviated handshake when using EAP-TLS/TTLS/PEAP.
|
# abbreviated handshake when using EAP-TLS/TTLS/PEAP.
|
||||||
|
|
|
@ -392,6 +392,7 @@ struct hostapd_bss_config {
|
||||||
char *private_key_passwd;
|
char *private_key_passwd;
|
||||||
int check_crl;
|
int check_crl;
|
||||||
int check_crl_strict;
|
int check_crl_strict;
|
||||||
|
unsigned int crl_reload_interval;
|
||||||
unsigned int tls_session_lifetime;
|
unsigned int tls_session_lifetime;
|
||||||
unsigned int tls_flags;
|
unsigned int tls_flags;
|
||||||
char *ocsp_stapling_response;
|
char *ocsp_stapling_response;
|
||||||
|
|
|
@ -201,6 +201,16 @@ int authsrv_init(struct hostapd_data *hapd)
|
||||||
|
|
||||||
os_memset(&conf, 0, sizeof(conf));
|
os_memset(&conf, 0, sizeof(conf));
|
||||||
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
|
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.tls_flags = hapd->conf->tls_flags;
|
||||||
conf.event_cb = authsrv_tls_event;
|
conf.event_cb = authsrv_tls_event;
|
||||||
conf.cb_ctx = hapd;
|
conf.cb_ctx = hapd;
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct tls_config {
|
||||||
int cert_in_cb;
|
int cert_in_cb;
|
||||||
const char *openssl_ciphers;
|
const char *openssl_ciphers;
|
||||||
unsigned int tls_session_lifetime;
|
unsigned int tls_session_lifetime;
|
||||||
|
unsigned int crl_reload_interval;
|
||||||
unsigned int tls_flags;
|
unsigned int tls_flags;
|
||||||
|
|
||||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||||
|
|
|
@ -214,7 +214,11 @@ static struct tls_context *tls_global = NULL;
|
||||||
struct tls_data {
|
struct tls_data {
|
||||||
SSL_CTX *ssl;
|
SSL_CTX *ssl;
|
||||||
unsigned int tls_session_lifetime;
|
unsigned int tls_session_lifetime;
|
||||||
|
int check_crl;
|
||||||
int check_crl_strict;
|
int check_crl_strict;
|
||||||
|
char *ca_cert;
|
||||||
|
unsigned int crl_reload_interval;
|
||||||
|
struct os_reltime crl_last_reload;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tls_connection {
|
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 */
|
#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
|
#ifdef CONFIG_NATIVE_WINDOWS
|
||||||
|
|
||||||
/* Windows CryptoAPI and access to certificate stores */
|
/* Windows CryptoAPI and access to certificate stores */
|
||||||
|
@ -993,8 +1028,10 @@ void * tls_init(const struct tls_config *conf)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
data->ssl = ssl;
|
data->ssl = ssl;
|
||||||
if (conf)
|
if (conf) {
|
||||||
data->tls_session_lifetime = conf->tls_session_lifetime;
|
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_SSLv2);
|
||||||
SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
|
SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
|
||||||
|
@ -1076,6 +1113,7 @@ void tls_deinit(void *ssl_ctx)
|
||||||
os_free(context);
|
os_free(context);
|
||||||
if (data->tls_session_lifetime > 0)
|
if (data->tls_session_lifetime > 0)
|
||||||
SSL_CTX_flush_sessions(ssl, 0);
|
SSL_CTX_flush_sessions(ssl, 0);
|
||||||
|
os_free(data->ca_cert);
|
||||||
SSL_CTX_free(ssl);
|
SSL_CTX_free(ssl);
|
||||||
|
|
||||||
tls_openssl_ref_count--;
|
tls_openssl_ref_count--;
|
||||||
|
@ -1471,8 +1509,28 @@ struct tls_connection * tls_connection_init(void *ssl_ctx)
|
||||||
SSL_CTX *ssl = data->ssl;
|
SSL_CTX *ssl = data->ssl;
|
||||||
struct tls_connection *conn;
|
struct tls_connection *conn;
|
||||||
long options;
|
long options;
|
||||||
|
X509_STORE *new_cert_store;
|
||||||
|
struct os_reltime now;
|
||||||
struct tls_context *context = SSL_CTX_get_app_data(ssl);
|
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));
|
conn = os_zalloc(sizeof(*conn));
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
return 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_CTX_set_client_CA_list(ssl_ctx,
|
||||||
SSL_load_client_CA_file(ca_cert));
|
SSL_load_client_CA_file(ca_cert));
|
||||||
#endif /* OPENSSL_NO_STDIO */
|
#endif /* OPENSSL_NO_STDIO */
|
||||||
|
|
||||||
|
os_free(data->ca_cert);
|
||||||
|
data->ca_cert = os_strdup(ca_cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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;
|
flags |= X509_V_FLAG_CRL_CHECK_ALL;
|
||||||
X509_STORE_set_flags(cs, flags);
|
X509_STORE_set_flags(cs, flags);
|
||||||
|
|
||||||
|
data->check_crl = check_crl;
|
||||||
data->check_crl_strict = strict;
|
data->check_crl_strict = strict;
|
||||||
|
os_get_reltime(&data->crl_last_reload);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue