diff --git a/src/charon/daemon.c b/src/charon/daemon.c index b3adf3e89..6d915873b 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -39,6 +39,7 @@ #include "daemon.h" #include +#include #include #include #include @@ -379,6 +380,8 @@ static void usage(const char *msg) " [--help]\n" " [--version]\n" " [--strictcrlpolicy]\n" + " [--crlcheckinterval ]\n" + " [--eapdir ]\n" " [--use-syslog]\n" " [--debug- ]\n" " : log context type (dmn|mgr|ike|chd|job|cfg|knl|net|enc|lib)\n" @@ -394,6 +397,7 @@ static void usage(const char *msg) */ int main(int argc, char *argv[]) { + u_int crl_check_interval = 0; bool strict_crl_policy = FALSE; bool use_syslog = FALSE; char *eapdir = IPSEC_EAPDIR; @@ -420,6 +424,7 @@ int main(int argc, char *argv[]) { "version", no_argument, NULL, 'v' }, { "use-syslog", no_argument, NULL, 'l' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, + { "crlcheckinterval", required_argument, NULL, 'x' }, { "eapdir", required_argument, NULL, 'e' }, /* TODO: handle "debug-all" */ { "debug-dmn", required_argument, &signal, DBG_DMN }, @@ -452,6 +457,9 @@ int main(int argc, char *argv[]) case 'r': strict_crl_policy = TRUE; continue; + case 'x': + crl_check_interval = atoi(optarg); + continue; case 'e': eapdir = optarg; continue; @@ -471,9 +479,13 @@ int main(int argc, char *argv[]) /* initialize daemon */ initialize(private_charon, strict_crl_policy, use_syslog, levels); + /* load pluggable EAP modules */ eap_method_load(eapdir); + /* set crl_check_interval */ + ca_info_set_crlcheckinterval(crl_check_interval); + /* check/setup PID file */ if (stat(PID_FILE, &stb) == 0) { diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index 765bae4b4..cf3d0eea6 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -91,6 +91,11 @@ struct private_ca_info_t { pthread_mutex_t mutex; }; +/** + * static value set by ca_info_set_crl() + */ +static crl_check_interval = 0; + /** * Implements ca_info_t.equals */ @@ -379,14 +384,14 @@ static x509_t* get_certificate(private_ca_info_t* this) static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo) { + rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert); bool stale; pthread_mutex_lock(&(this->mutex)); - if (this->crl == NULL) { stale = TRUE; - DBG1("crl is not locally available"); + DBG1("no crl is locally available"); } else { @@ -394,7 +399,7 @@ static cert_status_t verify_by_crl(private_ca_info_t* this, DBG1("crl is %s", stale? "stale":"valid"); } - if (stale) + if (stale && crl_check_interval > 0) { iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE); identification_t *uri; @@ -414,37 +419,50 @@ static cert_status_t verify_by_crl(private_ca_info_t* this, if (response_chunk.ptr != NULL) { crl_t *crl = crl_create_from_chunk(response_chunk); - - if (crl) + + if (crl == NULL) { - if (this->crl == NULL) + free(response_chunk.ptr); + continue; + } + if (!is_crl_issuer(this, crl)) + { + DBG1(" fetched crl has wrong issuer"); + crl->destroy(crl); + continue; + } + if (!crl->verify(crl, issuer_public_key)) + { + DBG1("fetched crl signature is invalid"); + crl->destroy(crl); + continue; + } + DBG2("fetched crl signature is valid"); + + if (this->crl == NULL) + { + this->crl = crl; + } + else if (crl->is_newer(crl, this->crl)) + { + this->crl->destroy(this->crl); + this->crl = crl; + DBG1(" thisUpdate is newer - existing crl replaced"); + if (this->crl->is_valid(this->crl)) { - this->crl = crl; - } - else if (crl->is_newer(crl, this->crl)) - { - this->crl->destroy(this->crl); - this->crl = crl; - DBG1(" thisUpdate is newer - existing crl replaced"); - if (this->crl->is_valid(this->crl)) - { - break; - } - else - { - DBG1("fetched crl is stale"); - } + /* we found a valid crl and exit the fetch loop */ + break; } else { - crl->destroy(crl); - DBG1(" thisUpdate is not newer - existing crl retained"); + DBG1("fetched crl is stale"); } } else { - free(response_chunk.ptr); - }; + crl->destroy(crl); + DBG1("thisUpdate is not newer - existing crl retained"); + } } } iterator->destroy(iterator); @@ -452,12 +470,7 @@ static cert_status_t verify_by_crl(private_ca_info_t* this, if (this->crl) { - rsa_public_key_t *issuer_public_key; - bool valid_signature; - - issuer_public_key = this->cacert->get_public_key(this->cacert); - valid_signature = this->crl->verify(this->crl, issuer_public_key); - if (!valid_signature) + if (!this->crl->verify(this->crl, issuer_public_key)) { DBG1("crl signature is invalid"); goto ret; @@ -666,6 +679,14 @@ static void __attribute__ ((constructor))print_register() register_printf_function(PRINTF_CAINFO, print, arginfo_ptr_alt_ptr_int); } +/* + * Described in header. + */ +void ca_info_set_crlcheckinterval(u_int interval) +{ + crl_check_interval = interval; +} + /* * Described in header. */ diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index 440ac4f0b..832fa9883 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -190,6 +190,15 @@ struct ca_info_t { void (*destroy) (ca_info_t *this); }; +/** + * @brief Create a ca info record + * + * @param interval crl_check_interval to be set in seconds + * + * @ingroup crypto + */ +void ca_info_set_crlcheckinterval(u_int interval); + /** * @brief Create a ca info record * @@ -197,7 +206,7 @@ struct ca_info_t { * @param cacert path to the ca certificate * @return created ca_info_t, or NULL if invalid. * - * @ingroup transforms + * @ingroup crypto */ ca_info_t *ca_info_create(const char *name, x509_t *cacert); diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 09f8c61d8..e235ff765 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -81,7 +81,7 @@ usage(const char *mess) " [--nocrsend]" " \\\n\t" "[--strictcrlpolicy]" - " [--crlcheckinterval]" + " [--crlcheckinterval ]" " [--cachecrls]" " [--uniqueids]" " \\\n\t" diff --git a/src/starter/invokecharon.c b/src/starter/invokecharon.c index 1fceae7e8..a490882b5 100644 --- a/src/starter/invokecharon.c +++ b/src/starter/invokecharon.c @@ -116,6 +116,14 @@ starter_start_charon (starter_config_t *cfg, bool debug) { arg[argc++] = "--strictcrlpolicy"; } + if (cfg->setup.crlcheckinterval > 0) + { + char buffer[BUF_LEN]; + + snprintf(buffer, BUF_LEN, "%u", cfg->setup.crlcheckinterval); + arg[argc++] = "--crlcheckinterval"; + arg[argc++] = buffer; + } if (cfg->setup.eapdir) { arg[argc++] = "--eapdir"; @@ -123,7 +131,7 @@ starter_start_charon (starter_config_t *cfg, bool debug) } { /* parse debug string */ - char *pos, *level, *buf_pos, type[4], buffer[512]; + char *pos, *level, *buf_pos, type[4], buffer[BUF_LEN]; pos = cfg->setup.charondebug; buf_pos = buffer; while (pos && sscanf(pos, "%4s %d,", type, &level) == 2)