From 790e00aaa9082c6b6ed5de64567971f994ce45ce Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 19 Feb 2013 11:22:36 +0100 Subject: [PATCH 1/4] Make cert_validator_t.validate optional to implement --- src/libstrongswan/credentials/cert_validator.h | 1 + src/libstrongswan/credentials/credential_manager.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h index 00e30d7a0..effc6b0d6 100644 --- a/src/libstrongswan/credentials/cert_validator.h +++ b/src/libstrongswan/credentials/cert_validator.h @@ -43,6 +43,7 @@ struct cert_validator_t { * @param pathlen the current length of the path bottom-up * @param anchor is issuer trusted root anchor * @param auth container for resulting authentication info + * @return TRUE if subject certificate valid */ bool (*validate)(cert_validator_t *this, certificate_t *subject, certificate_t *issuer, bool online, u_int pathlen, diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index 9e40c5a10..a427b57fb 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -541,6 +541,10 @@ static bool check_certificate(private_credential_manager_t *this, enumerator = this->validators->create_enumerator(this->validators); while (enumerator->enumerate(enumerator, &validator)) { + if (!validator->validate) + { + continue; + } if (!validator->validate(validator, subject, issuer, online, pathlen, trusted, auth)) { From de399f550d1bf7a84e57da52af10c8c2532403b9 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 19 Feb 2013 11:26:21 +0100 Subject: [PATCH 2/4] Add a cert_validator hook allowing plugins to provide custom lifetime checking --- .../credentials/cert_validator.h | 16 +++++ .../credentials/credential_manager.c | 58 +++++++++++++++---- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h index effc6b0d6..325fa0af3 100644 --- a/src/libstrongswan/credentials/cert_validator.h +++ b/src/libstrongswan/credentials/cert_validator.h @@ -34,6 +34,22 @@ typedef struct cert_validator_t cert_validator_t; */ struct cert_validator_t { + /** + * Check the lifetime of a certificate. + * + * If this function returns SUCCESS or FAILED, the certificate lifetime is + * considered definitely (in-)valid, without asking other validators. + * If all registered validaters return NEED_MORE, the default + * lifetime check is performed. + * + * @param cert certificate to check lifetime + * @param pathlen the current length of the path bottom-up + * @param anchor is certificate trusted root anchor? + * @param auth container for resulting authentication info + * @return SUCCESS, FAILED or NEED_MORE to ask next validator + */ + status_t (*check_lifetime)(cert_validator_t *this, certificate_t *cert, + int pathlen, bool anchor, auth_cfg_t *auth); /** * Validate a subject certificate in relation to its issuer. * diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index a427b57fb..44eaec62c 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -514,6 +514,52 @@ static void cache_queue(private_credential_manager_t *this) this->queue_mutex->unlock(this->queue_mutex); } +/** + * Use validators to check the lifetime of certificates + */ +static bool check_lifetime(private_credential_manager_t *this, + certificate_t *cert, char *label, + int pathlen, bool trusted, auth_cfg_t *auth) +{ + time_t not_before, not_after; + cert_validator_t *validator; + enumerator_t *enumerator; + status_t status = NEED_MORE; + + enumerator = this->validators->create_enumerator(this->validators); + while (enumerator->enumerate(enumerator, &validator)) + { + if (!validator->check_lifetime) + { + continue; + } + status = validator->check_lifetime(validator, cert, + pathlen, trusted, auth); + if (status != NEED_MORE) + { + break; + } + } + enumerator->destroy(enumerator); + + switch (status) + { + case NEED_MORE: + if (!cert->get_validity(cert, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)", + label, ¬_before, FALSE, ¬_after, FALSE); + return FALSE; + } + return TRUE; + case SUCCESS: + return TRUE; + case FAILED: + default: + return FALSE; + } +} + /** * check a certificate for its lifetime */ @@ -521,20 +567,12 @@ static bool check_certificate(private_credential_manager_t *this, certificate_t *subject, certificate_t *issuer, bool online, int pathlen, bool trusted, auth_cfg_t *auth) { - time_t not_before, not_after; cert_validator_t *validator; enumerator_t *enumerator; - if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) + if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) || + !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth)) { - DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); return FALSE; } From 0ed31e7284f4017e99647e436d2f7fedeeff04ba Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 19 Feb 2013 14:49:38 +0100 Subject: [PATCH 3/4] Add a stub for systime-fix, a plugin handling certificate lifetimes gracefully --- configure.in | 4 ++ src/libcharon/Makefile.am | 7 +++ src/libcharon/plugins/systime_fix/Makefile.am | 14 +++++ .../plugins/systime_fix/systime_fix_plugin.c | 63 +++++++++++++++++++ .../plugins/systime_fix/systime_fix_plugin.h | 42 +++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 src/libcharon/plugins/systime_fix/Makefile.am create mode 100644 src/libcharon/plugins/systime_fix/systime_fix_plugin.c create mode 100644 src/libcharon/plugins/systime_fix/systime_fix_plugin.h diff --git a/configure.in b/configure.in index 2c3e739d6..06481ea6a 100644 --- a/configure.in +++ b/configure.in @@ -222,6 +222,7 @@ ARG_ENABL_SET([whitelist], [enable peer identity whitelisting plugin.]) ARG_ENABL_SET([lookip], [enable fast virtual IP lookup and notification plugin.]) ARG_ENABL_SET([error-notify], [enable error notification plugin.]) ARG_ENABL_SET([certexpire], [enable CSV export of expiration dates of used certificates.]) +ARG_ENABL_SET([systime-fix], [enable plugin to handle cert lifetimes with invalid system time gracefully.]) ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) ARG_ENABL_SET([duplicheck], [advanced duplicate checking plugin using liveness checks.]) ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.]) @@ -971,6 +972,7 @@ ADD_PLUGIN([whitelist], [c charon]) ADD_PLUGIN([lookip], [c charon]) ADD_PLUGIN([error-notify], [c charon]) ADD_PLUGIN([certexpire], [c charon]) +ADD_PLUGIN([systime-fix], [c charon]) ADD_PLUGIN([led], [c charon]) ADD_PLUGIN([duplicheck], [c charon]) ADD_PLUGIN([coupling], [c charon]) @@ -1065,6 +1067,7 @@ AM_CONDITIONAL(USE_WHITELIST, test x$whitelist = xtrue) AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue) AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue) AM_CONDITIONAL(USE_CERTEXPIRE, test x$certexpire = xtrue) +AM_CONDITIONAL(USE_SYSTIME_FIX, test x$systime_fix = xtrue) AM_CONDITIONAL(USE_LED, test x$led = xtrue) AM_CONDITIONAL(USE_DUPLICHECK, test x$duplicheck = xtrue) AM_CONDITIONAL(USE_COUPLING, test x$coupling = xtrue) @@ -1302,6 +1305,7 @@ AC_OUTPUT( src/libcharon/plugins/lookip/Makefile src/libcharon/plugins/error_notify/Makefile src/libcharon/plugins/certexpire/Makefile + src/libcharon/plugins/systime_fix/Makefile src/libcharon/plugins/led/Makefile src/libcharon/plugins/duplicheck/Makefile src/libcharon/plugins/coupling/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 5203890ff..17607d954 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -506,6 +506,13 @@ if MONOLITHIC endif endif +if USE_SYSTIME_FIX + SUBDIRS += plugins/systime_fix +if MONOLITHIC + libcharon_la_LIBADD += plugins/systime_fix/libstrongswan-systime-fix.la +endif +endif + if USE_LED SUBDIRS += plugins/led if MONOLITHIC diff --git a/src/libcharon/plugins/systime_fix/Makefile.am b/src/libcharon/plugins/systime_fix/Makefile.am new file mode 100644 index 000000000..49dafbdae --- /dev/null +++ b/src/libcharon/plugins/systime_fix/Makefile.am @@ -0,0 +1,14 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-systime-fix.la +else +plugin_LTLIBRARIES = libstrongswan-systime-fix.la +endif + +libstrongswan_systime_fix_la_SOURCES = \ + systime_fix_plugin.h systime_fix_plugin.c + +libstrongswan_systime_fix_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c new file mode 100644 index 000000000..b78ebab35 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "systime_fix_plugin.h" + +#include + +typedef struct private_systime_fix_plugin_t private_systime_fix_plugin_t; + +/** + * Private data of systime_fix plugin + */ +struct private_systime_fix_plugin_t { + + /** + * Implements plugin interface + */ + systime_fix_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_systime_fix_plugin_t *this) +{ + return "systime-fix"; +} + +METHOD(plugin_t, destroy, void, + private_systime_fix_plugin_t *this) +{ + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *systime_fix_plugin_create() +{ + private_systime_fix_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.h b/src/libcharon/plugins/systime_fix/systime_fix_plugin.h new file mode 100644 index 000000000..402659539 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup systime_fix systime_fix + * @ingroup cplugins + * + * @defgroup systime_fix_plugin systime_fix_plugin + * @{ @ingroup systime_fix + */ + +#ifndef SYSTIME_FIX_PLUGIN_H_ +#define SYSTIME_FIX_PLUGIN_H_ + +#include + +typedef struct systime_fix_plugin_t systime_fix_plugin_t; + +/** + * Plugin handling cert lifetimes gracefully if system time is out of sync. + */ +struct systime_fix_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** SYSTIME_FIX_PLUGIN_H_ @}*/ From 295e42a47f9a46366209c076f6542459d65a4a38 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 19 Feb 2013 15:38:28 +0100 Subject: [PATCH 4/4] systime-fix disables certificate lifetime validation if system time not synced The system time can be periodically checked. If it gets valid, certificates get rechecked with the current lifetime. If certificates are invalid, associated IKE_SAs can be closed or reauthenticated. --- src/libcharon/plugins/systime_fix/Makefile.am | 1 + .../plugins/systime_fix/systime_fix_plugin.c | 193 ++++++++++++++++++ .../systime_fix/systime_fix_validator.c | 83 ++++++++ .../systime_fix/systime_fix_validator.h | 49 +++++ 4 files changed, 326 insertions(+) create mode 100644 src/libcharon/plugins/systime_fix/systime_fix_validator.c create mode 100644 src/libcharon/plugins/systime_fix/systime_fix_validator.h diff --git a/src/libcharon/plugins/systime_fix/Makefile.am b/src/libcharon/plugins/systime_fix/Makefile.am index 49dafbdae..a1f843db7 100644 --- a/src/libcharon/plugins/systime_fix/Makefile.am +++ b/src/libcharon/plugins/systime_fix/Makefile.am @@ -9,6 +9,7 @@ plugin_LTLIBRARIES = libstrongswan-systime-fix.la endif libstrongswan_systime_fix_la_SOURCES = \ + systime_fix_validator.h systime_fix_validator.c \ systime_fix_plugin.h systime_fix_plugin.c libstrongswan_systime_fix_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c index b78ebab35..7727ba03b 100644 --- a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c @@ -14,8 +14,20 @@ */ #include "systime_fix_plugin.h" +#include "systime_fix_validator.h" #include +#include +#include +#include + +#include + +/** + * Defining _XOPEN_SOURCE is difficult with libstrongswan includes, + * declare function explicitly. + */ +char *strptime(const char *s, const char *format, struct tm *tm); typedef struct private_systime_fix_plugin_t private_systime_fix_plugin_t; @@ -28,6 +40,26 @@ struct private_systime_fix_plugin_t { * Implements plugin interface */ systime_fix_plugin_t public; + + /** + * Certificate lifetime validator + */ + systime_fix_validator_t *validator; + + /** + * Interval we check for a now-valid system time, in seconds. 0 if disabled + */ + u_int interval; + + /** + * Timestamp where we start considering system time valid + */ + time_t threshold; + + /** + * Do we trigger reauth or delete when finding expired certificates? + */ + bool reauth; }; METHOD(plugin_t, get_name, char*, @@ -39,9 +71,155 @@ METHOD(plugin_t, get_name, char*, METHOD(plugin_t, destroy, void, private_systime_fix_plugin_t *this) { + if (this->validator) + { + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + this->validator->destroy(this->validator); + } free(this); } +/** + * Check if all certificates associated to an IKE_SA have valid lifetimes + */ +static bool has_invalid_certs(ike_sa_t *ike_sa) +{ + enumerator_t *cfgs, *items; + certificate_t *cert; + auth_rule_t type; + auth_cfg_t *auth; + time_t not_before, not_after; + bool valid = TRUE; + + cfgs = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE); + while (valid && cfgs->enumerate(cfgs, &auth)) + { + items = auth->create_enumerator(auth); + while (valid && items->enumerate(items, &type, &cert)) + { + switch (type) + { + case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_IM_CERT: + case AUTH_RULE_CA_CERT: + if (!cert->get_validity(cert, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "certificate '%Y' invalid " + "(valid from %T to %T)", cert->get_subject(cert), + ¬_before, FALSE, ¬_after, FALSE); + valid = FALSE; + } + break; + default: + break; + } + } + items->destroy(items); + } + cfgs->destroy(cfgs); + + if (valid) + { + DBG1(DBG_CFG, "all certificates have valid lifetimes"); + } + return !valid; +} + +/** + * Check system time, reevaluate certificates + */ +static job_requeue_t check_systime(private_systime_fix_plugin_t *this) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + char *action; + job_t *job; + + if (time(NULL) < this->threshold) + { + DBG2(DBG_CFG, "systime not valid, rechecking in %ds", this->interval); + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)check_systime, this, + NULL, NULL), this->interval); + return JOB_REQUEUE_NONE; + } + + DBG1(DBG_CFG, "system time got valid, rechecking certificates"); + + enumerator = charon->ike_sa_manager->create_enumerator( + charon->ike_sa_manager, TRUE); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (has_invalid_certs(ike_sa)) + { + if (this->reauth) + { + action = "reauthenticating"; + job = &rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), + TRUE)->job_interface; + } + else + { + action = "deleting"; + job = &delete_ike_sa_job_create(ike_sa->get_id(ike_sa), + TRUE)->job_interface; + } + DBG1(DBG_CFG, "%s[%d] has certificates not valid, %s IKE_SA", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), + action); + lib->processor->queue_job(lib->processor, job); + } + } + enumerator->destroy(enumerator); + + return JOB_REQUEUE_NONE; +} + +/** + * Load cert lifetime validator configuration + */ +static bool load_validator(private_systime_fix_plugin_t *this) +{ + struct tm tm = { + .tm_mday = 1, + }; + char *str, *fmt; + + fmt = lib->settings->get_str(lib->settings, + "%s.plugins.%s.threshold_format", "%Y", charon->name, get_name(this)); + str = lib->settings->get_str(lib->settings, + "%s.plugins.%s.threshold", NULL, charon->name, get_name(this)); + if (!str) + { + DBG1(DBG_CFG, "no threshold configured for %s, disabled", + get_name(this)); + return FALSE; + } + if (strptime(str, fmt, &tm) == NULL) + { + DBG1(DBG_CFG, "threshold for %s invalid, disabled", get_name(this)); + return FALSE; + } + this->threshold = mktime(&tm); + if (this->threshold == -1) + { + DBG1(DBG_CFG, "converting threshold for %s failed, disabled", + get_name(this)); + return FALSE; + } + if (time(NULL) >= this->threshold) + { + DBG1(DBG_CFG, "system time looks good, disabling %s", get_name(this)); + return FALSE; + } + + DBG1(DBG_CFG, "enabling %s, threshold: %s", get_name(this), asctime(&tm)); + this->validator = systime_fix_validator_create(this->threshold); + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + + return TRUE; +} + /** * Plugin constructor */ @@ -57,7 +235,22 @@ plugin_t *systime_fix_plugin_create() .destroy = _destroy, }, }, + .interval = lib->settings->get_int(lib->settings, + "%s.plugins.%s.interval", 0, charon->name, get_name(this)), + .reauth = lib->settings->get_bool(lib->settings, + "%s.plugins.%s.reauth", FALSE, charon->name, get_name(this)), ); + if (load_validator(this)) + { + if (this->interval != 0) + { + DBG1(DBG_CFG, "starting systime check, interval: %ds", + this->interval); + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)check_systime, this, + NULL, NULL), this->interval); + } + } return &this->public.plugin; } diff --git a/src/libcharon/plugins/systime_fix/systime_fix_validator.c b/src/libcharon/plugins/systime_fix/systime_fix_validator.c new file mode 100644 index 000000000..340e86cbc --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_validator.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "systime_fix_validator.h" + +#include +#include + +#include + +typedef struct private_systime_fix_validator_t private_systime_fix_validator_t; + +/** + * Private data of an systime_fix_validator_t object. + */ +struct private_systime_fix_validator_t { + + /** + * Public systime_fix_validator_t interface. + */ + systime_fix_validator_t public; + + /** + * Timestamp where we start to consider system time valid + */ + time_t threshold; +}; + +METHOD(cert_validator_t, check_lifetime, status_t, + private_systime_fix_validator_t *this, certificate_t *cert, + int pathlen, bool anchor, auth_cfg_t *auth) +{ + if (time(NULL) < this->threshold) + { + /* our system time seems to be invalid, accept certificate */ + if (pathlen) + { /* report only once per validated chain */ + DBG1(DBG_CFG, "system time out of sync, skipping certificate " + "lifetime check"); + } + return SUCCESS; + } + /* validate this certificate normally */ + return NEED_MORE; +} + +METHOD(systime_fix_validator_t, destroy, void, + private_systime_fix_validator_t *this) +{ + free(this); +} + +/** + * See header + */ +systime_fix_validator_t *systime_fix_validator_create(time_t threshold) +{ + private_systime_fix_validator_t *this; + + INIT(this, + .public = { + .validator = { + .check_lifetime = _check_lifetime, + }, + .destroy = _destroy, + }, + .threshold = threshold, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/systime_fix/systime_fix_validator.h b/src/libcharon/plugins/systime_fix/systime_fix_validator.h new file mode 100644 index 000000000..3e651fd91 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup systime_fix_validator systime_fix_validator + * @{ @ingroup systime_fix + */ + +#ifndef SYSTIME_FIX_VALIDATOR_H_ +#define SYSTIME_FIX_VALIDATOR_H_ + +#include + +typedef struct systime_fix_validator_t systime_fix_validator_t; + +/** + * Validator that accepts cert lifetimes if system time is out of sync. + */ +struct systime_fix_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a systime_fix_validator_t. + */ + void (*destroy)(systime_fix_validator_t *this); +}; + +/** + * Create a systime_fix_validator instance. + */ +systime_fix_validator_t *systime_fix_validator_create(); + +#endif /** SYSTIME_FIX_VALIDATOR_H_ @}*/