aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2007-04-05 17:07:14 +0000
committerAndreas Steffen <andreas.steffen@strongswan.org>2007-04-05 17:07:14 +0000
commit8883eef7b85d8cbf0daf6064d12971b35dad9921 (patch)
treef6c08234ba8e2bb5626c18400cb96664c3efa856
parente58afb1a0aa77d7666830c4ce91e97b8154db8de (diff)
downloadstrongswan-8883eef7b85d8cbf0daf6064d12971b35dad9921.tar.bz2
strongswan-8883eef7b85d8cbf0daf6064d12971b35dad9921.tar.xz
support cachecrls=yes
-rw-r--r--src/charon/config/credentials/local_credential_store.c18
-rw-r--r--src/charon/daemon.c10
-rw-r--r--src/libstrongswan/chunk.c40
-rw-r--r--src/libstrongswan/chunk.h5
-rw-r--r--src/libstrongswan/crypto/ca.c89
-rw-r--r--src/libstrongswan/crypto/ca.h8
-rwxr-xr-xsrc/libstrongswan/crypto/crl.c9
-rwxr-xr-xsrc/libstrongswan/crypto/crl.h11
-rw-r--r--src/starter/invokecharon.c4
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];