2d2ebe838ab5c59384932e9d994d95854d1c26e4
1 /* Stroke for charon is the counterpart to whack from pluto
2 * Copyright (C) 2007 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
18 #include <sys/types.h>
20 #include <sys/socket.h>
31 #include "stroke_msg.h"
32 #include "stroke_keywords.h"
39 static char* push_string(stroke_msg_t
*msg
, char *string
)
41 unsigned long string_start
= msg
->length
;
43 if (string
== NULL
|| msg
->length
+ strlen(string
) >= sizeof(stroke_msg_t
))
49 msg
->length
+= strlen(string
) + 1;
50 strcpy((char*)msg
+ string_start
, string
);
51 return (char*)string_start
;
55 static int send_stroke_msg (stroke_msg_t
*msg
)
57 struct sockaddr_un ctl_addr
;
59 char buffer
[512], *pass
;
61 ctl_addr
.sun_family
= AF_UNIX
;
62 strcpy(ctl_addr
.sun_path
, STROKE_SOCKET
);
64 msg
->output_verbosity
= 1; /* CONTROL */
66 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
69 fprintf(stderr
, "Opening unix socket %s: %s\n", STROKE_SOCKET
, strerror(errno
));
72 if (connect(sock
, (struct sockaddr
*)&ctl_addr
,
73 offsetof(struct sockaddr_un
, sun_path
) + strlen(ctl_addr
.sun_path
)) < 0)
75 fprintf(stderr
, "Connect to socket failed: %s\n", strerror(errno
));
81 if (write(sock
, msg
, msg
->length
) != msg
->length
)
83 fprintf(stderr
, "writing to socket failed: %s\n", strerror(errno
));
88 while ((byte_count
= read(sock
, buffer
, sizeof(buffer
)-1)) > 0)
90 buffer
[byte_count
] = '\0';
92 /* we prompt if we receive the "Passphrase:"/"PIN:" magic keyword */
93 if ((byte_count
>= 12 &&
94 strcmp(buffer
+ byte_count
- 12, "Passphrase:\n") == 0) ||
96 strcmp(buffer
+ byte_count
- 5, "PIN:\n") == 0))
98 /* remove trailing newline */
99 pass
= strrchr(buffer
, '\n');
104 pass
= getpass(buffer
);
107 ignore_result(write(sock
, pass
, strlen(pass
)));
108 ignore_result(write(sock
, "\n", 1));
113 printf("%s", buffer
);
118 fprintf(stderr
, "reading from socket failed: %s\n", strerror(errno
));
125 static int add_connection(char *name
,
126 char *my_id
, char *other_id
,
127 char *my_addr
, char *other_addr
,
128 char *my_nets
, char *other_nets
)
132 memset(&msg
, 0, sizeof(msg
));
133 msg
.length
= offsetof(stroke_msg_t
, buffer
);
134 msg
.type
= STR_ADD_CONN
;
136 msg
.add_conn
.name
= push_string(&msg
, name
);
137 msg
.add_conn
.ikev2
= 1;
138 msg
.add_conn
.auth_method
= 2;
139 msg
.add_conn
.mode
= 1;
140 msg
.add_conn
.mobike
= 1;
141 msg
.add_conn
.dpd
.action
= 1;
143 msg
.add_conn
.me
.id
= push_string(&msg
, my_id
);
144 msg
.add_conn
.me
.address
= push_string(&msg
, my_addr
);
145 msg
.add_conn
.me
.ikeport
= 500;
146 msg
.add_conn
.me
.subnets
= push_string(&msg
, my_nets
);
147 msg
.add_conn
.me
.sendcert
= 1;
149 msg
.add_conn
.other
.id
= push_string(&msg
, other_id
);
150 msg
.add_conn
.other
.address
= push_string(&msg
, other_addr
);
151 msg
.add_conn
.other
.ikeport
= 500;
152 msg
.add_conn
.other
.subnets
= push_string(&msg
, other_nets
);
153 msg
.add_conn
.other
.sendcert
= 1;
155 return send_stroke_msg(&msg
);
158 static int del_connection(char *name
)
162 msg
.length
= offsetof(stroke_msg_t
, buffer
);
163 msg
.type
= STR_DEL_CONN
;
164 msg
.initiate
.name
= push_string(&msg
, name
);
165 return send_stroke_msg(&msg
);
168 static int initiate_connection(char *name
)
172 msg
.length
= offsetof(stroke_msg_t
, buffer
);
173 msg
.type
= STR_INITIATE
;
174 msg
.initiate
.name
= push_string(&msg
, name
);
175 return send_stroke_msg(&msg
);
178 static int terminate_connection(char *name
)
182 msg
.type
= STR_TERMINATE
;
183 msg
.length
= offsetof(stroke_msg_t
, buffer
);
184 msg
.initiate
.name
= push_string(&msg
, name
);
185 return send_stroke_msg(&msg
);
188 static int terminate_connection_srcip(char *start
, char *end
)
192 msg
.type
= STR_TERMINATE_SRCIP
;
193 msg
.length
= offsetof(stroke_msg_t
, buffer
);
194 msg
.terminate_srcip
.start
= push_string(&msg
, start
);
195 msg
.terminate_srcip
.end
= push_string(&msg
, end
);
196 return send_stroke_msg(&msg
);
199 static int rekey_connection(char *name
)
203 msg
.type
= STR_REKEY
;
204 msg
.length
= offsetof(stroke_msg_t
, buffer
);
205 msg
.rekey
.name
= push_string(&msg
, name
);
206 return send_stroke_msg(&msg
);
209 static int route_connection(char *name
)
213 msg
.type
= STR_ROUTE
;
214 msg
.length
= offsetof(stroke_msg_t
, buffer
);
215 msg
.route
.name
= push_string(&msg
, name
);
216 return send_stroke_msg(&msg
);
219 static int unroute_connection(char *name
)
223 msg
.type
= STR_UNROUTE
;
224 msg
.length
= offsetof(stroke_msg_t
, buffer
);
225 msg
.unroute
.name
= push_string(&msg
, name
);
226 return send_stroke_msg(&msg
);
229 static int show_status(stroke_keyword_t kw
, char *connection
)
235 case STROKE_STATUSALL
:
236 msg
.type
= STR_STATUS_ALL
;
238 case STROKE_STATUSALL_NOBLK
:
239 msg
.type
= STR_STATUS_ALL_NOBLK
;
242 msg
.type
= STR_STATUS
;
245 msg
.length
= offsetof(stroke_msg_t
, buffer
);
246 msg
.status
.name
= push_string(&msg
, connection
);
247 return send_stroke_msg(&msg
);
250 static int list_flags
[] = {
265 static int list(stroke_keyword_t kw
, int utc
)
270 msg
.length
= offsetof(stroke_msg_t
, buffer
);
272 msg
.list
.flags
= list_flags
[kw
- STROKE_LIST_FIRST
];
273 return send_stroke_msg(&msg
);
276 static int reread_flags
[] = {
286 static int reread(stroke_keyword_t kw
)
290 msg
.type
= STR_REREAD
;
291 msg
.length
= offsetof(stroke_msg_t
, buffer
);
292 msg
.reread
.flags
= reread_flags
[kw
- STROKE_REREAD_FIRST
];
293 return send_stroke_msg(&msg
);
296 static int purge_flags
[] = {
303 static int purge(stroke_keyword_t kw
)
307 msg
.type
= STR_PURGE
;
308 msg
.length
= offsetof(stroke_msg_t
, buffer
);
309 msg
.purge
.flags
= purge_flags
[kw
- STROKE_PURGE_FIRST
];
310 return send_stroke_msg(&msg
);
313 static int export_flags
[] = {
317 static int export(stroke_keyword_t kw
, char *selector
)
321 msg
.type
= STR_EXPORT
;
322 msg
.length
= offsetof(stroke_msg_t
, buffer
);
323 msg
.export
.selector
= push_string(&msg
, selector
);
324 msg
.export
.flags
= export_flags
[kw
- STROKE_EXPORT_FIRST
];
325 return send_stroke_msg(&msg
);
328 static int leases(stroke_keyword_t kw
, char *pool
, char *address
)
332 msg
.type
= STR_LEASES
;
333 msg
.length
= offsetof(stroke_msg_t
, buffer
);
334 msg
.leases
.pool
= push_string(&msg
, pool
);
335 msg
.leases
.address
= push_string(&msg
, address
);
336 return send_stroke_msg(&msg
);
339 static int memusage()
343 msg
.type
= STR_MEMUSAGE
;
344 msg
.length
= offsetof(stroke_msg_t
, buffer
);
345 return send_stroke_msg(&msg
);
348 static int set_loglevel(char *type
, u_int level
)
352 msg
.type
= STR_LOGLEVEL
;
353 msg
.length
= offsetof(stroke_msg_t
, buffer
);
354 msg
.loglevel
.type
= push_string(&msg
, type
);
355 msg
.loglevel
.level
= level
;
356 return send_stroke_msg(&msg
);
359 static void exit_error(char *error
)
363 fprintf(stderr
, "%s\n", error
);
368 static void exit_usage(char *error
)
371 printf(" Add a connection:\n");
372 printf(" stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n");
373 printf(" MY_NET OTHER_NET MY_NETBITS OTHER_NETBITS\n");
374 printf(" where: ID is any IKEv2 ID \n");
375 printf(" ADDR is a IPv4 address\n");
376 printf(" NET is a IPv4 subnet in CIDR notation\n");
377 printf(" Delete a connection:\n");
378 printf(" stroke delete NAME\n");
379 printf(" where: NAME is a connection name added with \"stroke add\"\n");
380 printf(" Initiate a connection:\n");
381 printf(" stroke up NAME\n");
382 printf(" where: NAME is a connection name added with \"stroke add\"\n");
383 printf(" Terminate a connection:\n");
384 printf(" stroke down NAME\n");
385 printf(" where: NAME is a connection name added with \"stroke add\"\n");
386 printf(" Terminate a connection by remote srcip:\n");
387 printf(" stroke down-srcip START [END]\n");
388 printf(" where: START and optional END define the clients source IP\n");
389 printf(" Set loglevel for a logging type:\n");
390 printf(" stroke loglevel TYPE LEVEL\n");
391 printf(" where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|enc|tnc|imc|imv|pts|tls|lib\n");
392 printf(" LEVEL is -1|0|1|2|3|4\n");
393 printf(" Show connection status:\n");
394 printf(" stroke status\n");
395 printf(" Show extended status information:\n");
396 printf(" stroke statusall\n");
397 printf(" Show extended status information without blocking:\n");
398 printf(" stroke statusallnb\n");
399 printf(" Show list of authority and attribute certificates:\n");
400 printf(" stroke listcacerts|listocspcerts|listaacerts|listacerts\n");
401 printf(" Show list of end entity certificates, ca info records and crls:\n");
402 printf(" stroke listcerts|listcainfos|listcrls|listall\n");
403 printf(" Show list of supported algorithms:\n");
404 printf(" stroke listalgs\n");
405 printf(" Reload authority and attribute certificates:\n");
406 printf(" stroke rereadcacerts|rereadocspcerts|rereadaacerts|rereadacerts\n");
407 printf(" Reload secrets and crls:\n");
408 printf(" stroke rereadsecrets|rereadcrls|rereadall\n");
409 printf(" Purge ocsp cache entries:\n");
410 printf(" stroke purgeocsp\n");
411 printf(" Purge CRL cache entries:\n");
412 printf(" stroke purgecrls\n");
413 printf(" Purge X509 cache entries:\n");
414 printf(" stroke purgecerts\n");
415 printf(" Purge IKE_SAs without a CHILD_SA:\n");
416 printf(" stroke purgeike\n");
417 printf(" Export credentials to the console:\n");
418 printf(" stroke exportx509 DN\n");
419 printf(" Show current memory usage:\n");
420 printf(" stroke memusage\n");
421 printf(" Show leases of a pool:\n");
422 printf(" stroke leases [POOL [ADDRESS]]\n");
426 int main(int argc
, char *argv
[])
428 const stroke_token_t
*token
;
432 atexit(library_deinit
);
439 token
= in_word_set(argv
[1], strlen(argv
[1]));
443 exit_usage("unknown keyword");
451 exit_usage("\"add\" needs more parameters...");
453 res
= add_connection(argv
[2],
462 exit_usage("\"delete\" needs a connection name");
464 res
= del_connection(argv
[2]);
469 exit_usage("\"up\" needs a connection name");
471 res
= initiate_connection(argv
[2]);
476 exit_usage("\"down\" needs a connection name");
478 res
= terminate_connection(argv
[2]);
480 case STROKE_DOWN_SRCIP
:
483 exit_usage("\"down-srcip\" needs start and optional end address");
485 res
= terminate_connection_srcip(argv
[2], argc
> 3 ? argv
[3] : NULL
);
490 exit_usage("\"rekey\" needs a connection name");
492 res
= rekey_connection(argv
[2]);
497 exit_usage("\"route\" needs a connection name");
499 res
= route_connection(argv
[2]);
504 exit_usage("\"unroute\" needs a connection name");
506 res
= unroute_connection(argv
[2]);
508 case STROKE_LOGLEVEL
:
511 exit_usage("\"logtype\" needs more parameters...");
513 res
= set_loglevel(argv
[2], atoi(argv
[3]));
516 case STROKE_STATUSALL
:
517 case STROKE_STATUSALL_NOBLK
:
518 res
= show_status(token
->kw
, argc
> 2 ? argv
[2] : NULL
);
520 case STROKE_LIST_PUBKEYS
:
521 case STROKE_LIST_CERTS
:
522 case STROKE_LIST_CACERTS
:
523 case STROKE_LIST_OCSPCERTS
:
524 case STROKE_LIST_AACERTS
:
525 case STROKE_LIST_ACERTS
:
526 case STROKE_LIST_CAINFOS
:
527 case STROKE_LIST_CRLS
:
528 case STROKE_LIST_OCSP
:
529 case STROKE_LIST_ALGS
:
530 case STROKE_LIST_ALL
:
531 res
= list(token
->kw
, argc
> 2 && strcmp(argv
[2], "--utc") == 0);
533 case STROKE_REREAD_SECRETS
:
534 case STROKE_REREAD_CACERTS
:
535 case STROKE_REREAD_OCSPCERTS
:
536 case STROKE_REREAD_AACERTS
:
537 case STROKE_REREAD_ACERTS
:
538 case STROKE_REREAD_CRLS
:
539 case STROKE_REREAD_ALL
:
540 res
= reread(token
->kw
);
542 case STROKE_PURGE_OCSP
:
543 case STROKE_PURGE_CRLS
:
544 case STROKE_PURGE_CERTS
:
545 case STROKE_PURGE_IKE
:
546 res
= purge(token
->kw
);
548 case STROKE_EXPORT_X509
:
551 exit_usage("\"exportx509\" needs a distinguished name");
553 res
= export(token
->kw
, argv
[2]);
556 res
= leases(token
->kw
, argc
> 2 ? argv
[2] : NULL
,
557 argc
> 3 ? argv
[3] : NULL
);
559 case STROKE_MEMUSAGE
: