diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2015-07-14 14:41:27 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2015-07-21 13:02:30 +0200 |
commit | 63d370387d4118c647e4c86bf8e27eddfc3f5715 (patch) | |
tree | a0db15630c9576c14f3afa682c27df486da696be /src | |
parent | e1943491483f68050c0e06410407c37e169d6201 (diff) | |
download | strongswan-63d370387d4118c647e4c86bf8e27eddfc3f5715.tar.bz2 strongswan-63d370387d4118c647e4c86bf8e27eddfc3f5715.tar.xz |
vici: Certification Authority support added.
CDP and OCSP URIs for a one or multiple certification authorities
can be added via the VICI interface. swanctl allows to read
definitions from a new authorities section.
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/plugins/vici/Makefile.am | 1 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/README.md | 64 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_authority.c | 750 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_authority.h | 62 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_config.c | 32 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_config.h | 8 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_cred.c | 7 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_cred.h | 8 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_plugin.c | 16 | ||||
-rw-r--r-- | src/swanctl/Makefile.am | 2 | ||||
-rw-r--r-- | src/swanctl/command.c | 2 | ||||
-rw-r--r-- | src/swanctl/command.h | 2 | ||||
-rw-r--r-- | src/swanctl/commands/list_authorities.c | 169 | ||||
-rw-r--r-- | src/swanctl/commands/load_all.c | 8 | ||||
-rw-r--r-- | src/swanctl/commands/load_authorities.c | 365 | ||||
-rw-r--r-- | src/swanctl/commands/load_authorities.h | 26 | ||||
-rw-r--r-- | src/swanctl/swanctl.8.in | 8 | ||||
-rw-r--r-- | src/swanctl/swanctl.opt | 32 |
18 files changed, 1547 insertions, 15 deletions
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am index b25396085..c99d23e4e 100644 --- a/src/libcharon/plugins/vici/Makefile.am +++ b/src/libcharon/plugins/vici/Makefile.am @@ -23,6 +23,7 @@ libstrongswan_vici_la_SOURCES = \ vici_config.h vici_config.c \ vici_cred.h vici_cred.c \ vici_attribute.h vici_attribute.c \ + vici_authority.h vici_authority.c \ vici_logger.h vici_logger.c \ vici_plugin.h vici_plugin.c diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md index 0ce4271b0..db7ce4e76 100644 --- a/src/libcharon/plugins/vici/README.md +++ b/src/libcharon/plugins/vici/README.md @@ -366,6 +366,27 @@ over vici. # completes after streaming list-cert events } +### list-authorities() ### + +List currently loaded certification authority information by streaming +_list-authority_ events. + + { + name = <list certification authority of a given name> + } => { + # completes after streaming list-authority events + } + +### get-authorities() ### + +Return a list of currently loaded certification authority names. + + {} => { + authorities = [ + <list of certification authority names> + ] + } + ### load-conn() ### Load a single connection definition into the daemon. An existing connection @@ -442,6 +463,32 @@ credential cache. errmsg = <error string on failure> } +### load-authority() ### + +Load a single certification authority definition into the daemon. An existing +authority with the same name gets replaced. + + { + <certification authority name> = { + # certification authority parameters + # refer to swanctl.conf(5) for details. + } => { + success = <yes or no> + errmsg = <error string on failure> + } + } + +### unload-authority() ### + +Unload a previously loaded certification authority definition by name. + + { + name = <certification authority name> + } => { + success = <yes or no> + errmsg = <error string on failure> + } + ### load-pool() ### Load an in-memory virtual IP and configuration attribute pool. Existing @@ -673,6 +720,23 @@ _list-certs_ command. data = <ASN1 encoded certificate data> } +### list-authority ### + +The _list-authority_ event is issued to stream loaded certification authority +information during an active_list-authorities_ command. + + { + <certification authority name> = { + cacert = <subject distinguished name of CA certificate> + crl_uris = [ + <CRL URI (http, ldap or file)> + ] + ocsp_uris = [ + <OCSP URI (http)> + ] + cert_uri_base = <base URI for download of hash-and-URL certificates> + } + } # libvici C client library # diff --git a/src/libcharon/plugins/vici/vici_authority.c b/src/libcharon/plugins/vici/vici_authority.c new file mode 100644 index 000000000..94a7f68f6 --- /dev/null +++ b/src/libcharon/plugins/vici/vici_authority.c @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#define _GNU_SOURCE + +#include "vici_authority.h" +#include "vici_builder.h" + +#include <threading/rwlock.h> +#include <collections/linked_list.h> +#include <credentials/certificates/x509.h> +#include <utils/debug.h> + +#include <stdio.h> + +typedef struct private_vici_authority_t private_vici_authority_t; + +/** + * Private data of an vici_authority_t object. + */ +struct private_vici_authority_t { + + /** + * Public vici_authority_t interface. + */ + vici_authority_t public; + + /** + * Dispatcher + */ + vici_dispatcher_t *dispatcher; + + /** + * credential backend managed by VICI used for our ca certificates + */ + vici_cred_t *cred; + + /** + * List of certification authorities + */ + linked_list_t *authorities; + + /** + * rwlock to lock access to certification authorities + */ + rwlock_t *lock; + +}; + +typedef struct authority_t authority_t; + +/** + * loaded certification authorities + */ +struct authority_t { + + /** + * Name of the certification authoritiy + */ + char *name; + + /** + * Reference to CA certificate + */ + certificate_t *cert; + + /** + * CRL URIs + */ + linked_list_t *crl_uris; + + /** + * OCSP URIs + */ + linked_list_t *ocsp_uris; + + /** + * Hashes of certificates issued by this CA + */ + linked_list_t *hashes; + + /** + * Base URI used for certificates from this CA + */ + char *cert_uri_base; +}; + +/** + * create a new certification authority + */ +static authority_t *authority_create(char *name) +{ + authority_t *authority; + + INIT(authority, + .name = strdup(name), + .crl_uris = linked_list_create(), + .ocsp_uris = linked_list_create(), + .hashes = linked_list_create(), + ); + + return authority; +} + +/** + * destroy a certification authority + */ +static void authority_destroy(authority_t *this) +{ + this->crl_uris->destroy_function(this->crl_uris, free); + this->ocsp_uris->destroy_function(this->ocsp_uris, free); + this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy)); + DESTROY_IF(this->cert); + free(this->cert_uri_base); + free(this->name); + free(this); +} + + +/** + * Create a (error) reply message + */ +static vici_message_t* create_reply(char *fmt, ...) +{ + vici_builder_t *builder; + va_list args; + + builder = vici_builder_create(); + builder->add_kv(builder, "success", fmt ? "no" : "yes"); + if (fmt) + { + va_start(args, fmt); + builder->vadd_kv(builder, "errmsg", fmt, args); + va_end(args); + } + return builder->finalize(builder); +} + +/** + * A rule to parse a key/value or list item + */ +typedef struct { + /** name of the key/value or list */ + char *name; + /** function to parse value */ + bool (*parse)(void *out, chunk_t value); + /** result, passed to parse() */ + void *out; +} parse_rule_t; + +/** + * Parse key/values using a rule-set + */ +static bool parse_rules(parse_rule_t *rules, int count, char *name, + chunk_t value, vici_message_t **reply) +{ + int i; + + for (i = 0; i < count; i++) + { + if (streq(name, rules[i].name)) + { + if (rules[i].parse(rules[i].out, value)) + { + return TRUE; + } + *reply = create_reply("invalid value for: %s, authority discarded", + name); + return FALSE; + } + } + *reply = create_reply("unknown option: %s, authority discarded", name); + return FALSE; +} + +/** + * Parse callback data, passed to each callback + */ +typedef struct { + private_vici_authority_t *this; + vici_message_t *reply; +} request_data_t; + +/** + * Data associated with an authority load + */ +typedef struct { + request_data_t *request; + authority_t *authority; +} load_data_t; + +/** + * Parse a string + */ +CALLBACK(parse_string, bool, + char **str, chunk_t v) +{ + if (!chunk_printable(v, NULL, ' ')) + { + return FALSE; + } + *str = strndup(v.ptr, v.len); + + return TRUE; +} + +/** + * Parse list of URIs + */ +CALLBACK(parse_uris, bool, + linked_list_t *out, chunk_t v) +{ + char *uri; + + if (!chunk_printable(v, NULL, ' ')) + { + return FALSE; + } + uri = strndup(v.ptr, v.len); + out->insert_last(out, uri); + + return TRUE; +} + +/** + * Parse a CA certificate + */ +CALLBACK(parse_cacert, bool, + certificate_t **cacert, chunk_t v) +{ + certificate_t *cert; + x509_t *x509; + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_PEM, v, BUILD_END); + if (!cert) + { + return create_reply("parsing %N certificate failed", + certificate_type_names, CERT_X509); + } + x509 = (x509_t*)cert; + + if ((x509->get_flags(x509) & X509_CA) != X509_CA) + { + cert->destroy(cert); + return create_reply("certificate without CA flag, rejected"); + } + *cacert = cert; + + return TRUE; +} + +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 }, + }; + + return parse_rules(rules, countof(rules), name, value, + &data->request->reply); +} + +CALLBACK(authority_li, bool, + load_data_t *data, vici_message_t *message, char *name, chunk_t value) +{ + parse_rule_t rules[] = { + { "crl_uris", parse_uris, data->authority->crl_uris }, + { "ocsp_uris", parse_uris, data->authority->ocsp_uris }, + }; + + return parse_rules(rules, countof(rules), name, value, + &data->request->reply); +} + +static void log_authority_data(authority_t *authority) +{ + enumerator_t *enumerator; + identification_t *subject; + bool first = TRUE; + char *uri; + + subject = authority->cert->get_subject(authority->cert); + DBG2(DBG_CFG, " cacert = %Y", subject); + + enumerator = authority->crl_uris->create_enumerator(authority->crl_uris); + while (enumerator->enumerate(enumerator, &uri)) + { + if (first) + { + DBG2(DBG_CFG, " crl_uris = %s", uri); + first = FALSE; + } + else + { + DBG2(DBG_CFG, " %s", uri); + } + } + enumerator->destroy(enumerator); + + first = TRUE; + enumerator = authority->ocsp_uris->create_enumerator(authority->ocsp_uris); + while (enumerator->enumerate(enumerator, &uri)) + { + if (first) + { + DBG2(DBG_CFG, " ocsp_uris = %s", uri); + first = FALSE; + } + else + { + DBG2(DBG_CFG, " %s", uri); + } + } + enumerator->destroy(enumerator); + + if (authority->cert_uri_base) + { + DBG2(DBG_CFG, " cert_uri_base = %s", authority->cert_uri_base); + } +} + +CALLBACK(authority_sn, bool, + request_data_t *request, vici_message_t *message, + vici_parse_context_t *ctx, char *name) +{ + enumerator_t *enumerator; + linked_list_t *authorities; + authority_t *authority; + vici_cred_t *cred; + + load_data_t data = { + .request = request, + .authority = authority_create(name), + }; + + DBG2(DBG_CFG, " authority %s:", name); + + if (!message->parse(message, ctx, NULL, authority_kv, authority_li, &data) || + !data.authority->cert) + { + authority_destroy(data.authority); + return FALSE; + } + log_authority_data(data.authority); + + request->this->lock->write_lock(request->this->lock); + + authorities = request->this->authorities; + enumerator = authorities->create_enumerator(authorities); + while (enumerator->enumerate(enumerator, &authority)) + { + if (streq(authority->name, name)) + { + /* remove the old authority definition */ + authorities->remove_at(authorities, enumerator); + authority_destroy(authority); + break; + } + } + enumerator->destroy(enumerator); + authorities->insert_last(authorities, data.authority); + + cred = request->this->cred; + data.authority->cert = cred->add_cert(cred, data.authority->cert); + + request->this->lock->unlock(request->this->lock); + + return TRUE; +} + +CALLBACK(load_authority, vici_message_t*, + private_vici_authority_t *this, char *name, u_int id, vici_message_t *message) +{ + request_data_t request = { + .this = this, + }; + + if (!message->parse(message, NULL, authority_sn, NULL, NULL, &request)) + { + if (request.reply) + { + return request.reply; + } + return create_reply("parsing request failed"); + } + return create_reply(NULL); +} + +CALLBACK(unload_authority, vici_message_t*, + private_vici_authority_t *this, char *name, u_int id, vici_message_t *message) +{ + enumerator_t *enumerator; + authority_t *authority; + char *authority_name; + bool found = FALSE; + + authority_name = message->get_str(message, NULL, "name"); + if (!authority_name) + { + return create_reply("unload: missing authority name"); + } + + this->lock->write_lock(this->lock); + enumerator = this->authorities->create_enumerator(this->authorities); + while (enumerator->enumerate(enumerator, &authority)) + { + if (streq(authority->name, authority_name)) + { + this->authorities->remove_at(this->authorities, enumerator); + authority_destroy(authority); + found = TRUE; + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + if (!found) + { + return create_reply("unload: authority '%s' not found", authority_name); + } + return create_reply(NULL); +} + +CALLBACK(get_authorities, vici_message_t*, + private_vici_authority_t *this, char *name, u_int id, + vici_message_t *message) +{ + vici_builder_t *builder; + enumerator_t *enumerator; + authority_t *authority; + + builder = vici_builder_create(); + builder->begin_list(builder, "authorities"); + + this->lock->read_lock(this->lock); + enumerator = this->authorities->create_enumerator(this->authorities); + while (enumerator->enumerate(enumerator, &authority)) + { + builder->add_li(builder, "%s", authority->name); + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + builder->end_list(builder); + + return builder->finalize(builder); +} + +CALLBACK(list_authorities, vici_message_t*, + private_vici_authority_t *this, char *name, u_int id, vici_message_t *request) +{ + enumerator_t *enumerator, *e; + authority_t *authority; + vici_builder_t *b; + char *str, *uri; + + str = request->get_str(request, NULL, "name"); + + this->lock->read_lock(this->lock); + enumerator = this->authorities->create_enumerator(this->authorities); + while (enumerator->enumerate(enumerator, &authority)) + { + if (str && !streq(str, authority->name)) + { + continue; + } + b = vici_builder_create(); + + /* open authority section */ + b->begin_section(b, authority->name); + + /* subject DN of cacert */ + b->add_kv(b, "cacert", "%Y", + authority->cert->get_subject(authority->cert)); + + /* list of crl_uris */ + b->begin_list(b, "crl_uris"); + e = authority->crl_uris->create_enumerator(authority->crl_uris); + while (e->enumerate(e, &uri)) + { + b->add_li(b, "%s", uri); + } + e->destroy(e); + b->end_list(b); + + /* list of ocsp_uris */ + b->begin_list(b, "ocsp_uris"); + e = authority->ocsp_uris->create_enumerator(authority->ocsp_uris); + while (e->enumerate(e, &uri)) + { + b->add_li(b, "%s", uri); + } + e->destroy(e); + b->end_list(b); + + /* cert_uri_base */ + if (authority->cert_uri_base) + { + b->add_kv(b, "cert_uri_base", "%s", authority->cert_uri_base); + } + + /* close authority and raise event */ + b->end_section(b); + this->dispatcher->raise_event(this->dispatcher, "list-authority", id, + b->finalize(b)); + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + b = vici_builder_create(); + return b->finalize(b); +} + +static void manage_command(private_vici_authority_t *this, + char *name, vici_command_cb_t cb, bool reg) +{ + this->dispatcher->manage_command(this->dispatcher, name, + reg ? cb : NULL, this); +} + +/** + * (Un-)register dispatcher functions + */ +static void manage_commands(private_vici_authority_t *this, bool reg) +{ + this->dispatcher->manage_event(this->dispatcher, "list-authority", reg); + + manage_command(this, "load-authority", load_authority, reg); + manage_command(this, "unload-authority", unload_authority, reg); + manage_command(this, "get-authorities", get_authorities, reg); + manage_command(this, "list-authorities", list_authorities, reg); +} + +/** + * data to pass to create_inner_cdp + */ +typedef struct { + private_vici_authority_t *this; + certificate_type_t type; + identification_t *id; +} cdp_data_t; + +/** + * destroy cdp enumerator data and unlock list + */ +static void cdp_data_destroy(cdp_data_t *data) +{ + data->this->lock->unlock(data->this->lock); + free(data); +} + +/** + * inner enumerator constructor for CDP URIs + */ +static enumerator_t *create_inner_cdp(authority_t *authority, cdp_data_t *data) +{ + public_key_t *public; + enumerator_t *enumerator = NULL; + linked_list_t *list; + + if (data->type == CERT_X509_OCSP_RESPONSE) + { + list = authority->ocsp_uris; + } + else + { + list = authority->crl_uris; + } + + public = authority->cert->get_public_key(authority->cert); + if (public) + { + if (!data->id) + { + enumerator = list->create_enumerator(list); + } + else + { + if (public->has_fingerprint(public, data->id->get_encoding(data->id))) + { + enumerator = list->create_enumerator(list); + } + } + public->destroy(public); + } + return enumerator; +} + +/** + * inner enumerator constructor for "Hash and URL" + */ +static enumerator_t *create_inner_cdp_hashandurl(authority_t *authority, + cdp_data_t *data) +{ + enumerator_t *enumerator = NULL, *hash_enum; + identification_t *current; + + if (!data->id || !authority->cert_uri_base) + { + return NULL; + } + + hash_enum = authority->hashes->create_enumerator(authority->hashes); + while (hash_enum->enumerate(hash_enum, ¤t)) + { + if (current->matches(current, data->id)) + { + char *url, *hash; + + url = malloc(strlen(authority->cert_uri_base) + 40 + 1); + strcpy(url, authority->cert_uri_base); + hash = chunk_to_hex(current->get_encoding(current), NULL, FALSE).ptr; + strncat(url, hash, 40); + free(hash); + + enumerator = enumerator_create_single(url, free); + break; + } + } + hash_enum->destroy(hash_enum); + return enumerator; +} + +METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*, + private_vici_authority_t *this, certificate_type_t type, + identification_t *id) +{ + cdp_data_t *data; + + switch (type) + { /* we serve CRLs, OCSP responders and URLs for "Hash and URL" */ + case CERT_X509: + case CERT_X509_CRL: + case CERT_X509_OCSP_RESPONSE: + case CERT_ANY: + break; + default: + return NULL; + } + data = malloc_thing(cdp_data_t); + data->this = this; + data->type = type; + data->id = id; + + this->lock->read_lock(this->lock); + + return enumerator_create_nested( + this->authorities->create_enumerator(this->authorities), + (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : + (void*)create_inner_cdp, data, (void*)cdp_data_destroy); +} + +METHOD(vici_authority_t, check_for_hash_and_url, void, + private_vici_authority_t *this, certificate_t* cert) +{ + authority_t *authority; + enumerator_t *enumerator; + hasher_t *hasher; + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1(DBG_CFG, "unable to use hash-and-url: sha1 not supported"); + return; + } + + this->lock->write_lock(this->lock); + enumerator = this->authorities->create_enumerator(this->authorities); + while (enumerator->enumerate(enumerator, &authority)) + { + if (authority->cert_uri_base && + cert->issued_by(cert, authority->cert, NULL)) + { + chunk_t hash, encoded; + + if (cert->get_encoding(cert, CERT_ASN1_DER, &encoded)) + { + if (hasher->allocate_hash(hasher, encoded, &hash)) + { + authority->hashes->insert_last(authority->hashes, + identification_create_from_encoding(ID_KEY_ID, hash)); + chunk_free(&hash); + } + chunk_free(&encoded); + } + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + hasher->destroy(hasher); +} + +METHOD(vici_authority_t, destroy, void, + private_vici_authority_t *this) +{ + manage_commands(this, FALSE); + + this->authorities->destroy_function(this->authorities, + (void*)authority_destroy); + this->lock->destroy(this->lock); + free(this); +} + +/** + * See header + */ +vici_authority_t *vici_authority_create(vici_dispatcher_t *dispatcher, + vici_cred_t *cred) +{ + private_vici_authority_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = (void*)return_null, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = _create_cdp_enumerator, + .cache_cert = (void*)nop, + }, + .check_for_hash_and_url = _check_for_hash_and_url, + .destroy = _destroy, + }, + .dispatcher = dispatcher, + .cred = cred, + .authorities = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + ); + + manage_commands(this, TRUE); + + return &this->public; +} diff --git a/src/libcharon/plugins/vici/vici_authority.h b/src/libcharon/plugins/vici/vici_authority.h new file mode 100644 index 000000000..dbeabae62 --- /dev/null +++ b/src/libcharon/plugins/vici/vici_authority.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup vici_authority vici_authority + * @{ @ingroup vici + */ + +#ifndef VICI_AUTHORITY_H_ +#define VICI_AUTHORITY_H_ + +#include "vici_dispatcher.h" +#include "vici_cred.h" + +typedef struct vici_authority_t vici_authority_t; + +/** + * In-memory certification authority backend, managed by VICI. + */ +struct vici_authority_t { + + /** + * Implements credential_set_t + */ + credential_set_t set; + + /** + * Check if a certificate can be made available through hash and URL. + * + * @param cert end entity certificate + */ + void (*check_for_hash_and_url)(vici_authority_t *this, certificate_t* cert); + + /** + * Destroy a vici_authority_t. + */ + void (*destroy)(vici_authority_t *this); +}; + +/** + * Create a vici_authority instance. + * + * @param dispatcher dispatcher to receive requests from + * @param cred in-memory credential backend managed by VICI + * @return authority backend + */ +vici_authority_t *vici_authority_create(vici_dispatcher_t *dispatcher, + vici_cred_t *cred); + +#endif /** VICI_AUTHORITY_H_ @}*/ diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c index a1b95865d..139616f43 100644 --- a/src/libcharon/plugins/vici/vici_config.c +++ b/src/libcharon/plugins/vici/vici_config.c @@ -96,6 +96,12 @@ struct private_vici_config_t { * Lock for conns list */ rwlock_t *lock; + + /** + * Auxiliary certification authority information + */ + vici_authority_t *authority; + }; METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*, @@ -1043,15 +1049,21 @@ CALLBACK(parse_group, bool, /** * Parse a certificate; add as auth rule to config */ -static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v) +static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v) { + vici_authority_t *authority; certificate_t *cert; cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB_PEM, v, BUILD_END); if (cert) { - cfg->add(cfg, rule, cert); + if (rule == AUTH_RULE_SUBJECT_CERT) + { + authority = auth->request->this->authority; + authority->check_for_hash_and_url(authority, cert); + } + auth->cfg->add(auth->cfg, rule, cert); return TRUE; } return FALSE; @@ -1061,18 +1073,18 @@ static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v) * Parse subject certificates */ CALLBACK(parse_certs, bool, - auth_cfg_t *cfg, chunk_t v) + auth_data_t *auth, chunk_t v) { - return parse_cert(cfg, AUTH_RULE_SUBJECT_CERT, v); + return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v); } /** * Parse CA certificates */ CALLBACK(parse_cacerts, bool, - auth_cfg_t *cfg, chunk_t v) + auth_data_t *auth, chunk_t v) { - return parse_cert(cfg, AUTH_RULE_CA_CERT, v); + return parse_cert(auth, AUTH_RULE_CA_CERT, v); } /** @@ -1267,8 +1279,8 @@ CALLBACK(auth_li, bool, { parse_rule_t rules[] = { { "groups", parse_group, auth->cfg }, - { "certs", parse_certs, auth->cfg }, - { "cacerts", parse_cacerts, auth->cfg }, + { "certs", parse_certs, auth }, + { "cacerts", parse_cacerts, auth }, }; return parse_rules(rules, countof(rules), name, value, @@ -2056,7 +2068,8 @@ METHOD(vici_config_t, destroy, void, /** * See header */ -vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher) +vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher, + vici_authority_t *authority) { private_vici_config_t *this; @@ -2072,6 +2085,7 @@ vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher) .dispatcher = dispatcher, .conns = linked_list_create(), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .authority = authority, ); manage_commands(this, TRUE); diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h index 820d5f300..c3245bf5c 100644 --- a/src/libcharon/plugins/vici/vici_config.h +++ b/src/libcharon/plugins/vici/vici_config.h @@ -2,6 +2,9 @@ * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -22,6 +25,7 @@ #define VICI_CONFIG_H_ #include "vici_dispatcher.h" +#include "vici_authority.h" #include <config/backend.h> @@ -46,8 +50,10 @@ struct vici_config_t { * Create a vici_config instance. * * @param dispatcher dispatcher to receive requests from + * @param authority Auxiliary certification authority information * @return config backend */ -vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher); +vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher, + vici_authority_t *authority); #endif /** VICI_CONFIG_H_ @}*/ diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c index d4c02de6d..ffdc034ea 100644 --- a/src/libcharon/plugins/vici/vici_cred.c +++ b/src/libcharon/plugins/vici/vici_cred.c @@ -294,6 +294,12 @@ static void manage_commands(private_vici_cred_t *this, bool reg) manage_command(this, "load-shared", load_shared, reg); } +METHOD(vici_cred_t, add_cert, certificate_t*, + private_vici_cred_t *this, certificate_t *cert) +{ + return this->creds->get_cert_ref(this->creds, cert); +} + METHOD(vici_cred_t, destroy, void, private_vici_cred_t *this) { @@ -313,6 +319,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher) INIT(this, .public = { + .add_cert = _add_cert, .destroy = _destroy, }, .dispatcher = dispatcher, diff --git a/src/libcharon/plugins/vici/vici_cred.h b/src/libcharon/plugins/vici/vici_cred.h index e109a27da..8359c0e88 100644 --- a/src/libcharon/plugins/vici/vici_cred.h +++ b/src/libcharon/plugins/vici/vici_cred.h @@ -31,6 +31,14 @@ typedef struct vici_cred_t vici_cred_t; struct vici_cred_t { /** + * Add a certificate to the certificate store + * + * @param cert certificate to be added to store + * @return reference to certificate or cached copy + */ + certificate_t* (*add_cert)(vici_cred_t *this, certificate_t *cert); + + /** * Destroy a vici_cred_t. */ void (*destroy)(vici_cred_t *this); diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c index 7ae58a317..53ed8cdfb 100644 --- a/src/libcharon/plugins/vici/vici_plugin.c +++ b/src/libcharon/plugins/vici/vici_plugin.c @@ -2,6 +2,9 @@ * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -42,6 +45,7 @@ #include "vici_cred.h" #include "vici_config.h" #include "vici_attribute.h" +#include "vici_authority.h" #include "vici_logger.h" #include <library.h> @@ -80,6 +84,11 @@ struct private_vici_plugin_t { vici_cred_t *cred; /** + * Certification Authority backend + */ + vici_authority_t *authority; + + /** * Configuration backend */ vici_config_t *config; @@ -119,7 +128,10 @@ static bool register_vici(private_vici_plugin_t *this, this->query = vici_query_create(this->dispatcher); this->control = vici_control_create(this->dispatcher); this->cred = vici_cred_create(this->dispatcher); - this->config = vici_config_create(this->dispatcher); + this->authority = vici_authority_create(this->dispatcher, + this->cred); + lib->credmgr->add_set(lib->credmgr, &this->authority->set); + this->config = vici_config_create(this->dispatcher, this->authority); this->attrs = vici_attribute_create(this->dispatcher); this->logger = vici_logger_create(this->dispatcher); @@ -145,6 +157,8 @@ static bool register_vici(private_vici_plugin_t *this, this->logger->destroy(this->logger); this->attrs->destroy(this->attrs); this->config->destroy(this->config); + lib->credmgr->remove_set(lib->credmgr, &this->authority->set); + this->authority->destroy(this->authority); this->cred->destroy(this->cred); this->control->destroy(this->control); this->query->destroy(this->query); diff --git a/src/swanctl/Makefile.am b/src/swanctl/Makefile.am index f4f9fdf7e..abf067a7c 100644 --- a/src/swanctl/Makefile.am +++ b/src/swanctl/Makefile.am @@ -7,10 +7,12 @@ swanctl_SOURCES = \ commands/install.c \ commands/list_sas.c \ commands/list_pols.c \ + commands/list_authorities.c \ commands/list_conns.c \ commands/list_certs.c \ commands/list_pools.c \ commands/load_all.c \ + commands/load_authorities.h commands/load_authorities.c \ commands/load_conns.c commands/load_conns.h \ commands/load_creds.c commands/load_creds.h \ commands/load_pools.c commands/load_pools.h \ diff --git a/src/swanctl/command.c b/src/swanctl/command.c index 03cd8b959..26c41346c 100644 --- a/src/swanctl/command.c +++ b/src/swanctl/command.c @@ -211,7 +211,7 @@ int command_usage(char *error, ...) { for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++) { - fprintf(out, " swanctl --%-15s (-%c) %s\n", + fprintf(out, " swanctl --%-16s (-%c) %s\n", cmds[i].cmd, cmds[i].op, cmds[i].description); } } diff --git a/src/swanctl/command.h b/src/swanctl/command.h index ffc319085..0760d1384 100644 --- a/src/swanctl/command.h +++ b/src/swanctl/command.h @@ -27,7 +27,7 @@ /** * Maximum number of commands (+1). */ -#define MAX_COMMANDS 19 +#define MAX_COMMANDS 21 /** * Maximum number of options in a command (+3) diff --git a/src/swanctl/commands/list_authorities.c b/src/swanctl/commands/list_authorities.c new file mode 100644 index 000000000..8bff6f95d --- /dev/null +++ b/src/swanctl/commands/list_authorities.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> + +#include "command.h" + +#define LABELED_CRL_URI (1 << 0) +#define LABELED_OCSP_URI (1 << 1) + +CALLBACK(authority_kv, int, + void *null, vici_res_t *res, char *name, void *value, int len) +{ + chunk_t chunk; + + chunk = chunk_create(value, len); + if (chunk_printable(chunk, NULL, ' ')) + { + printf(" %s: %.*s\n", name, len, value); + } + + return 0; +} + + +CALLBACK(authority_list, int, + int *labeled, vici_res_t *res, char *name, void *value, int len) +{ + chunk_t chunk; + + chunk = chunk_create(value, len); + if (chunk_printable(chunk, NULL, ' ')) + { + if (streq(name, "crl_uris")) + { + printf(" %s %.*s\n", + (*labeled & LABELED_CRL_URI) ? " " : "crl_uris: ", + len, value); + *labeled |= LABELED_CRL_URI; + } + if (streq(name, "ocsp_uris")) + { + printf(" %s %.*s\n", + (*labeled & LABELED_OCSP_URI) ? " " : "ocsp_uris:", + len, value); + *labeled %= LABELED_OCSP_URI; + } + } + return 0; +} + +CALLBACK(authorities, int, + void *null, vici_res_t *res, char *name) +{ + int labeled = 0; + + printf("%s:\n", name); + + return vici_parse_cb(res, NULL, authority_kv, authority_list, &labeled); +} + +CALLBACK(list_cb, void, + command_format_options_t *format, char *name, vici_res_t *res) +{ + if (*format & COMMAND_FORMAT_RAW) + { + vici_dump(res, "list-authorities event", *format & COMMAND_FORMAT_PRETTY, + stdout); + } + else + { + if (vici_parse_cb(res, authorities, NULL, NULL, NULL) != 0) + { + fprintf(stderr, "parsing authority event failed: %s\n", + strerror(errno)); + } + } +} + +static int list_authorities(vici_conn_t *conn) +{ + vici_req_t *req; + vici_res_t *res; + command_format_options_t format = COMMAND_FORMAT_NONE; + char *arg, *ca_name = NULL;; + int ret = 0; + + while (TRUE) + { + switch (command_getopt(&arg)) + { + case 'h': + return command_usage(NULL); + case 'n': + ca_name = arg; + continue; + case 'P': + format |= COMMAND_FORMAT_PRETTY; + /* fall through to raw */ + case 'r': + format |= COMMAND_FORMAT_RAW; + continue; + case EOF: + break; + default: + return command_usage("invalid --list-authorities option"); + } + break; + } + if (vici_register(conn, "list-authority", list_cb, &format) != 0) + { + ret = errno; + fprintf(stderr, "registering for authorities failed: %s\n", + strerror(errno)); + return ret; + } + + req = vici_begin("list-authorities"); + if (ca_name) + { + vici_add_key_valuef(req, "name", "%s", ca_name); + } + res = vici_submit(req, conn); + if (!res) + { + ret = errno; + fprintf(stderr, "list-authorities request failed: %s\n", strerror(errno)); + return ret; + } + if (format & COMMAND_FORMAT_RAW) + { + vici_dump(res, "list-authorities reply", format & COMMAND_FORMAT_PRETTY, + stdout); + } + vici_free_res(res); + return 0; +} + +/** + * Register the command. + */ +static void __attribute__ ((constructor))reg() +{ + command_register((command_t) { + list_authorities, 'B', "list-authorities", + "list loaded authority configurations", + {"[--raw|--pretty]"}, + { + {"help", 'h', 0, "show usage information"}, + {"name", 'n', 1, "filter by authority name"}, + {"raw", 'r', 0, "dump raw response message"}, + {"pretty", 'P', 0, "dump raw response message in pretty print"}, + } + }); +} diff --git a/src/swanctl/commands/load_all.c b/src/swanctl/commands/load_all.c index f47fee5b4..0010ce140 100644 --- a/src/swanctl/commands/load_all.c +++ b/src/swanctl/commands/load_all.c @@ -22,6 +22,7 @@ #include "command.h" #include "swanctl.h" #include "load_creds.h" +#include "load_authorities.h" #include "load_pools.h" #include "load_conns.h" @@ -72,6 +73,10 @@ static int load_all(vici_conn_t *conn) } if (ret == 0) { + ret = load_authorities_cfg(conn, format, cfg); + } + if (ret == 0) + { ret = load_pools_cfg(conn, format, cfg); } if (ret == 0) @@ -90,7 +95,8 @@ static int load_all(vici_conn_t *conn) static void __attribute__ ((constructor))reg() { command_register((command_t) { - load_all, 'q', "load-all", "load credentials, pools and connections", + load_all, 'q', "load-all", + "load credentials, authorities, pools and connections", {"[--raw|--pretty] [--clear] [--noprompt]"}, { {"help", 'h', 0, "show usage information"}, diff --git a/src/swanctl/commands/load_authorities.c b/src/swanctl/commands/load_authorities.c new file mode 100644 index 000000000..88dde6aaf --- /dev/null +++ b/src/swanctl/commands/load_authorities.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> +#include <limits.h> + +#include "command.h" +#include "swanctl.h" +#include "load_authorities.h" + +/** + * Add a vici list from a comma separated string value + */ +static void add_list_key(vici_req_t *req, char *key, char *value) +{ + enumerator_t *enumerator; + char *token; + + vici_begin_list(req, key); + enumerator = enumerator_create_token(value, ",", " "); + while (enumerator->enumerate(enumerator, &token)) + { + vici_add_list_itemf(req, "%s", token); + } + enumerator->destroy(enumerator); + vici_end_list(req); +} + +/** + * Add a vici certificate blob value given by its file patch + */ +static bool add_file_key_value(vici_req_t *req, char *key, char *value) +{ + chunk_t *map; + char *path, buf[PATH_MAX]; + + if (path_absolute(value)) + { + path = value; + } + else + { + path = buf; + snprintf(path, PATH_MAX, "%s%s%s", + SWANCTL_X509CADIR, DIRECTORY_SEPARATOR, value); + } + map = chunk_map(path, FALSE); + + if (map) + { + vici_add_key_value(req, key, map->ptr, map->len); + chunk_unmap(map); + return TRUE; + } + else + { + fprintf(stderr, "loading ca certificate '%s' failed: %s\n", + path, strerror(errno)); + return FALSE; + } +} + +/** + * Translate sletting key/values from a section into vici key-values/lists + */ +static bool add_key_values(vici_req_t *req, settings_t *cfg, char *section) +{ + enumerator_t *enumerator; + char *key, *value; + bool ret = TRUE; + + 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")) + { + vici_add_key_valuef(req, key, "%s", value); + } + else + { + add_list_key(req, key, value); + } + if (!ret) + { + break; + } + } + enumerator->destroy(enumerator); + + return ret; +} + +/** + * Load an authority configuration + */ +static bool load_authority(vici_conn_t *conn, settings_t *cfg, + char *section, command_format_options_t format) +{ + vici_req_t *req; + vici_res_t *res; + bool ret = TRUE; + char buf[128]; + + snprintf(buf, sizeof(buf), "%s.%s", "authorities", section); + + req = vici_begin("load-authority"); + + vici_begin_section(req, section); + if (!add_key_values(req, cfg, buf)) + { + vici_free_req(req); + return FALSE; + } + vici_end_section(req); + + res = vici_submit(req, conn); + if (!res) + { + fprintf(stderr, "load-authority request failed: %s\n", strerror(errno)); + return FALSE; + } + if (format & COMMAND_FORMAT_RAW) + { + vici_dump(res, "load-authority reply", format & COMMAND_FORMAT_PRETTY, + stdout); + } + else if (!streq(vici_find_str(res, "no", "success"), "yes")) + { + fprintf(stderr, "loading authority '%s' failed: %s\n", + section, vici_find_str(res, "", "errmsg")); + ret = FALSE; + } + else + { + printf("loaded authority '%s'\n", section); + } + vici_free_res(res); + return ret; +} + +CALLBACK(list_authority, int, + linked_list_t *list, vici_res_t *res, char *name, void *value, int len) +{ + if (streq(name, "authorities")) + { + char *str; + + if (asprintf(&str, "%.*s", len, value) != -1) + { + list->insert_last(list, str); + } + } + return 0; +} + +/** + * Create a list of currently loaded authorities + */ +static linked_list_t* list_authorities(vici_conn_t *conn, + command_format_options_t format) +{ + linked_list_t *list; + vici_res_t *res; + + list = linked_list_create(); + + res = vici_submit(vici_begin("get-authorities"), conn); + if (res) + { + if (format & COMMAND_FORMAT_RAW) + { + vici_dump(res, "get-authorities reply", format & COMMAND_FORMAT_PRETTY, + stdout); + } + vici_parse_cb(res, NULL, NULL, list_authority, list); + vici_free_res(res); + } + return list; +} + +/** + * Remove and free a string from a list + */ +static void remove_from_list(linked_list_t *list, char *str) +{ + enumerator_t *enumerator; + char *current; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(current, str)) + { + list->remove_at(list, enumerator); + free(current); + } + } + enumerator->destroy(enumerator); +} + +/** + * Unload a authority by name + */ +static bool unload_authority(vici_conn_t *conn, char *name, + command_format_options_t format) +{ + vici_req_t *req; + vici_res_t *res; + bool ret = TRUE; + + req = vici_begin("unload-authority"); + vici_add_key_valuef(req, "name", "%s", name); + res = vici_submit(req, conn); + if (!res) + { + fprintf(stderr, "unload-authority request failed: %s\n", strerror(errno)); + return FALSE; + } + if (format & COMMAND_FORMAT_RAW) + { + vici_dump(res, "unload-authority reply", format & COMMAND_FORMAT_PRETTY, + stdout); + } + else if (!streq(vici_find_str(res, "no", "success"), "yes")) + { + fprintf(stderr, "unloading authority '%s' failed: %s\n", + name, vici_find_str(res, "", "errmsg")); + ret = FALSE; + } + vici_free_res(res); + return ret; +} + +/** + * See header. + */ +int load_authorities_cfg(vici_conn_t *conn, command_format_options_t format, + settings_t *cfg) +{ + u_int found = 0, loaded = 0, unloaded = 0; + char *section; + enumerator_t *enumerator; + linked_list_t *authorities; + + authorities = list_authorities(conn, format); + + enumerator = cfg->create_section_enumerator(cfg, "authorities"); + while (enumerator->enumerate(enumerator, §ion)) + { + remove_from_list(authorities, section); + found++; + if (load_authority(conn, cfg, section, format)) + { + loaded++; + } + } + enumerator->destroy(enumerator); + + /* unload all authorities in daemon, but not in file */ + while (authorities->remove_first(authorities, (void**)§ion) == SUCCESS) + { + if (unload_authority(conn, section, format)) + { + unloaded++; + } + free(section); + } + authorities->destroy(authorities); + + if (format & COMMAND_FORMAT_RAW) + { + return 0; + } + if (found == 0) + { + printf("no authorities found, %u unloaded\n", unloaded); + return 0; + } + if (loaded == found) + { + printf("successfully loaded %u authorities, %u unloaded\n", + loaded, unloaded); + return 0; + } + fprintf(stderr, "loaded %u of %u authorities, %u failed to load, " + "%u unloaded\n", loaded, found, found - loaded, unloaded); + return EINVAL; +} + +static int load_authorities(vici_conn_t *conn) +{ + command_format_options_t format = COMMAND_FORMAT_NONE; + settings_t *cfg; + char *arg; + int ret; + + while (TRUE) + { + switch (command_getopt(&arg)) + { + case 'h': + return command_usage(NULL); + case 'P': + format |= COMMAND_FORMAT_PRETTY; + /* fall through to raw */ + case 'r': + format |= COMMAND_FORMAT_RAW; + continue; + case EOF: + break; + default: + return command_usage("invalid --load-authorities option"); + } + break; + } + + cfg = settings_create(SWANCTL_CONF); + if (!cfg) + { + fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF); + return EINVAL; + } + + ret = load_authorities_cfg(conn, format, cfg); + + cfg->destroy(cfg); + + return ret; +} + +/** + * Register the command. + */ +static void __attribute__ ((constructor))reg() +{ + command_register((command_t) { + load_authorities, 'b', + "load-authorities", "(re-)load authority configuration", + {"[--raw|--pretty]"}, + { + {"help", 'h', 0, "show usage information"}, + {"raw", 'r', 0, "dump raw response message"}, + {"pretty", 'P', 0, "dump raw response message in pretty print"}, + } + }); +} diff --git a/src/swanctl/commands/load_authorities.h b/src/swanctl/commands/load_authorities.h new file mode 100644 index 000000000..d4be214fb --- /dev/null +++ b/src/swanctl/commands/load_authorities.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015 Andreas Stefffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "command.h" + +/** + * Load all certification authority definitions from configuration file + * + * @param conn vici connection to load to + * @param format output format + * @param cfg configuration to load from + */ +int load_authorities_cfg(vici_conn_t *conn, command_format_options_t format, + settings_t *cfg); diff --git a/src/swanctl/swanctl.8.in b/src/swanctl/swanctl.8.in index 543c10a67..cd033f91e 100644 --- a/src/swanctl/swanctl.8.in +++ b/src/swanctl/swanctl.8.in @@ -53,9 +53,15 @@ list currently active IKE_SAs .B "\-P, \-\-list\-pols" list currently installed policies .TP +.B "\-b, \-\-load\-authorities" +(re\-)load certification authorities information +.TP .B "\-L, \-\-list\-conns" list loaded configurations .TP +.B "\-B, \-\-list\-authorities" +list loaded certification authorities information +.TP .B "\-x, \-\-list\-certs" list stored certificates .TP @@ -63,7 +69,7 @@ list stored certificates list loaded pool configurations .TP .B "\-q, \-\-load\-all" -(re\-)load credentials, pools and connections +(re\-)load credentials, pools, authorities and connections .TP .B "\-c, \-\-load\-conns" (re\-)load connection configuration diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt index b6ef17546..0bdb6a1f9 100644 --- a/src/swanctl/swanctl.opt +++ b/src/swanctl/swanctl.opt @@ -810,3 +810,35 @@ pools.<name>.<attr> = subnets for the corresponding attribute types. Alternatively, **<attr>** can be a numerical identifier, for which string attribute values are accepted as well. + +authorities { # } + Section defining attributes of certification authorities. + +authorities.<name> { # } + Section defining a certification authority with a unique 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. + +authorities.<name>.crl_uris = + Comma-separated list of CRL distribution points + + 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 + +authorities.<name>.cert_uri_base = + Defines the base URI for the Hash and URL feature supported by IKEv2. + + Defines the base URI for the Hash and URL feature supported by IKEv2. + Instead of exchanging complete certificates, IKEv2 allows one to send an + URI that resolves to the DER encoded certificate. The certificate URIs are + built by appending the SHA1 hash of the DER encoded certificates to this + base URI. + |