]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/swanctl/commands/load_authorities.c
swanctl: Make credential directories relative to swanctl.conf
[thirdparty/strongswan.git] / src / swanctl / commands / load_authorities.c
CommitLineData
63d37038
AS
1/*
2 * Copyright (C) 2015 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16#define _GNU_SOURCE
17#include <stdio.h>
18#include <errno.h>
19#include <limits.h>
20
21#include "command.h"
22#include "swanctl.h"
23#include "load_authorities.h"
24
25/**
26 * Add a vici list from a comma separated string value
27 */
28static void add_list_key(vici_req_t *req, char *key, char *value)
29{
30 enumerator_t *enumerator;
31 char *token;
32
33 vici_begin_list(req, key);
34 enumerator = enumerator_create_token(value, ",", " ");
35 while (enumerator->enumerate(enumerator, &token))
36 {
37 vici_add_list_itemf(req, "%s", token);
38 }
39 enumerator->destroy(enumerator);
40 vici_end_list(req);
41}
42
43/**
44 * Add a vici certificate blob value given by its file patch
45 */
46static bool add_file_key_value(vici_req_t *req, char *key, char *value)
47{
48 chunk_t *map;
49 char *path, buf[PATH_MAX];
50
51 if (path_absolute(value))
52 {
53 path = value;
54 }
55 else
56 {
57 path = buf;
501bd53a
TB
58 snprintf(path, PATH_MAX, "%s%s%s%s%s", swanctl_dir,
59 DIRECTORY_SEPARATOR, SWANCTL_X509CADIR,
60 DIRECTORY_SEPARATOR, value);
63d37038
AS
61 }
62 map = chunk_map(path, FALSE);
63
64 if (map)
65 {
66 vici_add_key_value(req, key, map->ptr, map->len);
67 chunk_unmap(map);
68 return TRUE;
69 }
70 else
71 {
72 fprintf(stderr, "loading ca certificate '%s' failed: %s\n",
73 path, strerror(errno));
74 return FALSE;
75 }
76}
77
78/**
6d98bb92
TB
79 * Translate sletting key/values from a section enumerator into vici
80 * key-values/lists. Destroys the enumerator.
63d37038 81 */
6d98bb92 82static bool add_key_values(vici_req_t *req, enumerator_t *enumerator)
63d37038 83{
63d37038
AS
84 char *key, *value;
85 bool ret = TRUE;
86
63d37038
AS
87 while (enumerator->enumerate(enumerator, &key, &value))
88 {
63d37038
AS
89 if (streq(key, "cacert"))
90 {
91 ret = add_file_key_value(req, key, value);
92 }
bd6ef6be
TB
93 else if (streq(key, "crl_uris") ||
94 streq(key, "ocsp_uris"))
63d37038 95 {
bd6ef6be 96 add_list_key(req, key, value);
63d37038
AS
97 }
98 else
99 {
bd6ef6be 100 vici_add_key_valuef(req, key, "%s", value);
63d37038
AS
101 }
102 if (!ret)
103 {
104 break;
105 }
106 }
107 enumerator->destroy(enumerator);
108
109 return ret;
110}
111
112/**
113 * Load an authority configuration
114 */
115static bool load_authority(vici_conn_t *conn, settings_t *cfg,
116 char *section, command_format_options_t format)
117{
6d98bb92 118 enumerator_t *enumerator;
63d37038
AS
119 vici_req_t *req;
120 vici_res_t *res;
121 bool ret = TRUE;
63d37038
AS
122
123 req = vici_begin("load-authority");
124
125 vici_begin_section(req, section);
6d98bb92
TB
126 enumerator = cfg->create_key_value_enumerator(cfg, "authorities.%s",
127 section);
128 if (!add_key_values(req, enumerator))
63d37038
AS
129 {
130 vici_free_req(req);
131 return FALSE;
132 }
133 vici_end_section(req);
134
135 res = vici_submit(req, conn);
136 if (!res)
137 {
138 fprintf(stderr, "load-authority request failed: %s\n", strerror(errno));
139 return FALSE;
140 }
141 if (format & COMMAND_FORMAT_RAW)
142 {
143 vici_dump(res, "load-authority reply", format & COMMAND_FORMAT_PRETTY,
144 stdout);
145 }
146 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
147 {
148 fprintf(stderr, "loading authority '%s' failed: %s\n",
149 section, vici_find_str(res, "", "errmsg"));
150 ret = FALSE;
151 }
152 else
153 {
154 printf("loaded authority '%s'\n", section);
155 }
156 vici_free_res(res);
157 return ret;
158}
159
160CALLBACK(list_authority, int,
161 linked_list_t *list, vici_res_t *res, char *name, void *value, int len)
162{
163 if (streq(name, "authorities"))
164 {
165 char *str;
166
167 if (asprintf(&str, "%.*s", len, value) != -1)
168 {
169 list->insert_last(list, str);
170 }
171 }
172 return 0;
173}
174
175/**
176 * Create a list of currently loaded authorities
177 */
178static linked_list_t* list_authorities(vici_conn_t *conn,
179 command_format_options_t format)
180{
181 linked_list_t *list;
182 vici_res_t *res;
183
184 list = linked_list_create();
185
186 res = vici_submit(vici_begin("get-authorities"), conn);
187 if (res)
188 {
189 if (format & COMMAND_FORMAT_RAW)
190 {
191 vici_dump(res, "get-authorities reply", format & COMMAND_FORMAT_PRETTY,
192 stdout);
193 }
194 vici_parse_cb(res, NULL, NULL, list_authority, list);
195 vici_free_res(res);
196 }
197 return list;
198}
199
200/**
201 * Remove and free a string from a list
202 */
203static void remove_from_list(linked_list_t *list, char *str)
204{
205 enumerator_t *enumerator;
206 char *current;
207
208 enumerator = list->create_enumerator(list);
209 while (enumerator->enumerate(enumerator, &current))
210 {
211 if (streq(current, str))
212 {
213 list->remove_at(list, enumerator);
214 free(current);
215 }
216 }
217 enumerator->destroy(enumerator);
218}
219
220/**
221 * Unload a authority by name
222 */
223static bool unload_authority(vici_conn_t *conn, char *name,
224 command_format_options_t format)
225{
226 vici_req_t *req;
227 vici_res_t *res;
228 bool ret = TRUE;
229
230 req = vici_begin("unload-authority");
231 vici_add_key_valuef(req, "name", "%s", name);
232 res = vici_submit(req, conn);
233 if (!res)
234 {
235 fprintf(stderr, "unload-authority request failed: %s\n", strerror(errno));
236 return FALSE;
237 }
238 if (format & COMMAND_FORMAT_RAW)
239 {
240 vici_dump(res, "unload-authority reply", format & COMMAND_FORMAT_PRETTY,
241 stdout);
242 }
243 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
244 {
245 fprintf(stderr, "unloading authority '%s' failed: %s\n",
246 name, vici_find_str(res, "", "errmsg"));
247 ret = FALSE;
248 }
249 vici_free_res(res);
250 return ret;
251}
252
253/**
254 * See header.
255 */
256int load_authorities_cfg(vici_conn_t *conn, command_format_options_t format,
257 settings_t *cfg)
258{
259 u_int found = 0, loaded = 0, unloaded = 0;
260 char *section;
261 enumerator_t *enumerator;
262 linked_list_t *authorities;
263
264 authorities = list_authorities(conn, format);
265
266 enumerator = cfg->create_section_enumerator(cfg, "authorities");
267 while (enumerator->enumerate(enumerator, &section))
268 {
269 remove_from_list(authorities, section);
270 found++;
271 if (load_authority(conn, cfg, section, format))
272 {
273 loaded++;
274 }
275 }
276 enumerator->destroy(enumerator);
277
278 /* unload all authorities in daemon, but not in file */
279 while (authorities->remove_first(authorities, (void**)&section) == SUCCESS)
280 {
281 if (unload_authority(conn, section, format))
282 {
283 unloaded++;
284 }
285 free(section);
286 }
287 authorities->destroy(authorities);
288
289 if (format & COMMAND_FORMAT_RAW)
290 {
291 return 0;
292 }
293 if (found == 0)
294 {
4e3234af 295 fprintf(stderr, "no authorities found, %u unloaded\n", unloaded);
63d37038
AS
296 return 0;
297 }
298 if (loaded == found)
299 {
300 printf("successfully loaded %u authorities, %u unloaded\n",
301 loaded, unloaded);
302 return 0;
303 }
304 fprintf(stderr, "loaded %u of %u authorities, %u failed to load, "
305 "%u unloaded\n", loaded, found, found - loaded, unloaded);
306 return EINVAL;
307}
308
309static int load_authorities(vici_conn_t *conn)
310{
311 command_format_options_t format = COMMAND_FORMAT_NONE;
312 settings_t *cfg;
501bd53a 313 char *arg, *file = NULL;
63d37038
AS
314 int ret;
315
316 while (TRUE)
317 {
318 switch (command_getopt(&arg))
319 {
320 case 'h':
321 return command_usage(NULL);
322 case 'P':
323 format |= COMMAND_FORMAT_PRETTY;
324 /* fall through to raw */
325 case 'r':
326 format |= COMMAND_FORMAT_RAW;
327 continue;
80e8845d
TB
328 case 'f':
329 file = arg;
330 continue;
63d37038
AS
331 case EOF:
332 break;
333 default:
334 return command_usage("invalid --load-authorities option");
335 }
336 break;
337 }
338
501bd53a 339 cfg = load_swanctl_conf(file);
63d37038
AS
340 if (!cfg)
341 {
63d37038
AS
342 return EINVAL;
343 }
344
345 ret = load_authorities_cfg(conn, format, cfg);
346
347 cfg->destroy(cfg);
348
349 return ret;
350}
351
352/**
353 * Register the command.
354 */
355static void __attribute__ ((constructor))reg()
356{
357 command_register((command_t) {
358 load_authorities, 'b',
359 "load-authorities", "(re-)load authority configuration",
360 {"[--raw|--pretty]"},
361 {
362 {"help", 'h', 0, "show usage information"},
363 {"raw", 'r', 0, "dump raw response message"},
364 {"pretty", 'P', 0, "dump raw response message in pretty print"},
80e8845d 365 {"file", 'f', 1, "custom path to swanctl.conf"},
63d37038
AS
366 }
367 });
368}