]>
Commit | Line | Data |
---|---|---|
906a4096 | 1 | /* |
d8fe354a | 2 | * Copyright (C) 2007-2015 Tobias Brunner |
d5cc1758 TB |
3 | * Copyright (C) 2006 Martin Willi |
4 | * Hochschule fuer Technik Rapperswil | |
4749578d MW |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
f2ee13a7 | 17 | #include <stdlib.h> |
4749578d | 18 | #include <unistd.h> |
f2ee13a7 | 19 | #include <stdio.h> |
2d5b3d34 | 20 | #include <stdint.h> |
d24a74c5 | 21 | #include <string.h> |
dcb16841 | 22 | #include <getopt.h> |
4749578d | 23 | |
1c31d34e TB |
24 | #include <library.h> |
25 | ||
552cc11b | 26 | #include "stroke_msg.h" |
53472332 AS |
27 | #include "stroke_keywords.h" |
28 | ||
29 | struct stroke_token { | |
30 | char *name; | |
31 | stroke_keyword_t kw; | |
32 | }; | |
4749578d | 33 | |
dcb16841 | 34 | static char *daemon_name = "charon"; |
4182c86a TB |
35 | static int output_verbosity = 1; /* CONTROL */ |
36 | ||
d8fe354a | 37 | static stroke_msg_t *create_stroke_msg(int type) |
4749578d | 38 | { |
d8fe354a | 39 | stroke_msg_t *msg; |
ecadab2b | 40 | |
d8fe354a TB |
41 | INIT(msg, |
42 | .type = type, | |
43 | .length = offsetof(stroke_msg_t, buffer), | |
44 | ); | |
45 | return msg; | |
46 | } | |
47 | ||
48 | #define push_string(msg, field, str) \ | |
49 | push_string_impl(msg, offsetof(stroke_msg_t, field), str) | |
50 | ||
51 | static void push_string_impl(stroke_msg_t **msg, size_t offset, char *string) | |
52 | { | |
53 | size_t cur_len = (*msg)->length, str_len; | |
54 | ||
55 | if (!string) | |
56 | { | |
57 | return; | |
58 | } | |
59 | str_len = strlen(string) + 1; | |
60 | if (cur_len + str_len >= UINT16_MAX) | |
4749578d | 61 | { |
d8fe354a TB |
62 | (*msg)->length = UINT16_MAX; |
63 | return; | |
4749578d | 64 | } |
d8fe354a | 65 | while (cur_len + str_len > sizeof(stroke_msg_t) + (*msg)->buflen) |
ecadab2b | 66 | { |
d8fe354a TB |
67 | *msg = realloc(*msg, sizeof(stroke_msg_t) + (*msg)->buflen + |
68 | STROKE_BUF_LEN_INC); | |
69 | (*msg)->buflen += STROKE_BUF_LEN_INC; | |
ecadab2b | 70 | } |
d8fe354a TB |
71 | (*msg)->length += str_len; |
72 | strcpy((char*)*msg + cur_len, string); | |
73 | *(char**)((char*)*msg + offset) = (char*)cur_len; | |
4749578d MW |
74 | } |
75 | ||
d8fe354a | 76 | static int send_stroke_msg(stroke_msg_t *msg) |
4749578d | 77 | { |
906a4096 TB |
78 | stream_t *stream; |
79 | char *uri, buffer[512], *pass; | |
80 | int count; | |
7daf5226 | 81 | |
d8fe354a TB |
82 | if (msg->length == UINT16_MAX) |
83 | { | |
84 | fprintf(stderr, "stroke message exceeds maximum buffer size"); | |
85 | free(msg); | |
86 | return -1; | |
87 | } | |
88 | ||
4182c86a | 89 | msg->output_verbosity = output_verbosity; |
7daf5226 | 90 | |
dcb16841 TB |
91 | uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket", |
92 | "unix://" STROKE_SOCKET, daemon_name); | |
906a4096 TB |
93 | stream = lib->streams->connect(lib->streams, uri); |
94 | if (!stream) | |
4749578d | 95 | { |
906a4096 | 96 | fprintf(stderr, "failed to connect to stroke socket '%s'\n", uri); |
d8fe354a | 97 | free(msg); |
4749578d MW |
98 | return -1; |
99 | } | |
7daf5226 | 100 | |
906a4096 | 101 | if (!stream->write_all(stream, msg, msg->length)) |
4749578d | 102 | { |
906a4096 TB |
103 | fprintf(stderr, "sending stroke message failed\n"); |
104 | stream->destroy(stream); | |
d8fe354a | 105 | free(msg); |
4749578d MW |
106 | return -1; |
107 | } | |
7daf5226 | 108 | |
906a4096 | 109 | while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0) |
f2ee13a7 | 110 | { |
906a4096 | 111 | buffer[count] = '\0'; |
7daf5226 | 112 | |
ff5cb888 | 113 | /* we prompt if we receive a magic keyword */ |
906a4096 TB |
114 | if ((count >= 12 && streq(buffer + count - 12, "Passphrase:\n")) || |
115 | (count >= 10 && streq(buffer + count - 10, "Password:\n")) || | |
116 | (count >= 5 && streq(buffer + count - 5, "PIN:\n"))) | |
750bbcf9 | 117 | { |
70789d28 MW |
118 | /* remove trailing newline */ |
119 | pass = strrchr(buffer, '\n'); | |
120 | if (pass) | |
750bbcf9 | 121 | { |
70789d28 | 122 | *pass = ' '; |
750bbcf9 | 123 | } |
2421ac9e | 124 | #ifdef HAVE_GETPASS |
70789d28 | 125 | pass = getpass(buffer); |
2421ac9e TB |
126 | #else |
127 | pass = ""; | |
128 | #endif | |
70789d28 MW |
129 | if (pass) |
130 | { | |
906a4096 TB |
131 | stream->write_all(stream, pass, strlen(pass)); |
132 | stream->write_all(stream, "\n", 1); | |
70789d28 MW |
133 | } |
134 | } | |
135 | else | |
136 | { | |
137 | printf("%s", buffer); | |
750bbcf9 | 138 | } |
f2ee13a7 | 139 | } |
906a4096 | 140 | if (count < 0) |
f2ee13a7 | 141 | { |
906a4096 | 142 | fprintf(stderr, "reading stroke response failed\n"); |
f2ee13a7 | 143 | } |
906a4096 | 144 | stream->destroy(stream); |
d8fe354a | 145 | free(msg); |
4749578d MW |
146 | return 0; |
147 | } | |
148 | ||
149 | static int add_connection(char *name, | |
7daf5226 | 150 | char *my_id, char *other_id, |
f2ee13a7 | 151 | char *my_addr, char *other_addr, |
34443902 | 152 | char *my_nets, char *other_nets) |
4749578d | 153 | { |
d8fe354a TB |
154 | stroke_msg_t *msg; |
155 | ||
156 | msg = create_stroke_msg(STR_ADD_CONN); | |
157 | ||
158 | push_string(&msg, add_conn.name, name); | |
159 | msg->add_conn.version = 2; | |
160 | msg->add_conn.mode = 1; | |
161 | msg->add_conn.mobike = 1; | |
162 | msg->add_conn.dpd.action = 1; | |
163 | msg->add_conn.install_policy = 1; | |
164 | ||
165 | push_string(&msg, add_conn.me.id, my_id); | |
166 | push_string(&msg, add_conn.me.address, my_addr); | |
167 | msg->add_conn.me.ikeport = 500; | |
168 | push_string(&msg, add_conn.me.subnets, my_nets); | |
169 | msg->add_conn.me.sendcert = 1; | |
170 | msg->add_conn.me.to_port = 65535; | |
171 | ||
172 | push_string(&msg, add_conn.other.id, other_id); | |
173 | push_string(&msg, add_conn.other.address, other_addr); | |
174 | msg->add_conn.other.ikeport = 500; | |
175 | push_string(&msg, add_conn.other.subnets, other_nets); | |
176 | msg->add_conn.other.sendcert = 1; | |
177 | msg->add_conn.other.to_port = 65535; | |
178 | ||
179 | return send_stroke_msg(msg); | |
4749578d MW |
180 | } |
181 | ||
9fe14f4b MW |
182 | static int del_connection(char *name) |
183 | { | |
d8fe354a | 184 | stroke_msg_t *msg; |
7daf5226 | 185 | |
d8fe354a TB |
186 | msg = create_stroke_msg(STR_DEL_CONN); |
187 | push_string(&msg, initiate.name, name); | |
188 | return send_stroke_msg(msg); | |
9fe14f4b MW |
189 | } |
190 | ||
4749578d MW |
191 | static int initiate_connection(char *name) |
192 | { | |
d8fe354a | 193 | stroke_msg_t *msg; |
7daf5226 | 194 | |
d8fe354a TB |
195 | msg = create_stroke_msg(STR_INITIATE); |
196 | push_string(&msg, initiate.name, name); | |
197 | return send_stroke_msg(msg); | |
4749578d MW |
198 | } |
199 | ||
f2ee13a7 MW |
200 | static int terminate_connection(char *name) |
201 | { | |
d8fe354a | 202 | stroke_msg_t *msg; |
7daf5226 | 203 | |
d8fe354a TB |
204 | msg = create_stroke_msg(STR_TERMINATE); |
205 | push_string(&msg, initiate.name, name); | |
206 | return send_stroke_msg(msg); | |
f2ee13a7 MW |
207 | } |
208 | ||
13106499 MW |
209 | static int terminate_connection_srcip(char *start, char *end) |
210 | { | |
d8fe354a | 211 | stroke_msg_t *msg; |
7daf5226 | 212 | |
d8fe354a TB |
213 | msg = create_stroke_msg(STR_TERMINATE_SRCIP); |
214 | push_string(&msg, terminate_srcip.start, start); | |
215 | push_string(&msg, terminate_srcip.end, end); | |
216 | return send_stroke_msg(msg); | |
13106499 MW |
217 | } |
218 | ||
851d6048 MW |
219 | static int rekey_connection(char *name) |
220 | { | |
d8fe354a | 221 | stroke_msg_t *msg; |
851d6048 | 222 | |
d8fe354a TB |
223 | msg = create_stroke_msg(STR_REKEY); |
224 | push_string(&msg, rekey.name, name); | |
225 | return send_stroke_msg(msg); | |
851d6048 MW |
226 | } |
227 | ||
45f76a7d MW |
228 | static int route_connection(char *name) |
229 | { | |
d8fe354a | 230 | stroke_msg_t *msg; |
7daf5226 | 231 | |
d8fe354a TB |
232 | msg = create_stroke_msg(STR_ROUTE); |
233 | push_string(&msg, route.name, name); | |
234 | return send_stroke_msg(msg); | |
45f76a7d MW |
235 | } |
236 | ||
237 | static int unroute_connection(char *name) | |
238 | { | |
d8fe354a | 239 | stroke_msg_t *msg; |
7daf5226 | 240 | |
d8fe354a TB |
241 | msg = create_stroke_msg(STR_UNROUTE); |
242 | push_string(&msg, unroute.name, name); | |
243 | return send_stroke_msg(msg); | |
45f76a7d MW |
244 | } |
245 | ||
53472332 | 246 | static int show_status(stroke_keyword_t kw, char *connection) |
f2ee13a7 | 247 | { |
d8fe354a | 248 | stroke_msg_t *msg; |
7daf5226 | 249 | |
a694b481 MW |
250 | switch (kw) |
251 | { | |
252 | case STROKE_STATUSALL: | |
d8fe354a | 253 | msg = create_stroke_msg(STR_STATUS_ALL); |
a694b481 MW |
254 | break; |
255 | case STROKE_STATUSALL_NOBLK: | |
d8fe354a | 256 | msg = create_stroke_msg(STR_STATUS_ALL_NOBLK); |
a694b481 MW |
257 | break; |
258 | default: | |
d8fe354a | 259 | msg = create_stroke_msg(STR_STATUS); |
a694b481 MW |
260 | break; |
261 | } | |
d8fe354a TB |
262 | push_string(&msg, status.name, connection); |
263 | return send_stroke_msg(msg); | |
f2ee13a7 MW |
264 | } |
265 | ||
53472332 | 266 | static int list_flags[] = { |
d1cbe551 | 267 | LIST_PUBKEYS, |
53472332 AS |
268 | LIST_CERTS, |
269 | LIST_CACERTS, | |
34d7935e | 270 | LIST_OCSPCERTS, |
f9e0dc3e AS |
271 | LIST_AACERTS, |
272 | LIST_ACERTS, | |
273 | LIST_GROUPS, | |
34d7935e | 274 | LIST_CAINFOS, |
53472332 | 275 | LIST_CRLS, |
34d7935e | 276 | LIST_OCSP, |
94822086 | 277 | LIST_ALGS, |
2d2ffa58 | 278 | LIST_PLUGINS, |
53472332 AS |
279 | LIST_ALL |
280 | }; | |
281 | ||
1c3aa9bf | 282 | static int list(stroke_keyword_t kw, bool utc) |
86a7937b | 283 | { |
d8fe354a | 284 | stroke_msg_t *msg; |
7daf5226 | 285 | |
d8fe354a TB |
286 | msg = create_stroke_msg(STR_LIST); |
287 | msg->list.utc = utc; | |
288 | msg->list.flags = list_flags[kw - STROKE_LIST_FIRST]; | |
289 | return send_stroke_msg(msg); | |
86a7937b MW |
290 | } |
291 | ||
76dafed7 | 292 | static int reread_flags[] = { |
a74be4f7 | 293 | REREAD_SECRETS, |
76dafed7 | 294 | REREAD_CACERTS, |
34d7935e | 295 | REREAD_OCSPCERTS, |
f9e0dc3e AS |
296 | REREAD_AACERTS, |
297 | REREAD_ACERTS, | |
76dafed7 AS |
298 | REREAD_CRLS, |
299 | REREAD_ALL | |
300 | }; | |
301 | ||
302 | static int reread(stroke_keyword_t kw) | |
303 | { | |
d8fe354a | 304 | stroke_msg_t *msg; |
7daf5226 | 305 | |
d8fe354a TB |
306 | msg = create_stroke_msg(STR_REREAD); |
307 | msg->reread.flags = reread_flags[kw - STROKE_REREAD_FIRST]; | |
308 | return send_stroke_msg(msg); | |
76dafed7 AS |
309 | } |
310 | ||
34d7935e | 311 | static int purge_flags[] = { |
83242706 | 312 | PURGE_OCSP, |
cf5866b9 MW |
313 | PURGE_CRLS, |
314 | PURGE_CERTS, | |
fc2e43eb | 315 | PURGE_IKE, |
34d7935e AS |
316 | }; |
317 | ||
318 | static int purge(stroke_keyword_t kw) | |
319 | { | |
d8fe354a | 320 | stroke_msg_t *msg; |
7daf5226 | 321 | |
d8fe354a TB |
322 | msg = create_stroke_msg(STR_PURGE); |
323 | msg->purge.flags = purge_flags[kw - STROKE_PURGE_FIRST]; | |
324 | return send_stroke_msg(msg); | |
34d7935e AS |
325 | } |
326 | ||
3d711a68 MW |
327 | static int export_flags[] = { |
328 | EXPORT_X509, | |
de2debf8 MW |
329 | EXPORT_CONN_CERT, |
330 | EXPORT_CONN_CHAIN, | |
3d711a68 MW |
331 | }; |
332 | ||
333 | static int export(stroke_keyword_t kw, char *selector) | |
6b83549d | 334 | { |
d8fe354a | 335 | stroke_msg_t *msg; |
6b83549d | 336 | |
d8fe354a TB |
337 | msg = create_stroke_msg(STR_EXPORT); |
338 | push_string(&msg, export.selector, selector); | |
339 | msg->export.flags = export_flags[kw - STROKE_EXPORT_FIRST]; | |
340 | return send_stroke_msg(msg); | |
3d711a68 MW |
341 | } |
342 | ||
343 | static int leases(stroke_keyword_t kw, char *pool, char *address) | |
344 | { | |
d8fe354a | 345 | stroke_msg_t *msg; |
7daf5226 | 346 | |
d8fe354a TB |
347 | msg = create_stroke_msg(STR_LEASES); |
348 | push_string(&msg, leases.pool, pool); | |
349 | push_string(&msg, leases.address, address); | |
350 | return send_stroke_msg(msg); | |
6b83549d MW |
351 | } |
352 | ||
dfe9bad9 MW |
353 | static int memusage() |
354 | { | |
d8fe354a | 355 | stroke_msg_t *msg; |
dfe9bad9 | 356 | |
d8fe354a TB |
357 | msg = create_stroke_msg(STR_MEMUSAGE); |
358 | return send_stroke_msg(msg); | |
dfe9bad9 MW |
359 | } |
360 | ||
9f1b303a TB |
361 | static int user_credentials(char *name, char *user, char *pass) |
362 | { | |
d8fe354a TB |
363 | stroke_msg_t *msg; |
364 | ||
365 | msg = create_stroke_msg(STR_USER_CREDS); | |
366 | push_string(&msg, user_creds.name, name); | |
367 | push_string(&msg, user_creds.username, user); | |
368 | push_string(&msg, user_creds.password, pass); | |
369 | return send_stroke_msg(msg); | |
9f1b303a TB |
370 | } |
371 | ||
cf729248 | 372 | static int counters(int reset, char *name) |
d022322b | 373 | { |
d8fe354a | 374 | stroke_msg_t *msg; |
cf729248 | 375 | |
d8fe354a TB |
376 | msg = create_stroke_msg(STR_COUNTERS); |
377 | push_string(&msg, counters.name, name); | |
378 | msg->counters.reset = reset; | |
379 | return send_stroke_msg(msg); | |
d022322b MW |
380 | } |
381 | ||
0ae1deb8 | 382 | static int set_loglevel(char *type, u_int level) |
f2ee13a7 | 383 | { |
d8fe354a | 384 | stroke_msg_t *msg; |
7daf5226 | 385 | |
d8fe354a TB |
386 | msg = create_stroke_msg(STR_LOGLEVEL); |
387 | push_string(&msg, loglevel.type, type); | |
388 | msg->loglevel.level = level; | |
389 | return send_stroke_msg(msg); | |
f2ee13a7 MW |
390 | } |
391 | ||
dcb16841 | 392 | static int usage(char *error) |
f2ee13a7 | 393 | { |
dcb16841 TB |
394 | FILE *out = error ? stderr : stdout; |
395 | ||
396 | fprintf(out, "stroke [OPTIONS] command [ARGUMENTS]\n\n"); | |
397 | fprintf(out, "Options:\n"); | |
398 | fprintf(out, " -h, --help print this information.\n"); | |
399 | fprintf(out, " -d, --daemon=NAME name of the daemon.\n"); | |
400 | fprintf(out, "Commands:\n"); | |
401 | fprintf(out, " Add a connection:\n"); | |
402 | fprintf(out, " stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n"); | |
403 | fprintf(out, " MY_NET OTHER_NET\n"); | |
404 | fprintf(out, " where: ID is any IKEv2 ID \n"); | |
405 | fprintf(out, " ADDR is a IPv4 address\n"); | |
406 | fprintf(out, " NET is a IPv4 subnet in CIDR notation\n"); | |
407 | fprintf(out, " Delete a connection:\n"); | |
408 | fprintf(out, " stroke delete NAME\n"); | |
409 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
410 | fprintf(out, " Initiate a connection:\n"); | |
411 | fprintf(out, " stroke up NAME\n"); | |
412 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
413 | fprintf(out, " Initiate a connection without blocking:\n"); | |
414 | fprintf(out, " stroke up-nb NAME\n"); | |
415 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
416 | fprintf(out, " Terminate a connection:\n"); | |
417 | fprintf(out, " stroke down NAME\n"); | |
418 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
419 | fprintf(out, " Terminate a connection without blocking:\n"); | |
420 | fprintf(out, " stroke down-nb NAME\n"); | |
421 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
422 | fprintf(out, " Terminate a connection by remote srcip:\n"); | |
423 | fprintf(out, " stroke down-srcip START [END]\n"); | |
424 | fprintf(out, " where: START and optional END define the clients source IP\n"); | |
425 | fprintf(out, " Set loglevel for a logging type:\n"); | |
426 | fprintf(out, " stroke loglevel TYPE LEVEL\n"); | |
427 | fprintf(out, " where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n"); | |
428 | fprintf(out, " LEVEL is -1|0|1|2|3|4\n"); | |
429 | fprintf(out, " Show connection status:\n"); | |
430 | fprintf(out, " stroke status\n"); | |
431 | fprintf(out, " Show extended status information:\n"); | |
432 | fprintf(out, " stroke statusall\n"); | |
433 | fprintf(out, " Show extended status information without blocking:\n"); | |
434 | fprintf(out, " stroke statusall-nb\n"); | |
435 | fprintf(out, " Show list of authority and attribute certificates:\n"); | |
02d43102 | 436 | fprintf(out, " stroke listcacerts|listocspcerts|listaacerts|listacerts [--utc]\n"); |
dcb16841 | 437 | fprintf(out, " Show list of end entity certificates, ca info records and crls:\n"); |
02d43102 | 438 | fprintf(out, " stroke listcerts|listcainfos|listcrls|listall [--utc]\n"); |
dcb16841 TB |
439 | fprintf(out, " Show list of supported algorithms:\n"); |
440 | fprintf(out, " stroke listalgs\n"); | |
441 | fprintf(out, " Reload authority and attribute certificates:\n"); | |
442 | fprintf(out, " stroke rereadcacerts|rereadocspcerts|rereadaacerts|rereadacerts\n"); | |
443 | fprintf(out, " Reload secrets and crls:\n"); | |
444 | fprintf(out, " stroke rereadsecrets|rereadcrls|rereadall\n"); | |
445 | fprintf(out, " Purge ocsp cache entries:\n"); | |
446 | fprintf(out, " stroke purgeocsp\n"); | |
447 | fprintf(out, " Purge CRL cache entries:\n"); | |
448 | fprintf(out, " stroke purgecrls\n"); | |
449 | fprintf(out, " Purge X509 cache entries:\n"); | |
450 | fprintf(out, " stroke purgecerts\n"); | |
451 | fprintf(out, " Purge IKE_SAs without a CHILD_SA:\n"); | |
452 | fprintf(out, " stroke purgeike\n"); | |
453 | fprintf(out, " Export credentials to the console:\n"); | |
454 | fprintf(out, " stroke exportx509 DN\n"); | |
455 | fprintf(out, " stroke exportconncert connname\n"); | |
456 | fprintf(out, " stroke exportconnchain connname\n"); | |
457 | fprintf(out, " Show current memory usage:\n"); | |
458 | fprintf(out, " stroke memusage\n"); | |
459 | fprintf(out, " Show leases of a pool:\n"); | |
460 | fprintf(out, " stroke leases [POOL [ADDRESS]]\n"); | |
461 | fprintf(out, " Set username and password for a connection:\n"); | |
462 | fprintf(out, " stroke user-creds NAME USERNAME [PASSWORD]\n"); | |
463 | fprintf(out, " where: NAME is a connection name added with \"stroke add\"\n"); | |
464 | fprintf(out, " USERNAME is the username\n"); | |
465 | fprintf(out, " PASSWORD is the optional password, you'll be asked to enter it if not given\n"); | |
466 | fprintf(out, " Show IKE counters:\n"); | |
467 | fprintf(out, " stroke listcounters [connection-name]\n"); | |
468 | ||
f2ee13a7 MW |
469 | if (error) |
470 | { | |
dcb16841 TB |
471 | fprintf(out, "\nError: %s\n", error); |
472 | return -1; | |
f2ee13a7 | 473 | } |
dcb16841 | 474 | return 0; |
f2ee13a7 MW |
475 | } |
476 | ||
4749578d MW |
477 | int main(int argc, char *argv[]) |
478 | { | |
53472332 | 479 | const stroke_token_t *token; |
dcb16841 | 480 | char *cmd; |
1c3aa9bf | 481 | bool utc = FALSE; |
f2c2d395 | 482 | int res = 0; |
53472332 | 483 | |
34d3bfcf | 484 | library_init(NULL, "stroke"); |
1c31d34e TB |
485 | atexit(library_deinit); |
486 | ||
dcb16841 | 487 | while (true) |
f2ee13a7 | 488 | { |
dcb16841 TB |
489 | struct option long_opts[] = { |
490 | {"help", no_argument, NULL, 'h' }, | |
1c3aa9bf | 491 | {"utc", no_argument, NULL, 'u' }, |
dcb16841 TB |
492 | {"daemon", required_argument, NULL, 'd' }, |
493 | {0,0,0,0}, | |
494 | }; | |
495 | switch (getopt_long(argc, argv, "hd:", long_opts, NULL)) | |
496 | { | |
497 | case EOF: | |
498 | break; | |
499 | case 'h': | |
500 | return usage(NULL); | |
501 | case 'd': | |
502 | daemon_name = optarg; | |
503 | continue; | |
1c3aa9bf TB |
504 | case 'u': |
505 | utc = TRUE; | |
506 | continue; | |
dcb16841 TB |
507 | default: |
508 | return usage("invalid option"); | |
509 | } | |
510 | break; | |
f2ee13a7 | 511 | } |
7daf5226 | 512 | |
dcb16841 TB |
513 | if (optind == argc) |
514 | { | |
515 | return usage("command missing"); | |
516 | } | |
9820c0e2 | 517 | |
dcb16841 TB |
518 | cmd = argv[optind++]; |
519 | token = in_word_set(cmd, strlen(cmd)); | |
53472332 | 520 | if (token == NULL) |
4749578d | 521 | { |
dcb16841 | 522 | return usage("unknown command"); |
f2ee13a7 | 523 | } |
53472332 | 524 | |
dcb16841 TB |
525 | /* make argv/argc only cover positional arguments */ |
526 | argv = &argv[optind]; | |
527 | argc = argc - optind; | |
528 | ||
53472332 | 529 | switch (token->kw) |
f2ee13a7 | 530 | { |
53472332 | 531 | case STROKE_ADD: |
dcb16841 | 532 | if (argc < 7) |
53472332 | 533 | { |
dcb16841 | 534 | return usage("\"add\" needs more arguments..."); |
53472332 | 535 | } |
dcb16841 TB |
536 | res = add_connection(argv[0], argv[1], argv[2], argv[3], argv[4], |
537 | argv[5], argv[6]); | |
53472332 AS |
538 | break; |
539 | case STROKE_DELETE: | |
540 | case STROKE_DEL: | |
dcb16841 | 541 | if (argc < 1) |
53472332 | 542 | { |
dcb16841 | 543 | return usage("\"delete\" needs a connection name"); |
53472332 | 544 | } |
dcb16841 | 545 | res = del_connection(argv[0]); |
53472332 | 546 | break; |
4182c86a TB |
547 | case STROKE_UP_NOBLK: |
548 | output_verbosity = -1; | |
549 | /* fall-through */ | |
53472332 | 550 | case STROKE_UP: |
dcb16841 | 551 | if (argc < 1) |
53472332 | 552 | { |
dcb16841 | 553 | return usage("\"up\" needs a connection name"); |
53472332 | 554 | } |
dcb16841 | 555 | res = initiate_connection(argv[0]); |
53472332 | 556 | break; |
4182c86a TB |
557 | case STROKE_DOWN_NOBLK: |
558 | output_verbosity = -1; | |
559 | /* fall-through */ | |
53472332 | 560 | case STROKE_DOWN: |
dcb16841 | 561 | if (argc < 1) |
53472332 | 562 | { |
dcb16841 | 563 | return usage("\"down\" needs a connection name"); |
53472332 | 564 | } |
dcb16841 | 565 | res = terminate_connection(argv[0]); |
53472332 | 566 | break; |
556e426f | 567 | case STROKE_DOWN_SRCIP: |
dcb16841 | 568 | if (argc < 1) |
13106499 | 569 | { |
dcb16841 | 570 | return usage("\"down-srcip\" needs start and optional end address"); |
13106499 | 571 | } |
dcb16841 | 572 | res = terminate_connection_srcip(argv[0], argc > 1 ? argv[1] : NULL); |
13106499 | 573 | break; |
851d6048 | 574 | case STROKE_REKEY: |
dcb16841 | 575 | if (argc < 1) |
851d6048 | 576 | { |
dcb16841 | 577 | return usage("\"rekey\" needs a connection name"); |
851d6048 | 578 | } |
dcb16841 | 579 | res = rekey_connection(argv[0]); |
851d6048 | 580 | break; |
45f76a7d | 581 | case STROKE_ROUTE: |
dcb16841 | 582 | if (argc < 1) |
45f76a7d | 583 | { |
dcb16841 | 584 | return usage("\"route\" needs a connection name"); |
45f76a7d | 585 | } |
dcb16841 | 586 | res = route_connection(argv[0]); |
45f76a7d MW |
587 | break; |
588 | case STROKE_UNROUTE: | |
dcb16841 | 589 | if (argc < 1) |
45f76a7d | 590 | { |
dcb16841 | 591 | return usage("\"unroute\" needs a connection name"); |
45f76a7d | 592 | } |
dcb16841 | 593 | res = unroute_connection(argv[0]); |
45f76a7d | 594 | break; |
53472332 | 595 | case STROKE_LOGLEVEL: |
dcb16841 | 596 | if (argc < 2) |
53472332 | 597 | { |
dcb16841 | 598 | return usage("\"logtype\" needs more parameters..."); |
53472332 | 599 | } |
dcb16841 | 600 | res = set_loglevel(argv[0], atoi(argv[1])); |
53472332 AS |
601 | break; |
602 | case STROKE_STATUS: | |
603 | case STROKE_STATUSALL: | |
a694b481 | 604 | case STROKE_STATUSALL_NOBLK: |
dcb16841 | 605 | res = show_status(token->kw, argc ? argv[0] : NULL); |
53472332 | 606 | break; |
d1cbe551 | 607 | case STROKE_LIST_PUBKEYS: |
53472332 AS |
608 | case STROKE_LIST_CERTS: |
609 | case STROKE_LIST_CACERTS: | |
34d7935e | 610 | case STROKE_LIST_OCSPCERTS: |
0dbc039a AS |
611 | case STROKE_LIST_AACERTS: |
612 | case STROKE_LIST_ACERTS: | |
34d7935e | 613 | case STROKE_LIST_CAINFOS: |
53472332 | 614 | case STROKE_LIST_CRLS: |
34d7935e | 615 | case STROKE_LIST_OCSP: |
94822086 | 616 | case STROKE_LIST_ALGS: |
2d2ffa58 | 617 | case STROKE_LIST_PLUGINS: |
53472332 | 618 | case STROKE_LIST_ALL: |
1c3aa9bf | 619 | res = list(token->kw, utc); |
53472332 | 620 | break; |
0dbc039a | 621 | case STROKE_REREAD_SECRETS: |
76dafed7 | 622 | case STROKE_REREAD_CACERTS: |
0dbc039a AS |
623 | case STROKE_REREAD_OCSPCERTS: |
624 | case STROKE_REREAD_AACERTS: | |
625 | case STROKE_REREAD_ACERTS: | |
76dafed7 AS |
626 | case STROKE_REREAD_CRLS: |
627 | case STROKE_REREAD_ALL: | |
628 | res = reread(token->kw); | |
629 | break; | |
34d7935e | 630 | case STROKE_PURGE_OCSP: |
cf5866b9 MW |
631 | case STROKE_PURGE_CRLS: |
632 | case STROKE_PURGE_CERTS: | |
83242706 | 633 | case STROKE_PURGE_IKE: |
34d7935e AS |
634 | res = purge(token->kw); |
635 | break; | |
3d711a68 | 636 | case STROKE_EXPORT_X509: |
de2debf8 MW |
637 | case STROKE_EXPORT_CONN_CERT: |
638 | case STROKE_EXPORT_CONN_CHAIN: | |
dcb16841 | 639 | if (argc < 1) |
3d711a68 | 640 | { |
dcb16841 | 641 | return usage("\"export\" needs a name"); |
3d711a68 | 642 | } |
dcb16841 | 643 | res = export(token->kw, argv[0]); |
3d711a68 | 644 | break; |
6b83549d | 645 | case STROKE_LEASES: |
dcb16841 TB |
646 | res = leases(token->kw, argc ? argv[0] : NULL, |
647 | argc > 1 ? argv[1] : NULL); | |
6b83549d | 648 | break; |
dfe9bad9 MW |
649 | case STROKE_MEMUSAGE: |
650 | res = memusage(); | |
651 | break; | |
9f1b303a | 652 | case STROKE_USER_CREDS: |
dcb16841 | 653 | if (argc < 2) |
9f1b303a | 654 | { |
dcb16841 | 655 | return usage("\"user-creds\" needs a connection name, " |
9f1b303a TB |
656 | "username and optionally a password"); |
657 | } | |
dcb16841 | 658 | res = user_credentials(argv[0], argv[1], argc > 2 ? argv[2] : NULL); |
9f1b303a | 659 | break; |
d022322b | 660 | case STROKE_COUNTERS: |
cf729248 MW |
661 | case STROKE_COUNTERS_RESET: |
662 | res = counters(token->kw == STROKE_COUNTERS_RESET, | |
dcb16841 | 663 | argc ? argv[0] : NULL); |
d022322b | 664 | break; |
53472332 | 665 | default: |
dcb16841 | 666 | return usage(NULL); |
4749578d | 667 | } |
13e4a62f | 668 | return res; |
4749578d | 669 | } |