2 * Copyright (C) 2007-2014 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
24 #include "stroke_msg.h"
25 #include "stroke_keywords.h"
32 static int output_verbosity
= 1; /* CONTROL */
34 static char* push_string(stroke_msg_t
*msg
, char *string
)
36 unsigned long string_start
= msg
->length
;
38 if (string
== NULL
|| msg
->length
+ strlen(string
) >= sizeof(stroke_msg_t
))
44 msg
->length
+= strlen(string
) + 1;
45 strcpy((char*)msg
+ string_start
, string
);
46 return (char*)string_start
;
50 static int send_stroke_msg (stroke_msg_t
*msg
)
53 char *uri
, buffer
[512], *pass
;
56 msg
->output_verbosity
= output_verbosity
;
58 uri
= lib
->settings
->get_str(lib
->settings
, "charon.plugins.stroke.socket",
59 "unix://" STROKE_SOCKET
);
60 stream
= lib
->streams
->connect(lib
->streams
, uri
);
63 fprintf(stderr
, "failed to connect to stroke socket '%s'\n", uri
);
67 if (!stream
->write_all(stream
, msg
, msg
->length
))
69 fprintf(stderr
, "sending stroke message failed\n");
70 stream
->destroy(stream
);
74 while ((count
= stream
->read(stream
, buffer
, sizeof(buffer
)-1, TRUE
)) > 0)
78 /* we prompt if we receive a magic keyword */
79 if ((count
>= 12 && streq(buffer
+ count
- 12, "Passphrase:\n")) ||
80 (count
>= 10 && streq(buffer
+ count
- 10, "Password:\n")) ||
81 (count
>= 5 && streq(buffer
+ count
- 5, "PIN:\n")))
83 /* remove trailing newline */
84 pass
= strrchr(buffer
, '\n');
90 pass
= getpass(buffer
);
96 stream
->write_all(stream
, pass
, strlen(pass
));
97 stream
->write_all(stream
, "\n", 1);
102 printf("%s", buffer
);
107 fprintf(stderr
, "reading stroke response failed\n");
109 stream
->destroy(stream
);
113 static int add_connection(char *name
,
114 char *my_id
, char *other_id
,
115 char *my_addr
, char *other_addr
,
116 char *my_nets
, char *other_nets
)
120 memset(&msg
, 0, sizeof(msg
));
121 msg
.length
= offsetof(stroke_msg_t
, buffer
);
122 msg
.type
= STR_ADD_CONN
;
124 msg
.add_conn
.name
= push_string(&msg
, name
);
125 msg
.add_conn
.version
= 2;
126 msg
.add_conn
.mode
= 1;
127 msg
.add_conn
.mobike
= 1;
128 msg
.add_conn
.dpd
.action
= 1;
129 msg
.add_conn
.install_policy
= 1;
131 msg
.add_conn
.me
.id
= push_string(&msg
, my_id
);
132 msg
.add_conn
.me
.address
= push_string(&msg
, my_addr
);
133 msg
.add_conn
.me
.ikeport
= 500;
134 msg
.add_conn
.me
.subnets
= push_string(&msg
, my_nets
);
135 msg
.add_conn
.me
.sendcert
= 1;
136 msg
.add_conn
.me
.to_port
= 65535;
138 msg
.add_conn
.other
.id
= push_string(&msg
, other_id
);
139 msg
.add_conn
.other
.address
= push_string(&msg
, other_addr
);
140 msg
.add_conn
.other
.ikeport
= 500;
141 msg
.add_conn
.other
.subnets
= push_string(&msg
, other_nets
);
142 msg
.add_conn
.other
.sendcert
= 1;
143 msg
.add_conn
.other
.to_port
= 65535;
145 return send_stroke_msg(&msg
);
148 static int del_connection(char *name
)
152 msg
.length
= offsetof(stroke_msg_t
, buffer
);
153 msg
.type
= STR_DEL_CONN
;
154 msg
.initiate
.name
= push_string(&msg
, name
);
155 return send_stroke_msg(&msg
);
158 static int initiate_connection(char *name
)
162 msg
.length
= offsetof(stroke_msg_t
, buffer
);
163 msg
.type
= STR_INITIATE
;
164 msg
.initiate
.name
= push_string(&msg
, name
);
165 return send_stroke_msg(&msg
);
168 static int terminate_connection(char *name
)
172 msg
.type
= STR_TERMINATE
;
173 msg
.length
= offsetof(stroke_msg_t
, buffer
);
174 msg
.initiate
.name
= push_string(&msg
, name
);
175 return send_stroke_msg(&msg
);
178 static int terminate_connection_srcip(char *start
, char *end
)
182 msg
.type
= STR_TERMINATE_SRCIP
;
183 msg
.length
= offsetof(stroke_msg_t
, buffer
);
184 msg
.terminate_srcip
.start
= push_string(&msg
, start
);
185 msg
.terminate_srcip
.end
= push_string(&msg
, end
);
186 return send_stroke_msg(&msg
);
189 static int rekey_connection(char *name
)
193 msg
.type
= STR_REKEY
;
194 msg
.length
= offsetof(stroke_msg_t
, buffer
);
195 msg
.rekey
.name
= push_string(&msg
, name
);
196 return send_stroke_msg(&msg
);
199 static int route_connection(char *name
)
203 msg
.type
= STR_ROUTE
;
204 msg
.length
= offsetof(stroke_msg_t
, buffer
);
205 msg
.route
.name
= push_string(&msg
, name
);
206 return send_stroke_msg(&msg
);
209 static int unroute_connection(char *name
)
213 msg
.type
= STR_UNROUTE
;
214 msg
.length
= offsetof(stroke_msg_t
, buffer
);
215 msg
.unroute
.name
= push_string(&msg
, name
);
216 return send_stroke_msg(&msg
);
219 static int show_status(stroke_keyword_t kw
, char *connection
)
225 case STROKE_STATUSALL
:
226 msg
.type
= STR_STATUS_ALL
;
228 case STROKE_STATUSALL_NOBLK
:
229 msg
.type
= STR_STATUS_ALL_NOBLK
;
232 msg
.type
= STR_STATUS
;
235 msg
.length
= offsetof(stroke_msg_t
, buffer
);
236 msg
.status
.name
= push_string(&msg
, connection
);
237 return send_stroke_msg(&msg
);
240 static int list_flags
[] = {
256 static int list(stroke_keyword_t kw
, int utc
)
261 msg
.length
= offsetof(stroke_msg_t
, buffer
);
263 msg
.list
.flags
= list_flags
[kw
- STROKE_LIST_FIRST
];
264 return send_stroke_msg(&msg
);
267 static int reread_flags
[] = {
277 static int reread(stroke_keyword_t kw
)
281 msg
.type
= STR_REREAD
;
282 msg
.length
= offsetof(stroke_msg_t
, buffer
);
283 msg
.reread
.flags
= reread_flags
[kw
- STROKE_REREAD_FIRST
];
284 return send_stroke_msg(&msg
);
287 static int purge_flags
[] = {
294 static int purge(stroke_keyword_t kw
)
298 msg
.type
= STR_PURGE
;
299 msg
.length
= offsetof(stroke_msg_t
, buffer
);
300 msg
.purge
.flags
= purge_flags
[kw
- STROKE_PURGE_FIRST
];
301 return send_stroke_msg(&msg
);
304 static int export_flags
[] = {
310 static int export(stroke_keyword_t kw
, char *selector
)
314 msg
.type
= STR_EXPORT
;
315 msg
.length
= offsetof(stroke_msg_t
, buffer
);
316 msg
.export
.selector
= push_string(&msg
, selector
);
317 msg
.export
.flags
= export_flags
[kw
- STROKE_EXPORT_FIRST
];
318 return send_stroke_msg(&msg
);
321 static int leases(stroke_keyword_t kw
, char *pool
, char *address
)
325 msg
.type
= STR_LEASES
;
326 msg
.length
= offsetof(stroke_msg_t
, buffer
);
327 msg
.leases
.pool
= push_string(&msg
, pool
);
328 msg
.leases
.address
= push_string(&msg
, address
);
329 return send_stroke_msg(&msg
);
332 static int memusage()
336 msg
.type
= STR_MEMUSAGE
;
337 msg
.length
= offsetof(stroke_msg_t
, buffer
);
338 return send_stroke_msg(&msg
);
341 static int user_credentials(char *name
, char *user
, char *pass
)
345 msg
.type
= STR_USER_CREDS
;
346 msg
.length
= offsetof(stroke_msg_t
, buffer
);
347 msg
.user_creds
.name
= push_string(&msg
, name
);
348 msg
.user_creds
.username
= push_string(&msg
, user
);
349 msg
.user_creds
.password
= push_string(&msg
, pass
);
350 return send_stroke_msg(&msg
);
353 static int counters(int reset
, char *name
)
357 msg
.type
= STR_COUNTERS
;
358 msg
.length
= offsetof(stroke_msg_t
, buffer
);
359 msg
.counters
.name
= push_string(&msg
, name
);
360 msg
.counters
.reset
= reset
;
362 return send_stroke_msg(&msg
);
365 static int set_loglevel(char *type
, u_int level
)
369 msg
.type
= STR_LOGLEVEL
;
370 msg
.length
= offsetof(stroke_msg_t
, buffer
);
371 msg
.loglevel
.type
= push_string(&msg
, type
);
372 msg
.loglevel
.level
= level
;
373 return send_stroke_msg(&msg
);
376 static void exit_error(char *error
)
380 fprintf(stderr
, "%s\n", error
);
385 static void exit_usage(char *error
)
388 printf(" Add a connection:\n");
389 printf(" stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n");
390 printf(" MY_NET OTHER_NET\n");
391 printf(" where: ID is any IKEv2 ID \n");
392 printf(" ADDR is a IPv4 address\n");
393 printf(" NET is a IPv4 subnet in CIDR notation\n");
394 printf(" Delete a connection:\n");
395 printf(" stroke delete NAME\n");
396 printf(" where: NAME is a connection name added with \"stroke add\"\n");
397 printf(" Initiate a connection:\n");
398 printf(" stroke up NAME\n");
399 printf(" where: NAME is a connection name added with \"stroke add\"\n");
400 printf(" Initiate a connection without blocking:\n");
401 printf(" stroke up-nb NAME\n");
402 printf(" where: NAME is a connection name added with \"stroke add\"\n");
403 printf(" Terminate a connection:\n");
404 printf(" stroke down NAME\n");
405 printf(" where: NAME is a connection name added with \"stroke add\"\n");
406 printf(" Terminate a connection without blocking:\n");
407 printf(" stroke down-nb NAME\n");
408 printf(" where: NAME is a connection name added with \"stroke add\"\n");
409 printf(" Terminate a connection by remote srcip:\n");
410 printf(" stroke down-srcip START [END]\n");
411 printf(" where: START and optional END define the clients source IP\n");
412 printf(" Set loglevel for a logging type:\n");
413 printf(" stroke loglevel TYPE LEVEL\n");
414 printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n");
415 printf(" LEVEL is -1|0|1|2|3|4\n");
416 printf(" Show connection status:\n");
417 printf(" stroke status\n");
418 printf(" Show extended status information:\n");
419 printf(" stroke statusall\n");
420 printf(" Show extended status information without blocking:\n");
421 printf(" stroke statusall-nb\n");
422 printf(" Show list of authority and attribute certificates:\n");
423 printf(" stroke listcacerts|listocspcerts|listaacerts|listacerts\n");
424 printf(" Show list of end entity certificates, ca info records and crls:\n");
425 printf(" stroke listcerts|listcainfos|listcrls|listall\n");
426 printf(" Show list of supported algorithms:\n");
427 printf(" stroke listalgs\n");
428 printf(" Reload authority and attribute certificates:\n");
429 printf(" stroke rereadcacerts|rereadocspcerts|rereadaacerts|rereadacerts\n");
430 printf(" Reload secrets and crls:\n");
431 printf(" stroke rereadsecrets|rereadcrls|rereadall\n");
432 printf(" Purge ocsp cache entries:\n");
433 printf(" stroke purgeocsp\n");
434 printf(" Purge CRL cache entries:\n");
435 printf(" stroke purgecrls\n");
436 printf(" Purge X509 cache entries:\n");
437 printf(" stroke purgecerts\n");
438 printf(" Purge IKE_SAs without a CHILD_SA:\n");
439 printf(" stroke purgeike\n");
440 printf(" Export credentials to the console:\n");
441 printf(" stroke exportx509 DN\n");
442 printf(" stroke exportconncert connname\n");
443 printf(" stroke exportconnchain connname\n");
444 printf(" Show current memory usage:\n");
445 printf(" stroke memusage\n");
446 printf(" Show leases of a pool:\n");
447 printf(" stroke leases [POOL [ADDRESS]]\n");
448 printf(" Set username and password for a connection:\n");
449 printf(" stroke user-creds NAME USERNAME [PASSWORD]\n");
450 printf(" where: NAME is a connection name added with \"stroke add\"\n");
451 printf(" USERNAME is the username\n");
452 printf(" PASSWORD is the optional password, you'll be asked to enter it if not given\n");
453 printf(" Show IKE counters:\n");
454 printf(" stroke listcounters [connection-name]\n");
458 int main(int argc
, char *argv
[])
460 const stroke_token_t
*token
;
463 library_init(NULL
, "stroke");
464 atexit(library_deinit
);
471 token
= in_word_set(argv
[1], strlen(argv
[1]));
475 exit_usage("unknown keyword");
483 exit_usage("\"add\" needs more parameters...");
485 res
= add_connection(argv
[2],
494 exit_usage("\"delete\" needs a connection name");
496 res
= del_connection(argv
[2]);
498 case STROKE_UP_NOBLK
:
499 output_verbosity
= -1;
504 exit_usage("\"up\" needs a connection name");
506 res
= initiate_connection(argv
[2]);
508 case STROKE_DOWN_NOBLK
:
509 output_verbosity
= -1;
514 exit_usage("\"down\" needs a connection name");
516 res
= terminate_connection(argv
[2]);
518 case STROKE_DOWN_SRCIP
:
521 exit_usage("\"down-srcip\" needs start and optional end address");
523 res
= terminate_connection_srcip(argv
[2], argc
> 3 ? argv
[3] : NULL
);
528 exit_usage("\"rekey\" needs a connection name");
530 res
= rekey_connection(argv
[2]);
535 exit_usage("\"route\" needs a connection name");
537 res
= route_connection(argv
[2]);
542 exit_usage("\"unroute\" needs a connection name");
544 res
= unroute_connection(argv
[2]);
546 case STROKE_LOGLEVEL
:
549 exit_usage("\"logtype\" needs more parameters...");
551 res
= set_loglevel(argv
[2], atoi(argv
[3]));
554 case STROKE_STATUSALL
:
555 case STROKE_STATUSALL_NOBLK
:
556 res
= show_status(token
->kw
, argc
> 2 ? argv
[2] : NULL
);
558 case STROKE_LIST_PUBKEYS
:
559 case STROKE_LIST_CERTS
:
560 case STROKE_LIST_CACERTS
:
561 case STROKE_LIST_OCSPCERTS
:
562 case STROKE_LIST_AACERTS
:
563 case STROKE_LIST_ACERTS
:
564 case STROKE_LIST_CAINFOS
:
565 case STROKE_LIST_CRLS
:
566 case STROKE_LIST_OCSP
:
567 case STROKE_LIST_ALGS
:
568 case STROKE_LIST_PLUGINS
:
569 case STROKE_LIST_ALL
:
570 res
= list(token
->kw
, argc
> 2 && streq(argv
[2], "--utc"));
572 case STROKE_REREAD_SECRETS
:
573 case STROKE_REREAD_CACERTS
:
574 case STROKE_REREAD_OCSPCERTS
:
575 case STROKE_REREAD_AACERTS
:
576 case STROKE_REREAD_ACERTS
:
577 case STROKE_REREAD_CRLS
:
578 case STROKE_REREAD_ALL
:
579 res
= reread(token
->kw
);
581 case STROKE_PURGE_OCSP
:
582 case STROKE_PURGE_CRLS
:
583 case STROKE_PURGE_CERTS
:
584 case STROKE_PURGE_IKE
:
585 res
= purge(token
->kw
);
587 case STROKE_EXPORT_X509
:
588 case STROKE_EXPORT_CONN_CERT
:
589 case STROKE_EXPORT_CONN_CHAIN
:
592 exit_usage("\"export\" needs a name");
594 res
= export(token
->kw
, argv
[2]);
597 res
= leases(token
->kw
, argc
> 2 ? argv
[2] : NULL
,
598 argc
> 3 ? argv
[3] : NULL
);
600 case STROKE_MEMUSAGE
:
603 case STROKE_USER_CREDS
:
606 exit_usage("\"user-creds\" needs a connection name, "
607 "username and optionally a password");
609 res
= user_credentials(argv
[2], argv
[3], argc
> 4 ? argv
[4] : NULL
);
611 case STROKE_COUNTERS
:
612 case STROKE_COUNTERS_RESET
:
613 res
= counters(token
->kw
== STROKE_COUNTERS_RESET
,
614 argc
> 2 ? argv
[2] : NULL
);