ccf1f7cf329fb0a36718b88ff1d316e08659f457
2 * Copyright (C) 2007-2015 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
26 #include "stroke_msg.h"
27 #include "stroke_keywords.h"
34 static char *daemon_name
= "charon";
35 static int output_verbosity
= 1; /* CONTROL */
37 static stroke_msg_t
*create_stroke_msg(int type
)
43 .length
= offsetof(stroke_msg_t
, buffer
),
48 #define push_string(msg, field, str) \
49 push_string_impl(msg, offsetof(stroke_msg_t, field), str)
51 static void push_string_impl(stroke_msg_t
**msg
, size_t offset
, char *string
)
53 size_t cur_len
= (*msg
)->length
, str_len
;
59 str_len
= strlen(string
) + 1;
60 if (cur_len
+ str_len
>= UINT16_MAX
)
62 (*msg
)->length
= UINT16_MAX
;
65 while (cur_len
+ str_len
> sizeof(stroke_msg_t
) + (*msg
)->buflen
)
67 *msg
= realloc(*msg
, sizeof(stroke_msg_t
) + (*msg
)->buflen
+
69 (*msg
)->buflen
+= STROKE_BUF_LEN_INC
;
71 (*msg
)->length
+= str_len
;
72 strcpy((char*)*msg
+ cur_len
, string
);
73 *(char**)((char*)*msg
+ offset
) = (char*)cur_len
;
76 static int send_stroke_msg(stroke_msg_t
*msg
)
79 char *uri
, buffer
[512], *pass
;
82 if (msg
->length
== UINT16_MAX
)
84 fprintf(stderr
, "stroke message exceeds maximum buffer size");
89 msg
->output_verbosity
= output_verbosity
;
91 uri
= lib
->settings
->get_str(lib
->settings
, "%s.plugins.stroke.socket",
92 "unix://" STROKE_SOCKET
, daemon_name
);
93 stream
= lib
->streams
->connect(lib
->streams
, uri
);
96 fprintf(stderr
, "failed to connect to stroke socket '%s'\n", uri
);
101 if (!stream
->write_all(stream
, msg
, msg
->length
))
103 fprintf(stderr
, "sending stroke message failed\n");
104 stream
->destroy(stream
);
109 while ((count
= stream
->read(stream
, buffer
, sizeof(buffer
)-1, TRUE
)) > 0)
111 buffer
[count
] = '\0';
113 /* we prompt if we receive a magic keyword */
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")))
118 /* remove trailing newline */
119 pass
= strrchr(buffer
, '\n');
125 pass
= getpass(buffer
);
131 stream
->write_all(stream
, pass
, strlen(pass
));
132 stream
->write_all(stream
, "\n", 1);
137 printf("%s", buffer
);
142 fprintf(stderr
, "reading stroke response failed\n");
144 stream
->destroy(stream
);
149 static int add_connection(char *name
,
150 char *my_id
, char *other_id
,
151 char *my_addr
, char *other_addr
,
152 char *my_nets
, char *other_nets
)
156 msg
= create_stroke_msg(STR_ADD_CONN
);
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;
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;
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;
179 return send_stroke_msg(msg
);
182 static int del_connection(char *name
)
186 msg
= create_stroke_msg(STR_DEL_CONN
);
187 push_string(&msg
, initiate
.name
, name
);
188 return send_stroke_msg(msg
);
191 static int initiate_connection(char *name
)
195 msg
= create_stroke_msg(STR_INITIATE
);
196 push_string(&msg
, initiate
.name
, name
);
197 return send_stroke_msg(msg
);
200 static int terminate_connection(char *name
)
204 msg
= create_stroke_msg(STR_TERMINATE
);
205 push_string(&msg
, initiate
.name
, name
);
206 return send_stroke_msg(msg
);
209 static int terminate_connection_srcip(char *start
, char *end
)
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
);
219 static int rekey_connection(char *name
)
223 msg
= create_stroke_msg(STR_REKEY
);
224 push_string(&msg
, rekey
.name
, name
);
225 return send_stroke_msg(msg
);
228 static int route_connection(char *name
)
232 msg
= create_stroke_msg(STR_ROUTE
);
233 push_string(&msg
, route
.name
, name
);
234 return send_stroke_msg(msg
);
237 static int unroute_connection(char *name
)
241 msg
= create_stroke_msg(STR_UNROUTE
);
242 push_string(&msg
, unroute
.name
, name
);
243 return send_stroke_msg(msg
);
246 static int show_status(stroke_keyword_t kw
, char *connection
)
252 case STROKE_STATUSALL
:
253 msg
= create_stroke_msg(STR_STATUS_ALL
);
255 case STROKE_STATUSALL_NOBLK
:
256 msg
= create_stroke_msg(STR_STATUS_ALL_NOBLK
);
259 msg
= create_stroke_msg(STR_STATUS
);
262 push_string(&msg
, status
.name
, connection
);
263 return send_stroke_msg(msg
);
266 static int list_flags
[] = {
282 static int list(stroke_keyword_t kw
, int utc
)
286 msg
= create_stroke_msg(STR_LIST
);
288 msg
->list
.flags
= list_flags
[kw
- STROKE_LIST_FIRST
];
289 return send_stroke_msg(msg
);
292 static int reread_flags
[] = {
302 static int reread(stroke_keyword_t kw
)
306 msg
= create_stroke_msg(STR_REREAD
);
307 msg
->reread
.flags
= reread_flags
[kw
- STROKE_REREAD_FIRST
];
308 return send_stroke_msg(msg
);
311 static int purge_flags
[] = {
318 static int purge(stroke_keyword_t kw
)
322 msg
= create_stroke_msg(STR_PURGE
);
323 msg
->purge
.flags
= purge_flags
[kw
- STROKE_PURGE_FIRST
];
324 return send_stroke_msg(msg
);
327 static int export_flags
[] = {
333 static int export(stroke_keyword_t kw
, char *selector
)
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
);
343 static int leases(stroke_keyword_t kw
, char *pool
, char *address
)
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
);
353 static int memusage()
357 msg
= create_stroke_msg(STR_MEMUSAGE
);
358 return send_stroke_msg(msg
);
361 static int user_credentials(char *name
, char *user
, char *pass
)
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
);
372 static int counters(int reset
, char *name
)
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
);
382 static int set_loglevel(char *type
, u_int level
)
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
);
392 static int usage(char *error
)
394 FILE *out
= error ? stderr
: stdout
;
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");
436 fprintf(out
, " stroke listcacerts|listocspcerts|listaacerts|listacerts [--utc]\n");
437 fprintf(out
, " Show list of end entity certificates, ca info records and crls:\n");
438 fprintf(out
, " stroke listcerts|listcainfos|listcrls|listall [--utc]\n");
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");
471 fprintf(out
, "\nError: %s\n", error
);
477 int main(int argc
, char *argv
[])
479 const stroke_token_t
*token
;
483 library_init(NULL
, "stroke");
484 atexit(library_deinit
);
488 struct option long_opts
[] = {
489 {"help", no_argument
, NULL
, 'h' },
490 {"daemon", required_argument
, NULL
, 'd' },
493 switch (getopt_long(argc
, argv
, "hd:", long_opts
, NULL
))
500 daemon_name
= optarg
;
503 return usage("invalid option");
510 return usage("command missing");
513 cmd
= argv
[optind
++];
514 token
= in_word_set(cmd
, strlen(cmd
));
517 return usage("unknown command");
520 /* make argv/argc only cover positional arguments */
521 argv
= &argv
[optind
];
522 argc
= argc
- optind
;
529 return usage("\"add\" needs more arguments...");
531 res
= add_connection(argv
[0], argv
[1], argv
[2], argv
[3], argv
[4],
538 return usage("\"delete\" needs a connection name");
540 res
= del_connection(argv
[0]);
542 case STROKE_UP_NOBLK
:
543 output_verbosity
= -1;
548 return usage("\"up\" needs a connection name");
550 res
= initiate_connection(argv
[0]);
552 case STROKE_DOWN_NOBLK
:
553 output_verbosity
= -1;
558 return usage("\"down\" needs a connection name");
560 res
= terminate_connection(argv
[0]);
562 case STROKE_DOWN_SRCIP
:
565 return usage("\"down-srcip\" needs start and optional end address");
567 res
= terminate_connection_srcip(argv
[0], argc
> 1 ? argv
[1] : NULL
);
572 return usage("\"rekey\" needs a connection name");
574 res
= rekey_connection(argv
[0]);
579 return usage("\"route\" needs a connection name");
581 res
= route_connection(argv
[0]);
586 return usage("\"unroute\" needs a connection name");
588 res
= unroute_connection(argv
[0]);
590 case STROKE_LOGLEVEL
:
593 return usage("\"logtype\" needs more parameters...");
595 res
= set_loglevel(argv
[0], atoi(argv
[1]));
598 case STROKE_STATUSALL
:
599 case STROKE_STATUSALL_NOBLK
:
600 res
= show_status(token
->kw
, argc ? argv
[0] : NULL
);
602 case STROKE_LIST_PUBKEYS
:
603 case STROKE_LIST_CERTS
:
604 case STROKE_LIST_CACERTS
:
605 case STROKE_LIST_OCSPCERTS
:
606 case STROKE_LIST_AACERTS
:
607 case STROKE_LIST_ACERTS
:
608 case STROKE_LIST_CAINFOS
:
609 case STROKE_LIST_CRLS
:
610 case STROKE_LIST_OCSP
:
611 case STROKE_LIST_ALGS
:
612 case STROKE_LIST_PLUGINS
:
613 case STROKE_LIST_ALL
:
614 res
= list(token
->kw
, argc
&& streq(argv
[0], "--utc"));
616 case STROKE_REREAD_SECRETS
:
617 case STROKE_REREAD_CACERTS
:
618 case STROKE_REREAD_OCSPCERTS
:
619 case STROKE_REREAD_AACERTS
:
620 case STROKE_REREAD_ACERTS
:
621 case STROKE_REREAD_CRLS
:
622 case STROKE_REREAD_ALL
:
623 res
= reread(token
->kw
);
625 case STROKE_PURGE_OCSP
:
626 case STROKE_PURGE_CRLS
:
627 case STROKE_PURGE_CERTS
:
628 case STROKE_PURGE_IKE
:
629 res
= purge(token
->kw
);
631 case STROKE_EXPORT_X509
:
632 case STROKE_EXPORT_CONN_CERT
:
633 case STROKE_EXPORT_CONN_CHAIN
:
636 return usage("\"export\" needs a name");
638 res
= export(token
->kw
, argv
[0]);
641 res
= leases(token
->kw
, argc ? argv
[0] : NULL
,
642 argc
> 1 ? argv
[1] : NULL
);
644 case STROKE_MEMUSAGE
:
647 case STROKE_USER_CREDS
:
650 return usage("\"user-creds\" needs a connection name, "
651 "username and optionally a password");
653 res
= user_credentials(argv
[0], argv
[1], argc
> 2 ? argv
[2] : NULL
);
655 case STROKE_COUNTERS
:
656 case STROKE_COUNTERS_RESET
:
657 res
= counters(token
->kw
== STROKE_COUNTERS_RESET
,
658 argc ? argv
[0] : NULL
);