support cachecrls=yes

This commit is contained in:
Andreas Steffen 2007-04-05 17:07:14 +00:00
parent e58afb1a0a
commit 8883eef7b8
9 changed files with 169 additions and 25 deletions

View File

@ -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 ocsp service is not available then fall back to crl */
if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict)) 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); 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 * 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); iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
ca_info_t *ca_info; 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)) 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); 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; break;
} }
} }
@ -1097,8 +1105,8 @@ static void load_crls(private_local_credential_store_t *this)
crl = crl_create_from_file(file); crl = crl_create_from_file(file);
if (crl) if (crl)
{ {
DBG1(DBG_CFG, "crl is %s", crl->is_valid(crl)? "valid":"stale"); DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale");
add_crl(this, crl); add_crl(this, crl, file);
} }
} }
} }

View File

@ -380,6 +380,7 @@ static void usage(const char *msg)
" [--help]\n" " [--help]\n"
" [--version]\n" " [--version]\n"
" [--strictcrlpolicy]\n" " [--strictcrlpolicy]\n"
" [--cachecrls]\n"
" [--crlcheckinterval <interval>]\n" " [--crlcheckinterval <interval>]\n"
" [--eapdir <dir>]\n" " [--eapdir <dir>]\n"
" [--use-syslog]\n" " [--use-syslog]\n"
@ -399,6 +400,7 @@ int main(int argc, char *argv[])
{ {
u_int crl_check_interval = 0; u_int crl_check_interval = 0;
bool strict_crl_policy = FALSE; bool strict_crl_policy = FALSE;
bool cache_crls = FALSE;
bool use_syslog = FALSE; bool use_syslog = FALSE;
char *eapdir = IPSEC_EAPDIR; char *eapdir = IPSEC_EAPDIR;
@ -424,6 +426,7 @@ int main(int argc, char *argv[])
{ "version", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'v' },
{ "use-syslog", no_argument, NULL, 'l' }, { "use-syslog", no_argument, NULL, 'l' },
{ "strictcrlpolicy", no_argument, NULL, 'r' }, { "strictcrlpolicy", no_argument, NULL, 'r' },
{ "cachecrls", no_argument, NULL, 'C' },
{ "crlcheckinterval", required_argument, NULL, 'x' }, { "crlcheckinterval", required_argument, NULL, 'x' },
{ "eapdir", required_argument, NULL, 'e' }, { "eapdir", required_argument, NULL, 'e' },
/* TODO: handle "debug-all" */ /* TODO: handle "debug-all" */
@ -457,6 +460,9 @@ int main(int argc, char *argv[])
case 'r': case 'r':
strict_crl_policy = TRUE; strict_crl_policy = TRUE;
continue; continue;
case 'C':
cache_crls = TRUE;
continue;
case 'x': case 'x':
crl_check_interval = atoi(optarg); crl_check_interval = atoi(optarg);
continue; continue;
@ -483,8 +489,8 @@ int main(int argc, char *argv[])
/* load pluggable EAP modules */ /* load pluggable EAP modules */
eap_method_load(eapdir); eap_method_load(eapdir);
/* set crl_check_interval */ /* set cache_crls and crl_check_interval options */
ca_info_set_crlcheckinterval(crl_check_interval); ca_info_set_options(cache_crls, crl_check_interval);
/* check/setup PID file */ /* check/setup PID file */
if (stat(PID_FILE, &stb) == 0) if (stat(PID_FILE, &stb) == 0)

View File

@ -25,6 +25,7 @@
#include "chunk.h" #include "chunk.h"
#include <debug.h>
#include <printf_hook.h> #include <printf_hook.h>
/** /**
@ -205,6 +206,45 @@ void chunk_split(chunk_t chunk, const char *mode, ...)
va_end(chunks); 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. * Described in header.

View File

@ -78,6 +78,11 @@ chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
*/ */
void chunk_split(chunk_t chunk, 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 * Free contents of a chunk
*/ */

View File

@ -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 * Implements ca_info_t.equals
@ -378,11 +379,63 @@ static x509_t* get_certificate(private_ca_info_t* this)
return this->cacert; return this->cacert;
} }
/**
* 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. * Implements ca_info_t.verify_by_crl.
*/ */
static cert_status_t verify_by_crl(private_ca_info_t* this, static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo,
certinfo_t *certinfo) const char *crl_dir)
{ {
rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert); rsa_public_key_t *issuer_public_key = this->cacert->get_public_key(this->cacert);
bool stale; 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->destroy(this->crl);
this->crl = crl; this->crl = crl;
DBG1(" thisUpdate is newer - existing crl replaced"); 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 else
{ {
crl->destroy(crl); crl->destroy(crl);
DBG1("thisUpdate is not newer - existing crl retained"); 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. * 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; 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_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri;
this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; 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.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.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.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp;
this->public.destroy = (void (*) (ca_info_t*))destroy; this->public.destroy = (void (*) (ca_info_t*))destroy;

View File

@ -161,9 +161,10 @@ struct ca_info_t {
* *
* @param this ca info object * @param this ca info object
* @param certinfo detailed certificate status information * @param certinfo detailed certificate status information
* @param crl_dir directory where fetched crls should be stored
* @return certificate status * @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 * @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 * @param interval crl_check_interval to be set in seconds
* *
* @ingroup crypto * @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 * @brief Create a ca info record

View File

@ -394,6 +394,14 @@ static void get_status(const private_crl_t *this, certinfo_t *certinfo)
iterator->destroy(iterator); iterator->destroy(iterator);
} }
/**
* 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 * Implements crl_t.destroy
*/ */
@ -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.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.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.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; this->public.destroy = (void (*) (crl_t*))destroy;
if (!parse_x509crl(chunk, 0, this)) if (!parse_x509crl(chunk, 0, this))

View File

@ -105,6 +105,17 @@ struct crl_t {
*/ */
void (*get_status) (const crl_t *this, certinfo_t *certinfo); 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. * @brief Destroys the crl.
* *

View File

@ -116,6 +116,10 @@ starter_start_charon (starter_config_t *cfg, bool debug)
{ {
arg[argc++] = "--strictcrlpolicy"; arg[argc++] = "--strictcrlpolicy";
} }
if (cfg->setup.cachecrls)
{
arg[argc++] = "--cachecrls";
}
if (cfg->setup.crlcheckinterval > 0) if (cfg->setup.crlcheckinterval > 0)
{ {
char buffer[BUF_LEN]; char buffer[BUF_LEN];