diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2007-04-05 17:07:14 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2007-04-05 17:07:14 +0000 |
commit | 8883eef7b85d8cbf0daf6064d12971b35dad9921 (patch) | |
tree | f6c08234ba8e2bb5626c18400cb96664c3efa856 | |
parent | e58afb1a0aa77d7666830c4ce91e97b8154db8de (diff) | |
download | strongswan-8883eef7b85d8cbf0daf6064d12971b35dad9921.tar.bz2 strongswan-8883eef7b85d8cbf0daf6064d12971b35dad9921.tar.xz |
support cachecrls=yes
-rw-r--r-- | src/charon/config/credentials/local_credential_store.c | 18 | ||||
-rw-r--r-- | src/charon/daemon.c | 10 | ||||
-rw-r--r-- | src/libstrongswan/chunk.c | 40 | ||||
-rw-r--r-- | src/libstrongswan/chunk.h | 5 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ca.c | 89 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ca.h | 8 | ||||
-rwxr-xr-x | src/libstrongswan/crypto/crl.c | 9 | ||||
-rwxr-xr-x | src/libstrongswan/crypto/crl.h | 11 | ||||
-rw-r--r-- | src/starter/invokecharon.c | 4 |
9 files changed, 169 insertions, 25 deletions
diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index ed6a760b8..3a03f20f9 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -665,7 +665,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f /* if ocsp service is not available then fall back to crl */ if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict)) { - status = issuer->verify_by_crl(issuer, certinfo); + status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR); } nextUpdate = certinfo->get_nextUpdate(certinfo); @@ -1038,7 +1038,7 @@ static void load_ocsp_certificates(private_local_credential_store_t *this) /** * Add the latest crl to the issuing ca */ -static void add_crl(private_local_credential_store_t *this, crl_t *crl) +static void add_crl(private_local_credential_store_t *this, crl_t *crl, const char *path) { iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE); ca_info_t *ca_info; @@ -1048,8 +1048,16 @@ static void add_crl(private_local_credential_store_t *this, crl_t *crl) { if (ca_info->is_crl_issuer(ca_info, crl)) { - found = TRUE; + char buffer[BUF_LEN]; + chunk_t uri = { buffer, 7 + strlen(path) }; + ca_info->add_crl(ca_info, crl); + if (uri.len < BUF_LEN) + { + snprintf(buffer, BUF_LEN, "file://%s", path); + ca_info->add_crluri(ca_info, uri); + } + found = TRUE; break; } } @@ -1097,8 +1105,8 @@ static void load_crls(private_local_credential_store_t *this) crl = crl_create_from_file(file); if (crl) { - DBG1(DBG_CFG, "crl is %s", crl->is_valid(crl)? "valid":"stale"); - add_crl(this, crl); + DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale"); + add_crl(this, crl, file); } } } diff --git a/src/charon/daemon.c b/src/charon/daemon.c index 6d915873b..7671aea86 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -380,6 +380,7 @@ static void usage(const char *msg) " [--help]\n" " [--version]\n" " [--strictcrlpolicy]\n" + " [--cachecrls]\n" " [--crlcheckinterval <interval>]\n" " [--eapdir <dir>]\n" " [--use-syslog]\n" @@ -399,6 +400,7 @@ int main(int argc, char *argv[]) { u_int crl_check_interval = 0; bool strict_crl_policy = FALSE; + bool cache_crls = FALSE; bool use_syslog = FALSE; char *eapdir = IPSEC_EAPDIR; @@ -424,6 +426,7 @@ int main(int argc, char *argv[]) { "version", no_argument, NULL, 'v' }, { "use-syslog", no_argument, NULL, 'l' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, + { "cachecrls", no_argument, NULL, 'C' }, { "crlcheckinterval", required_argument, NULL, 'x' }, { "eapdir", required_argument, NULL, 'e' }, /* TODO: handle "debug-all" */ @@ -457,6 +460,9 @@ int main(int argc, char *argv[]) case 'r': strict_crl_policy = TRUE; continue; + case 'C': + cache_crls = TRUE; + continue; case 'x': crl_check_interval = atoi(optarg); continue; @@ -483,8 +489,8 @@ int main(int argc, char *argv[]) /* load pluggable EAP modules */ eap_method_load(eapdir); - /* set crl_check_interval */ - ca_info_set_crlcheckinterval(crl_check_interval); + /* set cache_crls and crl_check_interval options */ + ca_info_set_options(cache_crls, crl_check_interval); /* check/setup PID file */ if (stat(PID_FILE, &stb) == 0) diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c index 1967b350a..cba823c22 100644 --- a/src/libstrongswan/chunk.c +++ b/src/libstrongswan/chunk.c @@ -25,6 +25,7 @@ #include "chunk.h" +#include <debug.h> #include <printf_hook.h> /** @@ -205,6 +206,45 @@ void chunk_split(chunk_t chunk, const char *mode, ...) va_end(chunks); } +/** + * Described in header. + */ +bool chunk_write(chunk_t chunk, const char *path, const char *label, mode_t mask, bool force) +{ + mode_t oldmask; + FILE *fd; + + if (!force) + { + fd = fopen(path, "r"); + if (fd) + { + fclose(fd); + DBG1(" %s file '%s' already exists", label, path); + return FALSE; + } + } + + /* set umask */ + oldmask = umask(mask); + + fd = fopen(path, "w"); + + if (fd) + { + fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd); + fclose(fd); + DBG1(" written %s file '%s' (%u bytes)", label, path, chunk.len); + umask(oldmask); + return TRUE; + } + else + { + DBG1(" could not open %s file '%s' for writing", label, path); + umask(oldmask); + return FALSE; + } +} /** * Described in header. diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h index e4e816f0f..a13ccfc22 100644 --- a/src/libstrongswan/chunk.h +++ b/src/libstrongswan/chunk.h @@ -79,6 +79,11 @@ chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...); void chunk_split(chunk_t chunk, const char *mode, ...); /** + * Write the binary contents of a chunk_t to a file + */ +bool chunk_write(chunk_t chunk, const char *path, const char *label, mode_t mask, bool force); + +/** * Free contents of a chunk */ void chunk_free(chunk_t *chunk); diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index cf3d0eea6..4ec8c8430 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -92,9 +92,10 @@ struct private_ca_info_t { }; /** - * static value set by ca_info_set_crl() + * static options set by ca_info_set_options() */ -static crl_check_interval = 0; +static bool cache_crls = FALSE; +static u_int crl_check_interval = 0; /** * Implements ca_info_t.equals @@ -379,10 +380,62 @@ static x509_t* get_certificate(private_ca_info_t* this) } /** + * caches a crl by saving it to a given crl directory + */ +void cache_crl(private_ca_info_t* this, const char *crl_dir, crl_t *crl) +{ + char buffer[BUF_LEN]; + char *path; + char *pos = buffer; + int len = BUF_LEN; + int n; + + chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert); + chunk_t uri; + + uri.ptr = buffer; + uri.len = 7 + strlen(crl_dir) + 1 + 2*authKeyID.len + 4; + + if (uri.len >= BUF_LEN) + { + DBG1("file uri exceeds buffer length of %d bytes - crl not saved", BUF_LEN); + return; + } + + /* print the file uri prefix */ + n = snprintf(pos, len, "file://"); + pos += n; len -= n; + + /* remember the start of the path string */ + path = pos; + + /* print the default crl directory path */ + n = snprintf(pos, len, "%s/", crl_dir); + pos += n; len -= n; + + /* create and print a unique crl filename derived from the authKeyID */ + while (authKeyID.len-- > 0) + { + n = snprintf(pos, len, "%02x", *authKeyID.ptr++); + pos += n; len -= n; + } + + /* add the file suffix */ + n = snprintf(pos, len, ".crl"); + + if (crl->write_to_file(crl, path, 0022, TRUE)) + { + identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); + + add_identification(this->crluris, crluri); + } +} + +/** * Implements ca_info_t.verify_by_crl. */ -static cert_status_t verify_by_crl(private_ca_info_t* this, - certinfo_t *certinfo) +static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo, + const char *crl_dir) { rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert); bool stale; @@ -448,20 +501,25 @@ static cert_status_t verify_by_crl(private_ca_info_t* this, this->crl->destroy(this->crl); this->crl = crl; DBG1(" thisUpdate is newer - existing crl replaced"); - if (this->crl->is_valid(this->crl)) - { - /* we found a valid crl and exit the fetch loop */ - break; - } - else - { - DBG1("fetched crl is stale"); - } } else { crl->destroy(crl); DBG1("thisUpdate is not newer - existing crl retained"); + continue; + } + if (crl->is_valid(crl)) + { + if (cache_crls && strncasecmp(uri_string, "file", 4) != 0) + { + cache_crl(this, crl_dir, crl); + } + /* we found a valid crl and therefore exit the fetch loop */ + break; + } + else + { + DBG1("fetched crl is stale"); } } } @@ -682,8 +740,9 @@ static void __attribute__ ((constructor))print_register() /* * Described in header. */ -void ca_info_set_crlcheckinterval(u_int interval) +void ca_info_set_options(bool cache, u_int interval) { + cache_crls = cache; crl_check_interval = interval; } @@ -720,7 +779,7 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert) this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri; this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate; - this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*))verify_by_crl; + this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*, const char*))verify_by_crl; this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,certinfo_t*,credential_store_t*))verify_by_ocsp; this->public.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp; this->public.destroy = (void (*) (ca_info_t*))destroy; diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index 832fa9883..c494a4468 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -161,9 +161,10 @@ struct ca_info_t { * * @param this ca info object * @param certinfo detailed certificate status information + * @param crl_dir directory where fetched crls should be stored * @return certificate status */ - cert_status_t (*verify_by_crl) (ca_info_t* this, certinfo_t* certinfo); + cert_status_t (*verify_by_crl) (ca_info_t *this, certinfo_t *certinfo, const char *crl_dir); /** * @brief Verify the status of a certificate by OCSP @@ -191,13 +192,14 @@ struct ca_info_t { }; /** - * @brief Create a ca info record + * @brief Set ca info options * + * @param cache TRUE if crls shall be cached by storing them * @param interval crl_check_interval to be set in seconds * * @ingroup crypto */ -void ca_info_set_crlcheckinterval(u_int interval); +void ca_info_set_options(bool cache, u_int interval); /** * @brief Create a ca info record diff --git a/src/libstrongswan/crypto/crl.c b/src/libstrongswan/crypto/crl.c index 0b9fdaf4f..00d6a3ac3 100755 --- a/src/libstrongswan/crypto/crl.c +++ b/src/libstrongswan/crypto/crl.c @@ -395,6 +395,14 @@ static void get_status(const private_crl_t *this, certinfo_t *certinfo) } /** + * Implements crl_t.write_to_file. + */ +static bool write_to_file(private_crl_t *this, const char *path, mode_t mask, bool force) +{ + return chunk_write(this->certificateList, path, "crl", mask, force); +} + +/** * Implements crl_t.destroy */ static void destroy(private_crl_t *this) @@ -493,6 +501,7 @@ crl_t *crl_create_from_chunk(chunk_t chunk) this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer; this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify; this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status; + this->public.write_to_file = (bool (*) (const crl_t*,const char*,mode_t,bool))write_to_file; this->public.destroy = (void (*) (crl_t*))destroy; if (!parse_x509crl(chunk, 0, this)) diff --git a/src/libstrongswan/crypto/crl.h b/src/libstrongswan/crypto/crl.h index 48953ba78..8a11fc390 100755 --- a/src/libstrongswan/crypto/crl.h +++ b/src/libstrongswan/crypto/crl.h @@ -106,6 +106,17 @@ struct crl_t { void (*get_status) (const crl_t *this, certinfo_t *certinfo); /** + * @brief Write a der-encoded crl to a file + * + * @param this calling object + * @param path path where the file is to be stored + * @param mask file access control rights + * @param force overwrite the file if it already exists + * @return TRUE if successfully written + */ + bool (*write_to_file) (const crl_t *this, const char *path, mode_t mask, bool force); + + /** * @brief Destroys the crl. * * @param this crl to destroy diff --git a/src/starter/invokecharon.c b/src/starter/invokecharon.c index a490882b5..e97c8388b 100644 --- a/src/starter/invokecharon.c +++ b/src/starter/invokecharon.c @@ -116,6 +116,10 @@ starter_start_charon (starter_config_t *cfg, bool debug) { arg[argc++] = "--strictcrlpolicy"; } + if (cfg->setup.cachecrls) + { + arg[argc++] = "--cachecrls"; + } if (cfg->setup.crlcheckinterval > 0) { char buffer[BUF_LEN]; |