vici: Add support to load CA certificates from tokens and paths in authority sections

This commit is contained in:
Tobias Brunner 2016-11-30 15:41:18 +01:00
parent 2f8354ca6c
commit bd6ef6be7e
3 changed files with 130 additions and 21 deletions

View File

@ -1,4 +1,5 @@
/*
* Copyright (C) 2016 Tobias Brunner
* Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@ -199,8 +200,27 @@ typedef struct {
typedef struct {
request_data_t *request;
authority_t *authority;
char *handle;
uint32_t slot;
char *module;
char *file;
} load_data_t;
/**
* Clean up data associated with an authority load
*/
static void free_load_data(load_data_t *data)
{
if (data->authority)
{
authority_destroy(data->authority);
}
free(data->handle);
free(data->module);
free(data->file);
free(data);
}
/**
* Parse a string
*/
@ -216,6 +236,28 @@ CALLBACK(parse_string, bool,
return TRUE;
}
/**
* Parse a uint32_t
*/
CALLBACK(parse_uint32, bool,
uint32_t *out, chunk_t v)
{
char buf[16], *end;
u_long l;
if (!vici_stringify(v, buf, sizeof(buf)))
{
return FALSE;
}
l = strtoul(buf, &end, 0);
if (*end == 0)
{
*out = l;
return TRUE;
}
return FALSE;
}
/**
* Parse list of URIs
*/
@ -266,8 +308,12 @@ CALLBACK(authority_kv, bool,
load_data_t *data, vici_message_t *message, char *name, chunk_t value)
{
parse_rule_t rules[] = {
{ "cacert", parse_cacert, &data->authority->cert },
{ "cert_uri_base", parse_string, &data->authority->cert_uri_base },
{ "cacert", parse_cacert, &data->authority->cert },
{ "file", parse_string, &data->file },
{ "handle", parse_string, &data->handle },
{ "slot", parse_uint32, &data->slot },
{ "module", parse_string, &data->module },
{ "cert_uri_base", parse_string, &data->authority->cert_uri_base },
};
return parse_rules(rules, countof(rules), name, value,
@ -341,21 +387,60 @@ CALLBACK(authority_sn, bool,
linked_list_t *authorities;
authority_t *authority;
vici_cred_t *cred;
load_data_t *data;
chunk_t handle;
load_data_t data = {
INIT(data,
.request = request,
.authority = authority_create(name),
};
.slot = -1,
);
DBG2(DBG_CFG, " authority %s:", name);
if (!message->parse(message, ctx, NULL, authority_kv, authority_li, &data) ||
!data.authority->cert)
if (!message->parse(message, ctx, NULL, authority_kv, authority_li, data))
{
authority_destroy(data.authority);
free_load_data(data);
return FALSE;
}
log_authority_data(data.authority);
if (!data->authority->cert)
{
if (data->file)
{
data->authority->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, data->file, BUILD_END);
}
else if (data->handle)
{
handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
if (data->slot != -1)
{
data->authority->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_PKCS11_KEYID, handle,
BUILD_PKCS11_SLOT, data->slot,
data->module ? BUILD_PKCS11_MODULE : BUILD_END,
data->module, BUILD_END);
}
else
{
data->authority->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_PKCS11_KEYID, handle,
data->module ? BUILD_PKCS11_MODULE : BUILD_END,
data->module, BUILD_END);
}
chunk_free(&handle);
}
}
if (!data->authority->cert)
{
request->reply = create_reply("CA certificate missing: %s", name);
free_load_data(data);
return FALSE;
}
log_authority_data(data->authority);
request->this->lock->write_lock(request->this->lock);
@ -372,12 +457,14 @@ CALLBACK(authority_sn, bool,
}
}
enumerator->destroy(enumerator);
authorities->insert_last(authorities, data.authority);
authorities->insert_last(authorities, data->authority);
cred = request->this->cred;
data.authority->cert = cred->add_cert(cred, data.authority->cert);
data->authority->cert = cred->add_cert(cred, data->authority->cert);
data->authority = NULL;
request->this->lock->unlock(request->this->lock);
free_load_data(data);
return TRUE;
}

View File

@ -86,18 +86,18 @@ static bool add_key_values(vici_req_t *req, settings_t *cfg, char *section)
enumerator = cfg->create_key_value_enumerator(cfg, section);
while (enumerator->enumerate(enumerator, &key, &value))
{
/* pool subnet is encoded as key/value, all other attributes as list */
if (streq(key, "cacert"))
{
ret = add_file_key_value(req, key, value);
}
else if (streq(key, "cert_uri_base"))
else if (streq(key, "crl_uris") ||
streq(key, "ocsp_uris"))
{
vici_add_key_valuef(req, key, "%s", value);
add_list_key(req, key, value);
}
else
{
add_list_key(req, key, value);
vici_add_key_valuef(req, key, "%s", value);
}
if (!ret)
{

View File

@ -1054,18 +1054,40 @@ authorities.<name> { # }
authorities.<name>.cacert =
CA certificate belonging to the certification authority.
The certificates may use a relative path from the **swanctl** _x509ca_
directory or an absolute path.
CA certificate belonging to the certification authority. The certificates
may use a relative path from the **swanctl** _x509ca_ directory or an
absolute path.
Configure one of _cacert_, _file_, or _handle_ per section.
authorities.<name>.file =
Absolute path to the certificate to load.
Absolute path to the certificate to load. Passed as-is to the daemon, so it
must be readable by it.
Configure one of _cacert_, _file_, or _handle_ per section.
authorities.<name>.handle =
Hex-encoded CKA_ID of the CA certificate on a token.
Hex-encoded CKA_ID of the CA certificate on a token.
Configure one of _cacert_, _file_, or _handle_ per section.
authorities.<name>.slot =
Optional slot number of the token that stores the CA certificate.
authorities.<name>.module =
Optional PKCS#11 module name.
authorities.<name>.crl_uris =
Comma-separated list of CRL distribution points
Comma-separated list of CRL distribution points.
Comma-separated list of CRL distribution points (ldap, http, or file URI)
Comma-separated list of CRL distribution points (ldap, http, or file URI).
authorities.<name>.ocsp_uris =
Comma-separated list of OCSP URIs
Comma-separated list of OCSP URIs
Comma-separated list of OCSP URIs.
authorities.<name>.cert_uri_base =
Defines the base URI for the Hash and URL feature supported by IKEv2.