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/swanctl/commands | |
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/swanctl/commands')
-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 |
4 files changed, 567 insertions, 1 deletions
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); |