use credential builder to build crls
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "id.h"
|
||||
#include "certs.h"
|
||||
#include "ac.h"
|
||||
#include "crl.h"
|
||||
|
||||
/**
|
||||
* currently building cert_t
|
||||
@@ -191,17 +192,88 @@ static builder_t *ac_builder(credential_type_t type, int subtype)
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* currently building x509crl_t
|
||||
*/
|
||||
static x509crl_t *crl;
|
||||
|
||||
/**
|
||||
* builder add function
|
||||
*/
|
||||
static void crl_add(builder_t *this, builder_part_t part, ...)
|
||||
{
|
||||
chunk_t blob;
|
||||
va_list args;
|
||||
|
||||
switch (part)
|
||||
{
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
{
|
||||
va_start(args, part);
|
||||
blob = va_arg(args, chunk_t);
|
||||
va_end(args);
|
||||
|
||||
crl = malloc_thing(x509crl_t);
|
||||
*crl = empty_x509crl;
|
||||
|
||||
if (!parse_x509crl(blob, 0, crl))
|
||||
{
|
||||
plog(" error in X.509 crl");
|
||||
free_crl(crl);
|
||||
crl = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
builder_cancel(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* builder build function
|
||||
*/
|
||||
static void *crl_build(builder_t *this)
|
||||
{
|
||||
free(this);
|
||||
return crl;
|
||||
}
|
||||
|
||||
/**
|
||||
* CRL builder in x509crl_t format.
|
||||
*/
|
||||
static builder_t *crl_builder(credential_type_t type, int subtype)
|
||||
{
|
||||
builder_t *this;
|
||||
|
||||
if (subtype != CRED_TYPE_CRL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
this = malloc_thing(builder_t);
|
||||
this->add = crl_add;
|
||||
this->build = crl_build;
|
||||
|
||||
crl = NULL;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
void init_builder(void)
|
||||
{
|
||||
lib->creds->add_builder(lib->creds, CRED_PLUTO_CERT, CRED_TYPE_CERTIFICATE,
|
||||
(builder_constructor_t)cert_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PLUTO_CERT, CRED_TYPE_AC,
|
||||
(builder_constructor_t)ac_builder);
|
||||
lib->creds->add_builder(lib->creds, CRED_PLUTO_CERT, CRED_TYPE_CRL,
|
||||
(builder_constructor_t)crl_builder);
|
||||
}
|
||||
|
||||
void free_builder(void)
|
||||
{
|
||||
lib->creds->remove_builder(lib->creds, (builder_constructor_t)cert_builder);
|
||||
lib->creds->remove_builder(lib->creds, (builder_constructor_t)ac_builder);
|
||||
lib->creds->remove_builder(lib->creds, (builder_constructor_t)crl_builder);
|
||||
}
|
||||
|
||||
|
||||
+105
-116
@@ -39,6 +39,7 @@
|
||||
#include "keys.h"
|
||||
#include "whack.h"
|
||||
#include "fetch.h"
|
||||
#include "builder.h"
|
||||
|
||||
|
||||
/* chained lists of X.509 crls */
|
||||
@@ -202,127 +203,114 @@ void free_crls(void)
|
||||
/**
|
||||
* Insert X.509 CRL into chained list
|
||||
*/
|
||||
bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl)
|
||||
bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl)
|
||||
{
|
||||
x509crl_t *crl = malloc_thing(x509crl_t);
|
||||
x509cert_t *issuer_cert;
|
||||
x509crl_t *oldcrl;
|
||||
bool valid_sig;
|
||||
generalName_t *gn;
|
||||
|
||||
*crl = empty_x509crl;
|
||||
/* add distribution point */
|
||||
gn = malloc_thing(generalName_t);
|
||||
gn->kind = GN_URI;
|
||||
gn->name = crl_uri;
|
||||
gn->next = crl->distributionPoints;
|
||||
crl->distributionPoints = gn;
|
||||
|
||||
if (parse_x509crl(blob, 0, crl))
|
||||
lock_authcert_list("insert_crl");
|
||||
/* get the issuer cacert */
|
||||
issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
|
||||
crl->authKeyID, AUTH_CA);
|
||||
if (issuer_cert == NULL)
|
||||
{
|
||||
x509cert_t *issuer_cert;
|
||||
x509crl_t *oldcrl;
|
||||
bool valid_sig;
|
||||
generalName_t *gn;
|
||||
|
||||
/* add distribution point */
|
||||
gn = malloc_thing(generalName_t);
|
||||
gn->kind = GN_URI;
|
||||
gn->name = crl_uri;
|
||||
gn->next = crl->distributionPoints;
|
||||
crl->distributionPoints = gn;
|
||||
|
||||
lock_authcert_list("insert_crl");
|
||||
/* get the issuer cacert */
|
||||
issuer_cert = get_authcert(crl->issuer, crl->authKeySerialNumber,
|
||||
crl->authKeyID, AUTH_CA);
|
||||
if (issuer_cert == NULL)
|
||||
{
|
||||
plog("crl issuer cacert not found");
|
||||
free_crl(crl);
|
||||
unlock_authcert_list("insert_crl");
|
||||
return FALSE;
|
||||
}
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("crl issuer cacert found")
|
||||
)
|
||||
|
||||
/* check the issuer's signature of the crl */
|
||||
valid_sig = x509_check_signature(crl->tbsCertList, crl->signature,
|
||||
crl->algorithm, issuer_cert);
|
||||
plog("crl issuer cacert not found");
|
||||
free_crl(crl);
|
||||
unlock_authcert_list("insert_crl");
|
||||
|
||||
if (!valid_sig)
|
||||
{
|
||||
free_crl(crl);
|
||||
return FALSE;
|
||||
}
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("crl signature is valid")
|
||||
)
|
||||
|
||||
lock_crl_list("insert_crl");
|
||||
oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
|
||||
, crl->authKeyID);
|
||||
|
||||
if (oldcrl != NULL)
|
||||
{
|
||||
if (crl->thisUpdate > oldcrl->thisUpdate)
|
||||
{
|
||||
/* keep any known CRL distribution points */
|
||||
add_distribution_points(oldcrl->distributionPoints
|
||||
, &crl->distributionPoints);
|
||||
|
||||
/* now delete the old CRL */
|
||||
free_first_crl();
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("thisUpdate is newer - existing crl deleted")
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
unlock_crl_list("insert_crls");
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("thisUpdate is not newer - existing crl not replaced");
|
||||
)
|
||||
free_crl(crl);
|
||||
return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert new CRL */
|
||||
crl->next = x509crls;
|
||||
x509crls = crl;
|
||||
|
||||
unlock_crl_list("insert_crl");
|
||||
|
||||
/* If crl caching is enabled then the crl is saved locally.
|
||||
* Only http or ldap URIs are cached but not local file URIs.
|
||||
* The issuer's subjectKeyID is used as a unique filename
|
||||
*/
|
||||
if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
|
||||
{
|
||||
char path[BUF_LEN], buf[BUF_LEN];
|
||||
char digest_buf[HASH_SIZE_SHA1];
|
||||
chunk_t subjectKeyID = chunk_from_buf(digest_buf);
|
||||
bool has_keyID;
|
||||
|
||||
if (issuer_cert->subjectKeyID.ptr == NULL)
|
||||
{
|
||||
has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID);
|
||||
}
|
||||
else
|
||||
{
|
||||
subjectKeyID = issuer_cert->subjectKeyID;
|
||||
has_keyID = TRUE;
|
||||
}
|
||||
if (has_keyID)
|
||||
{
|
||||
datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
|
||||
snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
|
||||
chunk_write(crl->certificateList, path, "crl", 0022, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* is the fetched crl valid? */
|
||||
return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("crl issuer cacert found")
|
||||
)
|
||||
|
||||
/* check the issuer's signature of the crl */
|
||||
valid_sig = x509_check_signature(crl->tbsCertList, crl->signature,
|
||||
crl->algorithm, issuer_cert);
|
||||
unlock_authcert_list("insert_crl");
|
||||
|
||||
if (!valid_sig)
|
||||
{
|
||||
plog(" error in X.509 crl");
|
||||
free_crl(crl);
|
||||
return FALSE;
|
||||
}
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("crl signature is valid")
|
||||
)
|
||||
|
||||
lock_crl_list("insert_crl");
|
||||
oldcrl = get_x509crl(crl->issuer, crl->authKeySerialNumber
|
||||
, crl->authKeyID);
|
||||
|
||||
if (oldcrl != NULL)
|
||||
{
|
||||
if (crl->thisUpdate > oldcrl->thisUpdate)
|
||||
{
|
||||
/* keep any known CRL distribution points */
|
||||
add_distribution_points(oldcrl->distributionPoints
|
||||
, &crl->distributionPoints);
|
||||
|
||||
/* now delete the old CRL */
|
||||
free_first_crl();
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("thisUpdate is newer - existing crl deleted")
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
unlock_crl_list("insert_crls");
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("thisUpdate is not newer - existing crl not replaced");
|
||||
)
|
||||
free_crl(crl);
|
||||
return oldcrl->nextUpdate - time(NULL) > 2*crl_check_interval;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert new CRL */
|
||||
crl->next = x509crls;
|
||||
x509crls = crl;
|
||||
|
||||
unlock_crl_list("insert_crl");
|
||||
|
||||
/* If crl caching is enabled then the crl is saved locally.
|
||||
* Only http or ldap URIs are cached but not local file URIs.
|
||||
* The issuer's subjectKeyID is used as a unique filename
|
||||
*/
|
||||
if (cache_crl && strncasecmp(crl_uri.ptr, "file", 4) != 0)
|
||||
{
|
||||
char path[BUF_LEN], buf[BUF_LEN];
|
||||
char digest_buf[HASH_SIZE_SHA1];
|
||||
chunk_t subjectKeyID = chunk_from_buf(digest_buf);
|
||||
bool has_keyID;
|
||||
|
||||
if (issuer_cert->subjectKeyID.ptr == NULL)
|
||||
{
|
||||
has_keyID = compute_subjectKeyID(issuer_cert, subjectKeyID);
|
||||
}
|
||||
else
|
||||
{
|
||||
subjectKeyID = issuer_cert->subjectKeyID;
|
||||
has_keyID = TRUE;
|
||||
}
|
||||
if (has_keyID)
|
||||
{
|
||||
datatot(subjectKeyID.ptr, subjectKeyID.len, 16, buf, BUF_LEN);
|
||||
snprintf(path, BUF_LEN, "%s/%s.crl", CRL_PATH, buf);
|
||||
chunk_write(crl->certificateList, path, "crl", 0022, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* is the fetched crl valid? */
|
||||
return crl->nextUpdate - time(NULL) > 2*crl_check_interval;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,11 +340,12 @@ void load_crls(void)
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
chunk_t blob = chunk_empty;
|
||||
char *filename = filelist[n]->d_name;
|
||||
|
||||
if (load_coded_file(filename, NULL, "crl", &blob, &pgp))
|
||||
x509crl_t *crl;
|
||||
|
||||
crl = lib->creds->create(lib->creds, CRED_PLUTO_CERT,
|
||||
CRED_TYPE_CRL, BUILD_FROM_FILE, filename, BUILD_END);
|
||||
if (crl)
|
||||
{
|
||||
chunk_t crl_uri;
|
||||
|
||||
@@ -367,7 +356,7 @@ void load_crls(void)
|
||||
snprintf(crl_uri.ptr, crl_uri.len + 1, "file://%s/%s"
|
||||
, CRL_PATH, filename);
|
||||
|
||||
insert_crl(blob, crl_uri, FALSE);
|
||||
insert_crl(crl, crl_uri, FALSE);
|
||||
}
|
||||
free(filelist[n]);
|
||||
}
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ extern const x509crl_t empty_x509crl;
|
||||
extern bool parse_x509crl(chunk_t blob, u_int level0, x509crl_t *crl);
|
||||
extern void load_crls(void);
|
||||
extern void check_crls(void);
|
||||
extern bool insert_crl(chunk_t blob, chunk_t crl_uri, bool cache_crl);
|
||||
extern bool insert_crl(x509crl_t *crl, chunk_t crl_uri, bool cache_crl);
|
||||
extern cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until
|
||||
, time_t *revocationDate, crl_reason_t *revocationReason);
|
||||
extern void list_crls(bool utc, bool strict);
|
||||
|
||||
+17
-30
@@ -41,6 +41,7 @@
|
||||
#include "ocsp.h"
|
||||
#include "crl.h"
|
||||
#include "fetch.h"
|
||||
#include "builder.h"
|
||||
|
||||
fetch_req_t empty_fetch_req = {
|
||||
NULL , /* next */
|
||||
@@ -262,40 +263,25 @@ static void free_fetch_request(fetch_req_t *req)
|
||||
/**
|
||||
* Fetch an ASN.1 blob coded in PEM or DER format from a URL
|
||||
*/
|
||||
bool fetch_asn1_blob(char *url, chunk_t *blob)
|
||||
x509crl_t* fetch_crl(char *url)
|
||||
{
|
||||
x509crl_t *crl;
|
||||
chunk_t blob;
|
||||
|
||||
DBG1(" fetching crl from '%s' ...", url);
|
||||
if (lib->fetcher->fetch(lib->fetcher, url, blob, FETCH_END) != SUCCESS)
|
||||
if (lib->fetcher->fetch(lib->fetcher, url, &blob, FETCH_END) != SUCCESS)
|
||||
{
|
||||
DBG1("crl fetching failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (is_asn1(*blob))
|
||||
crl = lib->creds->create(lib->creds, CRED_PLUTO_CERT, CRED_TYPE_CRL,
|
||||
BUILD_BLOB_PEM, blob, BUILD_END);
|
||||
free(blob.ptr);
|
||||
if (!crl)
|
||||
{
|
||||
DBG2(" fetched blob coded in DER format");
|
||||
DBG1("crl fetched successfully but data coded in unknown format");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
|
||||
if (pem_to_bin(blob, chunk_empty, &pgp) != SUCCESS)
|
||||
{
|
||||
free(blob->ptr);
|
||||
return FALSE;
|
||||
}
|
||||
if (is_asn1(*blob))
|
||||
{
|
||||
DBG2(" fetched blob coded in PEM format");
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1("crl fetched successfully but data coded in unknown format");
|
||||
free(blob->ptr);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
return crl;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,7 +345,6 @@ static void fetch_crls(bool cache_crls)
|
||||
while (req != NULL)
|
||||
{
|
||||
bool valid_crl = FALSE;
|
||||
chunk_t blob = chunk_empty;
|
||||
generalName_t *gn = req->distributionPoints;
|
||||
const char *ldaphost;
|
||||
ca_info_t *ca;
|
||||
@@ -372,12 +357,14 @@ static void fetch_crls(bool cache_crls)
|
||||
while (gn != NULL)
|
||||
{
|
||||
char *uri = complete_uri(gn->name, ldaphost);
|
||||
|
||||
if (fetch_asn1_blob(uri, &blob))
|
||||
x509crl_t *crl;
|
||||
|
||||
crl = fetch_crl(uri);
|
||||
if (crl)
|
||||
{
|
||||
chunk_t crl_uri = chunk_clone(gn->name);
|
||||
|
||||
if (insert_crl(blob, crl_uri, cache_crls))
|
||||
if (insert_crl(crl, crl_uri, cache_crls))
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("we have a valid crl")
|
||||
|
||||
Reference in New Issue
Block a user