swanctl: Add a command to (re-)load credentials
[strongswan.git] / src / swanctl / commands / load_creds.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
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 <sys/stat.h>
20
21 #include "command.h"
22 #include "swanctl.h"
23
24 /**
25 * Load a single certificate over vici
26 */
27 static bool load_cert(vici_conn_t *conn, bool raw, char *dir,
28 char *type, chunk_t data)
29 {
30 vici_req_t *req;
31 vici_res_t *res;
32 bool ret = TRUE;
33
34 req = vici_begin("load-cert");
35
36 vici_add_key_valuef(req, "type", "%s", type);
37 vici_add_key_value(req, "data", data.ptr, data.len);
38
39 res = vici_submit(req, conn);
40 if (!res)
41 {
42 fprintf(stderr, "load-cert request failed: %s\n", strerror(errno));
43 return FALSE;
44 }
45 if (raw)
46 {
47 vici_dump(res, "load-cert reply", stdout);
48 }
49 else if (!streq(vici_find_str(res, "no", "success"), "yes"))
50 {
51 fprintf(stderr, "loading '%s' failed: %s\n",
52 dir, vici_find_str(res, "", "errmsg"));
53 ret = FALSE;
54 }
55 vici_free_res(res);
56 return ret;
57 }
58
59 /**
60 * Load certficiates from a directory
61 */
62 static void load_certs(vici_conn_t *conn, bool raw, char *type, char *dir)
63 {
64 enumerator_t *enumerator;
65 struct stat st;
66 chunk_t *map;
67 char *path;
68
69 enumerator = enumerator_create_directory(dir);
70 if (enumerator)
71 {
72 while (enumerator->enumerate(enumerator, NULL, &path, &st))
73 {
74 if (S_ISREG(st.st_mode))
75 {
76 map = chunk_map(path, FALSE);
77 if (map)
78 {
79 load_cert(conn, raw, path, type, *map);
80 chunk_unmap(map);
81 }
82 else
83 {
84 fprintf(stderr, "mapping '%s' failed: %s, skipped\n",
85 path, strerror(errno));
86 }
87 }
88 }
89 enumerator->destroy(enumerator);
90 }
91 }
92
93 /**
94 * Clear all currently loaded credentials
95 */
96 static bool clear_creds(vici_conn_t *conn, bool raw)
97 {
98 vici_res_t *res;
99
100 res = vici_submit(vici_begin("clear-creds"), conn);
101 if (!res)
102 {
103 fprintf(stderr, "clear-creds request failed: %s\n", strerror(errno));
104 return FALSE;
105 }
106 if (raw)
107 {
108 vici_dump(res, "clear-creds reply", stdout);
109 }
110 vici_free_res(res);
111 return TRUE;
112 }
113
114 static int load_creds(vici_conn_t *conn)
115 {
116 bool raw = FALSE, clear = FALSE;
117 char *arg;
118
119 while (TRUE)
120 {
121 switch (command_getopt(&arg))
122 {
123 case 'h':
124 return command_usage(NULL);
125 case 'c':
126 clear = TRUE;
127 continue;
128 case 'r':
129 raw = TRUE;
130 continue;
131 case EOF:
132 break;
133 default:
134 return command_usage("invalid --load-creds option");
135 }
136 break;
137 }
138
139 if (clear)
140 {
141 if (!clear_creds(conn, raw))
142 {
143 return ECONNREFUSED;
144 }
145 }
146
147 load_certs(conn, raw, "x509", SWANCTL_X509DIR);
148 load_certs(conn, raw, "x509ca", SWANCTL_X509CADIR);
149 load_certs(conn, raw, "x509aa", SWANCTL_X509AADIR);
150 load_certs(conn, raw, "x509crl", SWANCTL_X509CRLDIR);
151 load_certs(conn, raw, "x509ac", SWANCTL_X509ACDIR);
152
153 return 0;
154 }
155
156 /**
157 * Register the command.
158 */
159 static void __attribute__ ((constructor))reg()
160 {
161 command_register((command_t) {
162 load_creds, 's', "load-creds", "(re-)load credentials",
163 {"[--raw]"},
164 {
165 {"help", 'h', 0, "show usage information"},
166 {"clear", 'c', 0, "clear previously loaded credentials"},
167 {"raw", 'r', 0, "dump raw response message"},
168 }
169 });
170 }