split connections with different virtual IPs in different peer_cfgs
[strongswan.git] / src / charon / control / interfaces / stroke_interface.c
1 /**
2 * @file stroke_interface.c
3 *
4 * @brief Implementation of stroke_interface_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Tobias Brunner
10 * Copyright (C) 2006-2007 Martin Willi
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <sys/fcntl.h>
30 #include <unistd.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <pthread.h>
34 #include <signal.h>
35
36 #include "stroke_interface.h"
37
38 #include <library.h>
39 #include <stroke.h>
40 #include <daemon.h>
41 #include <crypto/x509.h>
42 #include <crypto/ietf_attr_list.h>
43 #include <crypto/ac.h>
44 #include <crypto/ca.h>
45 #include <crypto/crl.h>
46 #include <control/interface_manager.h>
47 #include <control/interfaces/interface.h>
48 #include <utils/leak_detective.h>
49 #include <processing/jobs/callback_job.h>
50
51 #define IKE_PORT 500
52 #define PATH_BUF 256
53 #define STROKE_THREADS 3
54
55 typedef struct private_stroke_interface_t private_stroke_interface_t;
56
57 /**
58 * Private data of an stroke_interfacet object.
59 */
60 struct private_stroke_interface_t {
61
62 /**
63 * Public part of stroke_interfacet object.
64 */
65 stroke_interface_t public;
66
67 /**
68 * Unix socket to listen for strokes
69 */
70 int socket;
71
72 /**
73 * job accepting stroke messages
74 */
75 callback_job_t *job;
76 };
77
78 typedef struct stroke_log_info_t stroke_log_info_t;
79
80 /**
81 * helper struct to say what and where to log when using controller callback
82 */
83 struct stroke_log_info_t {
84
85 /**
86 * level to log up to
87 */
88 level_t level;
89
90 /**
91 * where to write log
92 */
93 FILE* out;
94 };
95
96 /**
97 * Helper function which corrects the string pointers
98 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
99 * contains RELATIVE addresses (relative to the beginning of the
100 * stroke_msg). They must be corrected if they reach our address
101 * space...
102 */
103 static void pop_string(stroke_msg_t *msg, char **string)
104 {
105 if (*string == NULL)
106 return;
107
108 /* check for sanity of string pointer and string */
109 if (string < (char**)msg
110 || string > (char**)msg + sizeof(stroke_msg_t)
111 || (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg)
112 || (unsigned long)*string > msg->length)
113 {
114 *string = "(invalid pointer in stroke msg)";
115 }
116 else
117 {
118 *string = (char*)msg + (unsigned long)*string;
119 }
120 }
121
122 /**
123 * Load end entitity certificate
124 */
125 static x509_t* load_end_certificate(const char *filename, identification_t **idp)
126 {
127 char path[PATH_BUF];
128 x509_t *cert;
129
130 if (*filename == '/')
131 {
132 /* absolute path name */
133 snprintf(path, sizeof(path), "%s", filename);
134 }
135 else
136 {
137 /* relative path name */
138 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
139 }
140
141 cert = x509_create_from_file(path, "end entity");
142
143 if (cert)
144 {
145 identification_t *id = *idp;
146 identification_t *subject = cert->get_subject(cert);
147
148 err_t ugh = cert->is_valid(cert, NULL);
149
150 if (ugh != NULL)
151 {
152 DBG1(DBG_CFG, "warning: certificate %s", ugh);
153 }
154 if (!id->equals(id, subject) && !cert->equals_subjectAltName(cert, id))
155 {
156 id->destroy(id);
157 id = subject;
158 *idp = id->clone(id);
159 }
160 return charon->credentials->add_end_certificate(charon->credentials, cert);
161 }
162 return NULL;
163 }
164
165 /**
166 * Load ca certificate
167 */
168 static x509_t* load_ca_certificate(const char *filename)
169 {
170 char path[PATH_BUF];
171 x509_t *cert;
172
173 if (*filename == '/')
174 {
175 /* absolute path name */
176 snprintf(path, sizeof(path), "%s", filename);
177 }
178 else
179 {
180 /* relative path name */
181 snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
182 }
183
184 cert = x509_create_from_file(path, "ca");
185
186 if (cert)
187 {
188 if (cert->is_ca(cert))
189 {
190 return charon->credentials->add_auth_certificate(charon->credentials, cert, AUTH_CA);
191 }
192 else
193 {
194 DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded");
195 cert->destroy(cert);
196 }
197 }
198 return NULL;
199 }
200
201 /**
202 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
203 */
204 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
205 {
206 pop_string(msg, &end->address);
207 pop_string(msg, &end->subnet);
208 pop_string(msg, &end->sourceip);
209 pop_string(msg, &end->id);
210 pop_string(msg, &end->cert);
211 pop_string(msg, &end->ca);
212 pop_string(msg, &end->groups);
213 pop_string(msg, &end->updown);
214
215 DBG2(DBG_CFG, " %s=%s", label, end->address);
216 DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnet);
217 DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
218 DBG2(DBG_CFG, " %sid=%s", label, end->id);
219 DBG2(DBG_CFG, " %scert=%s", label, end->cert);
220 DBG2(DBG_CFG, " %sca=%s", label, end->ca);
221 DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
222 DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
223 }
224
225 /**
226 * Add a connection to the configuration list
227 */
228 static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
229 {
230 ike_cfg_t *ike_cfg;
231 peer_cfg_t *peer_cfg;
232 peer_cfg_t *mediated_by_cfg = NULL;
233 child_cfg_t *child_cfg;
234 identification_t *my_id, *other_id;
235 identification_t *my_ca = NULL;
236 identification_t *other_ca = NULL;
237 identification_t *peer_id = NULL;
238 bool my_ca_same = FALSE;
239 bool other_ca_same =FALSE;
240 host_t *my_host, *other_host, *my_subnet, *other_subnet;
241 host_t *my_vip = NULL, *other_vip = NULL;
242 linked_list_t *other_groups = linked_list_create();
243 proposal_t *proposal;
244 traffic_selector_t *my_ts, *other_ts;
245 char *interface;
246 bool use_existing = FALSE;
247 iterator_t *iterator;
248 u_int32_t vendor;
249
250 pop_string(msg, &msg->add_conn.name);
251 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
252 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
253 pop_end(msg, "left", &msg->add_conn.me);
254 pop_end(msg, "right", &msg->add_conn.other);
255 pop_string(msg, &msg->add_conn.algorithms.ike);
256 pop_string(msg, &msg->add_conn.algorithms.esp);
257 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
258 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
259 pop_string(msg, &msg->add_conn.p2p.mediated_by);
260 pop_string(msg, &msg->add_conn.p2p.peerid);
261 DBG2(DBG_CFG, " p2p_mediation=%s", msg->add_conn.p2p.mediation ? "yes" : "no");
262 DBG2(DBG_CFG, " p2p_mediated_by=%s", msg->add_conn.p2p.mediated_by);
263 DBG2(DBG_CFG, " p2p_peerid=%s", msg->add_conn.p2p.peerid);
264
265 my_host = msg->add_conn.me.address ?
266 host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL;
267 if (my_host == NULL)
268 {
269 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.me.address);
270 return;
271 }
272
273 other_host = msg->add_conn.other.address ?
274 host_create_from_string(msg->add_conn.other.address, IKE_PORT) : NULL;
275 if (other_host == NULL)
276 {
277 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.other.address);
278 my_host->destroy(my_host);
279 return;
280 }
281
282 interface = charon->kernel_interface->get_interface(charon->kernel_interface,
283 other_host);
284 if (interface)
285 {
286 stroke_end_t tmp_end;
287 host_t *tmp_host;
288
289 DBG2(DBG_CFG, "left is other host, swapping ends\n");
290
291 tmp_host = my_host;
292 my_host = other_host;
293 other_host = tmp_host;
294
295 tmp_end = msg->add_conn.me;
296 msg->add_conn.me = msg->add_conn.other;
297 msg->add_conn.other = tmp_end;
298 free(interface);
299 }
300 else
301 {
302 interface = charon->kernel_interface->get_interface(
303 charon->kernel_interface, my_host);
304 if (!interface)
305 {
306 DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
307 }
308 else
309 {
310 free(interface);
311 }
312 }
313
314 my_id = identification_create_from_string(msg->add_conn.me.id ?
315 msg->add_conn.me.id : msg->add_conn.me.address);
316 if (my_id == NULL)
317 {
318 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
319 goto destroy_hosts;
320 }
321
322 other_id = identification_create_from_string(msg->add_conn.other.id ?
323 msg->add_conn.other.id : msg->add_conn.other.address);
324 if (other_id == NULL)
325 {
326 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
327 my_id->destroy(my_id);
328 goto destroy_hosts;
329 }
330
331 #ifdef P2P
332 if (msg->add_conn.p2p.mediation && msg->add_conn.p2p.mediated_by)
333 {
334 DBG1(DBG_CFG, "a mediation connection cannot be a"
335 " mediated connection at the same time, aborting");
336 goto destroy_ids;
337 }
338
339 if (msg->add_conn.p2p.mediated_by)
340 {
341 mediated_by_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, msg->add_conn.p2p.mediated_by);
342 if (!mediated_by_cfg)
343 {
344 DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
345 msg->add_conn.p2p.mediated_by);
346 goto destroy_ids;
347 }
348
349 if (!mediated_by_cfg->is_mediation(mediated_by_cfg))
350 {
351 DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is"
352 "no mediation connection, aborting",
353 msg->add_conn.p2p.mediated_by, msg->add_conn.name);
354 goto destroy_ids;
355 }
356 }
357
358 if (msg->add_conn.p2p.peerid)
359 {
360 peer_id = identification_create_from_string(msg->add_conn.p2p.peerid);
361 if (!peer_id)
362 {
363 DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.p2p.peerid);
364 goto destroy_ids;
365 }
366 }
367 else
368 {
369 /* no peer ID supplied, assume right ID */
370 peer_id = other_id->clone(other_id);
371 }
372 #endif /* P2P */
373
374 my_subnet = host_create_from_string(msg->add_conn.me.subnet ?
375 msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT);
376 if (my_subnet == NULL)
377 {
378 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
379 goto destroy_ids;
380 }
381
382 other_subnet = host_create_from_string(msg->add_conn.other.subnet ?
383 msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT);
384 if (other_subnet == NULL)
385 {
386 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
387 my_subnet->destroy(my_subnet);
388 goto destroy_ids;
389 }
390
391 if (msg->add_conn.me.virtual_ip && msg->add_conn.me.sourceip)
392 {
393 my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
394 }
395 if (msg->add_conn.other.virtual_ip && msg->add_conn.other.sourceip)
396 {
397 other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
398 }
399
400 if (msg->add_conn.me.tohost)
401 {
402 my_ts = traffic_selector_create_dynamic(msg->add_conn.me.protocol,
403 my_host->get_family(my_host) == AF_INET ?
404 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
405 msg->add_conn.me.port ? msg->add_conn.me.port : 0,
406 msg->add_conn.me.port ? msg->add_conn.me.port : 65535);
407 }
408 else
409 {
410 my_ts = traffic_selector_create_from_subnet(my_subnet,
411 msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0,
412 msg->add_conn.me.protocol, msg->add_conn.me.port);
413 }
414 my_subnet->destroy(my_subnet);
415
416 if (msg->add_conn.other.tohost)
417 {
418 other_ts = traffic_selector_create_dynamic(msg->add_conn.other.protocol,
419 other_host->get_family(other_host) == AF_INET ?
420 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
421 msg->add_conn.other.port ? msg->add_conn.other.port : 0,
422 msg->add_conn.other.port ? msg->add_conn.other.port : 65535);
423 }
424 else
425 {
426 other_ts = traffic_selector_create_from_subnet(other_subnet,
427 msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0,
428 msg->add_conn.other.protocol, msg->add_conn.other.port);
429 }
430 other_subnet->destroy(other_subnet);
431
432 if (msg->add_conn.me.ca)
433 {
434 if (streq(msg->add_conn.me.ca, "%same"))
435 {
436 my_ca_same = TRUE;
437 }
438 else
439 {
440 my_ca = identification_create_from_string(msg->add_conn.me.ca);
441 }
442 }
443 if (msg->add_conn.other.ca)
444 {
445 if (streq(msg->add_conn.other.ca, "%same"))
446 {
447 other_ca_same = TRUE;
448 }
449 else
450 {
451 other_ca = identification_create_from_string(msg->add_conn.other.ca);
452 }
453 }
454 if (msg->add_conn.me.cert)
455 {
456 x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id);
457
458 if (cert)
459 {
460 ca_info_t *ca_info;
461
462 if (cert->is_self_signed(cert))
463 {
464 /* a self-signed certificate is its own ca */
465 ca_info = ca_info_create(NULL, cert);
466 ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info);
467 cert->set_ca_info(cert, ca_info);
468 }
469 else
470 {
471 /* get_issuer() automatically sets cert->ca_info */
472 ca_info = charon->credentials->get_issuer(charon->credentials, cert);
473 }
474 if (my_ca == NULL && !my_ca_same)
475 {
476 identification_t *issuer = cert->get_issuer(cert);
477
478 my_ca = issuer->clone(issuer);
479 }
480 }
481 }
482 if (msg->add_conn.other.cert)
483 {
484 x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id);
485
486 if (cert)
487 {
488 ca_info_t *ca_info;
489
490 if (cert->is_self_signed(cert))
491 {
492 /* a self-signed certificate is its own ca */
493 ca_info = ca_info_create(NULL, cert);
494 ca_info = charon->credentials->add_ca_info(charon->credentials, ca_info);
495 cert->set_ca_info(cert, ca_info);
496 }
497 else
498 {
499 /* get_issuer() automatically sets cert->ca_info */
500 ca_info = charon->credentials->get_issuer(charon->credentials, cert);
501 }
502 if (other_ca == NULL && !other_ca_same)
503 {
504 identification_t *issuer = cert->get_issuer(cert);
505
506 other_ca = issuer->clone(issuer);
507 }
508 }
509 }
510 if (other_ca_same && my_ca)
511 {
512 other_ca = my_ca->clone(my_ca);
513 }
514 else if (my_ca_same && other_ca)
515 {
516 my_ca = other_ca->clone(other_ca);
517 }
518 if (my_ca == NULL)
519 {
520 my_ca = identification_create_from_string("%any");
521 }
522 if (other_ca == NULL)
523 {
524 other_ca = identification_create_from_string("%any");
525 }
526 DBG2(DBG_CFG, " my ca: '%D'", my_ca);
527 DBG2(DBG_CFG, " other ca:'%D'", other_ca);
528
529 if (msg->add_conn.other.groups)
530 {
531 ietfAttr_list_create_from_string(msg->add_conn.other.groups, other_groups);
532 }
533
534 /* have a look for an (almost) identical peer config to reuse */
535 iterator = charon->backends->create_iterator(charon->backends);
536 while (iterator->iterate(iterator, (void**)&peer_cfg))
537 {
538 host_t *my_vip_conf, *other_vip_conf;
539 bool my_vip_equals = FALSE, other_vip_equals = FALSE;
540
541 my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg);
542 if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) ||
543 (!my_vip_conf && !my_vip))
544 {
545 my_vip_equals = TRUE;
546 }
547 DESTROY_IF(my_vip_conf);
548 other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL);
549 if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) ||
550 (!other_vip_conf && !other_vip))
551 {
552 other_vip_equals = TRUE;
553 }
554 DESTROY_IF(other_vip_conf);
555
556 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
557 if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg))
558 && other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg))
559 && my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg))
560 && other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg))
561 && other_ca->equals(other_ca, peer_cfg->get_other_ca(peer_cfg))
562 && ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg))
563 && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
564 && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
565 && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type
566 && vendor == msg->add_conn.eap_vendor
567 && my_vip_equals && other_vip_equals)
568 {
569 DBG1(DBG_CFG, "reusing existing configuration '%s'",
570 peer_cfg->get_name(peer_cfg));
571 use_existing = TRUE;
572 break;
573 }
574 }
575 iterator->destroy(iterator);
576
577 if (use_existing)
578 {
579 DESTROY_IF(my_vip);
580 DESTROY_IF(other_vip);
581 my_host->destroy(my_host);
582 my_id->destroy(my_id);
583 my_ca->destroy(my_ca);
584 other_host->destroy(other_host);
585 other_id->destroy(other_id);
586 other_ca->destroy(other_ca);
587 DESTROY_IF(peer_id);
588 DESTROY_IF(mediated_by_cfg);
589 ietfAttr_list_destroy(other_groups);
590 }
591 else
592 {
593 ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
594 msg->add_conn.force_encap, my_host, other_host);
595
596 if (msg->add_conn.algorithms.ike)
597 {
598 char *proposal_string;
599 char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
600
601 if (*strict == '!')
602 *strict = '\0';
603 else
604 strict = NULL;
605
606 while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
607 {
608 proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
609 if (proposal == NULL)
610 {
611 DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
612 my_id->destroy(my_id);
613 other_id->destroy(other_id);
614 my_ts->destroy(my_ts);
615 other_ts->destroy(other_ts);
616 my_ca->destroy(my_ca);
617 other_ca->destroy(other_ca);
618 ike_cfg->destroy(ike_cfg);
619 return;
620 }
621 ike_cfg->add_proposal(ike_cfg, proposal);
622 }
623 if (!strict)
624 {
625 proposal = proposal_create_default(PROTO_IKE);
626 ike_cfg->add_proposal(ike_cfg, proposal);
627 }
628 }
629 else
630 {
631 proposal = proposal_create_default(PROTO_IKE);
632 ike_cfg->add_proposal(ike_cfg, proposal);
633 }
634
635 u_int32_t rekey = 0, reauth = 0, over, jitter;
636
637 jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
638 over = msg->add_conn.rekey.margin;
639 if (msg->add_conn.rekey.reauth)
640 {
641 reauth = msg->add_conn.rekey.ike_lifetime - over;
642 }
643 else
644 {
645 rekey = msg->add_conn.rekey.ike_lifetime - over;
646 }
647
648 peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
649 ike_cfg, my_id, other_id, my_ca, other_ca, other_groups,
650 msg->add_conn.me.sendcert, msg->add_conn.auth_method,
651 msg->add_conn.eap_type, msg->add_conn.eap_vendor,
652 msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
653 msg->add_conn.mobike,
654 msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip,
655 msg->add_conn.p2p.mediation, mediated_by_cfg, peer_id);
656 }
657
658 child_cfg = child_cfg_create(
659 msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
660 msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
661 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
662 msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
663 msg->add_conn.mode);
664
665 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
666
667 child_cfg->add_traffic_selector(child_cfg, TRUE, my_ts);
668 child_cfg->add_traffic_selector(child_cfg, FALSE, other_ts);
669
670 if (msg->add_conn.algorithms.esp)
671 {
672 char *proposal_string;
673 char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
674
675 if (*strict == '!')
676 *strict = '\0';
677 else
678 strict = NULL;
679
680 while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
681 {
682 proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
683 if (proposal == NULL)
684 {
685 DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
686 peer_cfg->destroy(peer_cfg);
687 return;
688 }
689 child_cfg->add_proposal(child_cfg, proposal);
690 }
691 if (!strict)
692 {
693 proposal = proposal_create_default(PROTO_ESP);
694 child_cfg->add_proposal(child_cfg, proposal);
695 }
696 }
697 else
698 {
699 proposal = proposal_create_default(PROTO_ESP);
700 child_cfg->add_proposal(child_cfg, proposal);
701 }
702
703 if (!use_existing)
704 {
705 /* add config to backend */
706 charon->backends->add_peer_cfg(charon->backends, peer_cfg);
707 DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]",
708 msg->add_conn.name, my_host, my_id, other_host, other_id);
709 }
710 return;
711
712 /* mopping up after parsing errors */
713
714 destroy_ids:
715 my_id->destroy(my_id);
716 other_id->destroy(other_id);
717 DESTROY_IF(mediated_by_cfg);
718 DESTROY_IF(peer_id);
719
720 destroy_hosts:
721 my_host->destroy(my_host);
722 other_host->destroy(other_host);
723 }
724
725 /**
726 * Delete a connection from the list
727 */
728 static void stroke_del_conn(stroke_msg_t *msg, FILE *out)
729 {
730 iterator_t *peer_iter, *child_iter;
731 peer_cfg_t *peer;
732 child_cfg_t *child;
733
734 pop_string(msg, &(msg->del_conn.name));
735 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
736
737 peer_iter = charon->backends->create_iterator(charon->backends);
738 while (peer_iter->iterate(peer_iter, (void**)&peer))
739 {
740 /* remove peer config with such a name */
741 if (streq(peer->get_name(peer), msg->del_conn.name))
742 {
743 peer_iter->remove(peer_iter);
744 peer->destroy(peer);
745 continue;
746 }
747 /* remove any child with such a name */
748 child_iter = peer->create_child_cfg_iterator(peer);
749 while (child_iter->iterate(child_iter, (void**)&child))
750 {
751 if (streq(child->get_name(child), msg->del_conn.name))
752 {
753 child_iter->remove(child_iter);
754 child->destroy(child);
755 }
756 }
757 child_iter->destroy(child_iter);
758 }
759 peer_iter->destroy(peer_iter);
760
761 fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
762 }
763
764 /**
765 * get the child_cfg with the same name as the peer cfg
766 */
767 static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
768 {
769 child_cfg_t *current, *found = NULL;
770 iterator_t *iterator;
771
772 iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
773 while (iterator->iterate(iterator, (void**)&current))
774 {
775 if (streq(current->get_name(current), name))
776 {
777 found = current;
778 found->get_ref(found);
779 break;
780 }
781 }
782 iterator->destroy(iterator);
783 return found;
784 }
785
786 /**
787 * logging to the stroke interface
788 */
789 static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level,
790 ike_sa_t *ike_sa, char *format, va_list args)
791 {
792 if (level <= info->level)
793 {
794 if (vfprintf(info->out, format, args) < 0 ||
795 fprintf(info->out, "\n") < 0 ||
796 fflush(info->out) != 0)
797 {
798 return FALSE;
799 }
800 }
801 return TRUE;
802 }
803
804 /**
805 * initiate a connection by name
806 */
807 static void stroke_initiate(stroke_msg_t *msg, FILE *out)
808 {
809 peer_cfg_t *peer_cfg;
810 child_cfg_t *child_cfg;
811 stroke_log_info_t info;
812
813 pop_string(msg, &(msg->initiate.name));
814 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
815
816 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
817 msg->initiate.name);
818 if (peer_cfg == NULL)
819 {
820 fprintf(out, "no config named '%s'\n", msg->initiate.name);
821 return;
822 }
823 if (peer_cfg->get_ike_version(peer_cfg) != 2)
824 {
825 DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
826 peer_cfg->get_ike_version(peer_cfg));
827 peer_cfg->destroy(peer_cfg);
828 return;
829 }
830
831 child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
832 if (child_cfg == NULL)
833 {
834 fprintf(out, "no child config named '%s'\n", msg->initiate.name);
835 peer_cfg->destroy(peer_cfg);
836 return;
837 }
838
839 if (msg->output_verbosity < 0)
840 {
841 charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg,
842 NULL, NULL);
843 }
844 else
845 {
846 info.out = out;
847 info.level = msg->output_verbosity;
848 charon->interfaces->initiate(charon->interfaces, peer_cfg, child_cfg,
849 (interface_manager_cb_t)stroke_log, &info);
850 }
851 }
852
853 /**
854 * route a policy (install SPD entries)
855 */
856 static void stroke_route(stroke_msg_t *msg, FILE *out)
857 {
858 peer_cfg_t *peer_cfg;
859 child_cfg_t *child_cfg;
860 stroke_log_info_t info;
861
862 pop_string(msg, &(msg->route.name));
863 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
864
865 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
866 msg->route.name);
867 if (peer_cfg == NULL)
868 {
869 fprintf(out, "no config named '%s'\n", msg->route.name);
870 return;
871 }
872 if (peer_cfg->get_ike_version(peer_cfg) != 2)
873 {
874 peer_cfg->destroy(peer_cfg);
875 return;
876 }
877
878 child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
879 if (child_cfg == NULL)
880 {
881 fprintf(out, "no child config named '%s'\n", msg->route.name);
882 peer_cfg->destroy(peer_cfg);
883 return;
884 }
885
886 info.out = out;
887 info.level = msg->output_verbosity;
888 charon->interfaces->route(charon->interfaces, peer_cfg, child_cfg,
889 (interface_manager_cb_t)stroke_log, &info);
890 peer_cfg->destroy(peer_cfg);
891 child_cfg->destroy(child_cfg);
892 }
893
894 /**
895 * unroute a policy
896 */
897 static void stroke_unroute(stroke_msg_t *msg, FILE *out)
898 {
899 char *name;
900 ike_sa_t *ike_sa;
901 iterator_t *iterator;
902 stroke_log_info_t info;
903
904 pop_string(msg, &(msg->terminate.name));
905 name = msg->terminate.name;
906
907 info.out = out;
908 info.level = msg->output_verbosity;
909
910 iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces);
911 while (iterator->iterate(iterator, (void**)&ike_sa))
912 {
913 child_sa_t *child_sa;
914 iterator_t *children;
915 u_int32_t id;
916
917 children = ike_sa->create_child_sa_iterator(ike_sa);
918 while (children->iterate(children, (void**)&child_sa))
919 {
920 if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
921 streq(name, child_sa->get_name(child_sa)))
922 {
923 id = child_sa->get_reqid(child_sa);
924 children->destroy(children);
925 iterator->destroy(iterator);
926 charon->interfaces->unroute(charon->interfaces, id,
927 (interface_manager_cb_t)stroke_log, &info);
928 return;
929 }
930 }
931 children->destroy(children);
932 }
933 iterator->destroy(iterator);
934 DBG1(DBG_CFG, "no such SA found");
935 }
936
937 /**
938 * terminate a connection by name
939 */
940 static void stroke_terminate(stroke_msg_t *msg, FILE *out)
941 {
942 char *string, *pos = NULL, *name = NULL;
943 u_int32_t id = 0;
944 bool child;
945 int len;
946 ike_sa_t *ike_sa;
947 iterator_t *iterator;
948 stroke_log_info_t info;
949
950 pop_string(msg, &(msg->terminate.name));
951 string = msg->terminate.name;
952 DBG1(DBG_CFG, "received stroke: terminate '%s'", string);
953
954 len = strlen(string);
955 if (len < 1)
956 {
957 DBG1(DBG_CFG, "error parsing string");
958 return;
959 }
960 switch (string[len-1])
961 {
962 case '}':
963 child = TRUE;
964 pos = strchr(string, '{');
965 break;
966 case ']':
967 child = FALSE;
968 pos = strchr(string, '[');
969 break;
970 default:
971 name = string;
972 child = FALSE;
973 break;
974 }
975
976 if (name)
977 {
978 /* is a single name */
979 }
980 else if (pos == string + len - 2)
981 { /* is name[] or name{} */
982 string[len-2] = '\0';
983 name = string;
984 }
985 else
986 { /* is name[123] or name{23} */
987 string[len-1] = '\0';
988 id = atoi(pos + 1);
989 if (id == 0)
990 {
991 DBG1(DBG_CFG, "error parsing string");
992 return;
993 }
994 }
995
996 info.out = out;
997 info.level = msg->output_verbosity;
998
999 iterator = charon->interfaces->create_ike_sa_iterator(charon->interfaces);
1000 while (iterator->iterate(iterator, (void**)&ike_sa))
1001 {
1002 child_sa_t *child_sa;
1003 iterator_t *children;
1004
1005 if (child)
1006 {
1007 children = ike_sa->create_child_sa_iterator(ike_sa);
1008 while (children->iterate(children, (void**)&child_sa))
1009 {
1010 if ((name && streq(name, child_sa->get_name(child_sa))) ||
1011 (id && id == child_sa->get_reqid(child_sa)))
1012 {
1013 id = child_sa->get_reqid(child_sa);
1014 children->destroy(children);
1015 iterator->destroy(iterator);
1016
1017 charon->interfaces->terminate_child(charon->interfaces, id,
1018 (interface_manager_cb_t)stroke_log, &info);
1019 return;
1020 }
1021 }
1022 children->destroy(children);
1023 }
1024 else if ((name && streq(name, ike_sa->get_name(ike_sa))) ||
1025 (id && id == ike_sa->get_unique_id(ike_sa)))
1026 {
1027 id = ike_sa->get_unique_id(ike_sa);
1028 /* unlock manager first */
1029 iterator->destroy(iterator);
1030
1031 charon->interfaces->terminate_ike(charon->interfaces, id,
1032 (interface_manager_cb_t)stroke_log, &info);
1033 return;
1034 }
1035
1036 }
1037 iterator->destroy(iterator);
1038 DBG1(DBG_CFG, "no such SA found");
1039 }
1040
1041 /**
1042 * Add a ca information record to the cainfo list
1043 */
1044 static void stroke_add_ca(stroke_msg_t *msg, FILE *out)
1045 {
1046 x509_t *cacert;
1047 ca_info_t *ca_info;
1048
1049 pop_string(msg, &msg->add_ca.name);
1050 pop_string(msg, &msg->add_ca.cacert);
1051 pop_string(msg, &msg->add_ca.crluri);
1052 pop_string(msg, &msg->add_ca.crluri2);
1053 pop_string(msg, &msg->add_ca.ocspuri);
1054 pop_string(msg, &msg->add_ca.ocspuri2);
1055
1056 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
1057
1058 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
1059 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
1060 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
1061 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
1062 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
1063 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
1064
1065 if (msg->add_ca.cacert == NULL)
1066 {
1067 DBG1(DBG_CFG, "missing cacert parameter\n");
1068 return;
1069 }
1070
1071 cacert = load_ca_certificate(msg->add_ca.cacert);
1072
1073 if (cacert == NULL)
1074 {
1075 return;
1076 }
1077 ca_info = ca_info_create(msg->add_ca.name, cacert);
1078
1079 if (msg->add_ca.crluri)
1080 {
1081 chunk_t uri = { msg->add_ca.crluri, strlen(msg->add_ca.crluri) };
1082
1083 ca_info->add_crluri(ca_info, uri);
1084 }
1085 if (msg->add_ca.crluri2)
1086 {
1087 chunk_t uri = { msg->add_ca.crluri2, strlen(msg->add_ca.crluri2) };
1088
1089 ca_info->add_crluri(ca_info, uri);
1090 }
1091 if (msg->add_ca.ocspuri)
1092 {
1093 chunk_t uri = { msg->add_ca.ocspuri, strlen(msg->add_ca.ocspuri) };
1094
1095 ca_info->add_ocspuri(ca_info, uri);
1096 }
1097 if (msg->add_ca.ocspuri2)
1098 {
1099 chunk_t uri = { msg->add_ca.ocspuri2, strlen(msg->add_ca.ocspuri2) };
1100
1101 ca_info->add_ocspuri(ca_info, uri);
1102 }
1103 charon->credentials->add_ca_info(charon->credentials, ca_info);
1104 DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
1105
1106 }
1107
1108 /**
1109 * Delete a ca information record from the cainfo list
1110 */
1111 static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
1112 {
1113 status_t status;
1114
1115 pop_string(msg, &(msg->del_ca.name));
1116 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
1117
1118 status = charon->credentials->release_ca_info(charon->credentials,
1119 msg->del_ca.name);
1120
1121 if (status == SUCCESS)
1122 {
1123 fprintf(out, "deleted ca '%s'\n", msg->del_ca.name);
1124 }
1125 else
1126 {
1127 fprintf(out, "no ca named '%s'\n", msg->del_ca.name);
1128 }
1129 }
1130
1131 /**
1132 * log an IKE_SA to out
1133 */
1134 static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
1135 {
1136 ike_sa_id_t *id = ike_sa->get_id(ike_sa);
1137 u_int32_t rekey, reauth;
1138
1139 fprintf(out, "%12s[%d]: %N, %H[%D]...%H[%D]\n",
1140 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
1141 ike_sa_state_names, ike_sa->get_state(ike_sa),
1142 ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
1143 ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
1144
1145 if (all)
1146 {
1147 fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s",
1148 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
1149 id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
1150 id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
1151
1152 rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME);
1153 reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME);
1154 if (rekey)
1155 {
1156 fprintf(out, ", rekeying in %V", &rekey);
1157 }
1158 if (reauth)
1159 {
1160 fprintf(out, ", reauthentication in %V", &reauth);
1161 }
1162 if (!rekey && !reauth)
1163 {
1164 fprintf(out, ", rekeying disabled");
1165 }
1166 fprintf(out, "\n");
1167 }
1168 }
1169
1170 /**
1171 * log an CHILD_SA to out
1172 */
1173 static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
1174 {
1175 u_int32_t rekey, now = time(NULL);
1176 u_int32_t use_in, use_out, use_fwd;
1177 encryption_algorithm_t encr_alg;
1178 integrity_algorithm_t int_alg;
1179 size_t encr_len, int_len;
1180 mode_t mode;
1181
1182 child_sa->get_stats(child_sa, &mode, &encr_alg, &encr_len,
1183 &int_alg, &int_len, &rekey, &use_in, &use_out,
1184 &use_fwd);
1185
1186 fprintf(out, "%12s{%d}: %N, %N",
1187 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
1188 child_sa_state_names, child_sa->get_state(child_sa),
1189 mode_names, mode);
1190
1191 if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
1192 {
1193 fprintf(out, ", %N SPIs: %.8x_i %.8x_o",
1194 protocol_id_names, child_sa->get_protocol(child_sa),
1195 htonl(child_sa->get_spi(child_sa, TRUE)),
1196 htonl(child_sa->get_spi(child_sa, FALSE)));
1197
1198 if (all)
1199 {
1200 fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa),
1201 child_sa->get_reqid(child_sa));
1202
1203
1204 if (child_sa->get_protocol(child_sa) == PROTO_ESP)
1205 {
1206 fprintf(out, "%N", encryption_algorithm_names, encr_alg);
1207
1208 if (encr_len)
1209 {
1210 fprintf(out, "-%d", encr_len);
1211 }
1212 fprintf(out, "/");
1213 }
1214
1215 fprintf(out, "%N", integrity_algorithm_names, int_alg);
1216 if (int_len)
1217 {
1218 fprintf(out, "-%d", int_len);
1219 }
1220 fprintf(out, ", rekeying ");
1221
1222 if (rekey)
1223 {
1224 fprintf(out, "in %#V", &now, &rekey);
1225 }
1226 else
1227 {
1228 fprintf(out, "disabled");
1229 }
1230
1231 fprintf(out, ", last use: ");
1232 use_in = max(use_in, use_fwd);
1233 if (use_in)
1234 {
1235 fprintf(out, "%ds_i ", now - use_in);
1236 }
1237 else
1238 {
1239 fprintf(out, "no_i ");
1240 }
1241 if (use_out)
1242 {
1243 fprintf(out, "%ds_o ", now - use_out);
1244 }
1245 else
1246 {
1247 fprintf(out, "no_o ");
1248 }
1249 }
1250 }
1251
1252 fprintf(out, "\n%12s{%d}: %#R=== %#R\n",
1253 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
1254 child_sa->get_traffic_selectors(child_sa, TRUE),
1255 child_sa->get_traffic_selectors(child_sa, FALSE));
1256 }
1257
1258 /**
1259 * show status of daemon
1260 */
1261 static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
1262 {
1263 iterator_t *iterator, *children;
1264 host_t *host;
1265 peer_cfg_t *peer_cfg;
1266 ike_cfg_t *ike_cfg;
1267 child_cfg_t *child_cfg;
1268 ike_sa_t *ike_sa;
1269 char *name = NULL;
1270
1271 if (msg->status.name)
1272 {
1273 pop_string(msg, &(msg->status.name));
1274 name = msg->status.name;
1275 }
1276
1277 if (all)
1278 {
1279 leak_detective_status(out);
1280
1281 fprintf(out, "Performance:\n");
1282 fprintf(out, " worker threads: %d idle of %d,",
1283 charon->processor->get_idle_threads(charon->processor),
1284 charon->processor->get_total_threads(charon->processor));
1285 fprintf(out, " job queue load: %d,",
1286 charon->processor->get_job_load(charon->processor));
1287 fprintf(out, " scheduled events: %d\n",
1288 charon->scheduler->get_job_load(charon->scheduler));
1289 iterator = charon->kernel_interface->create_address_iterator(
1290 charon->kernel_interface);
1291 fprintf(out, "Listening IP addresses:\n");
1292 while (iterator->iterate(iterator, (void**)&host))
1293 {
1294 fprintf(out, " %H\n", host);
1295 }
1296 iterator->destroy(iterator);
1297
1298 fprintf(out, "Connections:\n");
1299 iterator = charon->backends->create_iterator(charon->backends);
1300 while (iterator->iterate(iterator, (void**)&peer_cfg))
1301 {
1302 if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
1303 (name && !streq(name, peer_cfg->get_name(peer_cfg))))
1304 {
1305 continue;
1306 }
1307
1308 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
1309 fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
1310 ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
1311 ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
1312 {
1313 identification_t *my_ca = peer_cfg->get_my_ca(peer_cfg);
1314 identification_t *other_ca = peer_cfg->get_other_ca(peer_cfg);
1315 linked_list_t *groups = peer_cfg->get_groups(peer_cfg);
1316
1317 if (my_ca->get_type(my_ca) != ID_ANY
1318 || other_ca->get_type(other_ca) != ID_ANY)
1319 {
1320 fprintf(out, "%12s: CAs: '%D'...'%D'\n", peer_cfg->get_name(peer_cfg),
1321 my_ca, other_ca);
1322 }
1323 if (groups->get_count(groups) > 0)
1324 {
1325 fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg));
1326 ietfAttr_list_list(groups, out);
1327 fprintf(out, "\n");
1328 }
1329
1330 }
1331 children = peer_cfg->create_child_cfg_iterator(peer_cfg);
1332 while (children->iterate(children, (void**)&child_cfg))
1333 {
1334 linked_list_t *my_ts, *other_ts;
1335 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
1336 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
1337 fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg),
1338 my_ts, other_ts);
1339 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
1340 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
1341 }
1342 children->destroy(children);
1343 }
1344 iterator->destroy(iterator);
1345 }
1346
1347 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
1348 if (all && iterator->get_count(iterator) > 0)
1349 {
1350 fprintf(out, "Security Associations:\n");
1351 }
1352 while (iterator->iterate(iterator, (void**)&ike_sa))
1353 {
1354 bool ike_printed = FALSE;
1355 child_sa_t *child_sa;
1356 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
1357
1358 if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
1359 {
1360 log_ike_sa(out, ike_sa, all);
1361 ike_printed = TRUE;
1362 }
1363
1364 while (children->iterate(children, (void**)&child_sa))
1365 {
1366 if (name == NULL || streq(name, child_sa->get_name(child_sa)))
1367 {
1368 if (!ike_printed)
1369 {
1370 log_ike_sa(out, ike_sa, all);
1371 ike_printed = TRUE;
1372 }
1373 log_child_sa(out, child_sa, all);
1374 }
1375 }
1376 children->destroy(children);
1377 }
1378 iterator->destroy(iterator);
1379 }
1380
1381 /**
1382 * list all authority certificates matching a specified flag
1383 */
1384 static void list_auth_certificates(u_int flag, const char *label,
1385 bool utc, FILE *out)
1386 {
1387 bool first = TRUE;
1388 x509_t *cert;
1389
1390 iterator_t *iterator = charon->credentials->create_auth_cert_iterator(charon->credentials);
1391
1392 while (iterator->iterate(iterator, (void**)&cert))
1393 {
1394 if (cert->has_authority_flag(cert, flag))
1395 {
1396 if (first)
1397 {
1398 fprintf(out, "\n");
1399 fprintf(out, "List of X.509 %s Certificates:\n", label);
1400 fprintf(out, "\n");
1401 first = FALSE;
1402 }
1403 cert->list(cert, out, utc);
1404 fprintf(out, "\n");
1405 }
1406 }
1407 iterator->destroy(iterator);
1408 }
1409
1410 /**
1411 * list various information
1412 */
1413 static void stroke_list(stroke_msg_t *msg, FILE *out)
1414 {
1415 iterator_t *iterator;
1416
1417 if (msg->list.flags & LIST_CERTS)
1418 {
1419 x509_t *cert;
1420
1421 iterator = charon->credentials->create_cert_iterator(charon->credentials);
1422 if (iterator->get_count(iterator))
1423 {
1424 fprintf(out, "\n");
1425 fprintf(out, "List of X.509 End Entity Certificates:\n");
1426 fprintf(out, "\n");
1427 }
1428 while (iterator->iterate(iterator, (void**)&cert))
1429 {
1430 cert->list(cert, out, msg->list.utc);
1431 if (charon->credentials->has_rsa_private_key(
1432 charon->credentials, cert->get_public_key(cert)))
1433 {
1434 fprintf(out, ", has private key");
1435 }
1436 fprintf(out, "\n");
1437
1438 }
1439 iterator->destroy(iterator);
1440 }
1441 if (msg->list.flags & LIST_CACERTS)
1442 {
1443 list_auth_certificates(AUTH_CA, "CA", msg->list.utc, out);
1444 }
1445 if (msg->list.flags & LIST_OCSPCERTS)
1446 {
1447 list_auth_certificates(AUTH_OCSP, "OCSP", msg->list.utc, out);
1448 }
1449 if (msg->list.flags & LIST_AACERTS)
1450 {
1451 list_auth_certificates(AUTH_AA, "AA", msg->list.utc, out);
1452 }
1453 if (msg->list.flags & LIST_ACERTS)
1454 {
1455 x509ac_t *cert;
1456
1457 iterator = charon->credentials->create_acert_iterator(charon->credentials);
1458 if (iterator->get_count(iterator))
1459 {
1460 fprintf(out, "\n");
1461 fprintf(out, "List of X.509 Attribute Certificates:\n");
1462 fprintf(out, "\n");
1463 }
1464 while (iterator->iterate(iterator, (void**)&cert))
1465 {
1466 cert->list(cert, out, msg->list.utc);
1467 }
1468 iterator->destroy(iterator);
1469 }
1470 if (msg->list.flags & LIST_CAINFOS)
1471 {
1472 ca_info_t *ca_info;
1473 bool first = TRUE;
1474
1475 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1476 while (iterator->iterate(iterator, (void**)&ca_info))
1477 {
1478 if (ca_info->is_ca(ca_info))
1479 {
1480 if (first)
1481 {
1482 fprintf(out, "\n");
1483 fprintf(out, "List of X.509 CA Information Records:\n");
1484 fprintf(out, "\n");
1485 first = FALSE;
1486 }
1487 ca_info->list(ca_info, out, msg->list.utc);
1488 }
1489 }
1490 iterator->destroy(iterator);
1491 }
1492 if (msg->list.flags & LIST_CRLS)
1493 {
1494 ca_info_t *ca_info;
1495 bool first = TRUE;
1496
1497 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1498 while (iterator->iterate(iterator, (void **)&ca_info))
1499 {
1500 if (ca_info->is_ca(ca_info) && ca_info->has_crl(ca_info))
1501 {
1502 if (first)
1503 {
1504 fprintf(out, "\n");
1505 fprintf(out, "List of X.509 CRLs:\n");
1506 fprintf(out, "\n");
1507 first = FALSE;
1508 }
1509 ca_info->list_crl(ca_info, out, msg->list.utc);
1510 }
1511 }
1512 iterator->destroy(iterator);
1513 }
1514 if (msg->list.flags & LIST_OCSP)
1515 {
1516 ca_info_t *ca_info;
1517 bool first = TRUE;
1518
1519 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1520 while (iterator->iterate(iterator, (void **)&ca_info))
1521 {
1522 if (ca_info->is_ca(ca_info) && ca_info->has_certinfos(ca_info))
1523 {
1524 if (first)
1525 {
1526 fprintf(out, "\n");
1527 fprintf(out, "List of OCSP responses:\n");
1528 first = FALSE;
1529 }
1530 fprintf(out, "\n");
1531 ca_info->list_certinfos(ca_info, out, msg->list.utc);
1532 }
1533 }
1534 iterator->destroy(iterator);
1535 }
1536 }
1537
1538 /**
1539 * reread various information
1540 */
1541 static void stroke_reread(stroke_msg_t *msg, FILE *out)
1542 {
1543 if (msg->reread.flags & REREAD_SECRETS)
1544 {
1545 charon->credentials->load_secrets(charon->credentials, TRUE);
1546 }
1547 if (msg->reread.flags & REREAD_CACERTS)
1548 {
1549 charon->credentials->load_ca_certificates(charon->credentials);
1550 }
1551 if (msg->reread.flags & REREAD_OCSPCERTS)
1552 {
1553 charon->credentials->load_ocsp_certificates(charon->credentials);
1554 }
1555 if (msg->reread.flags & REREAD_AACERTS)
1556 {
1557 charon->credentials->load_aa_certificates(charon->credentials);
1558 }
1559 if (msg->reread.flags & REREAD_ACERTS)
1560 {
1561 charon->credentials->load_attr_certificates(charon->credentials);
1562 }
1563 if (msg->reread.flags & REREAD_CRLS)
1564 {
1565 charon->credentials->load_crls(charon->credentials);
1566 }
1567 }
1568
1569 /**
1570 * purge various information
1571 */
1572 static void stroke_purge(stroke_msg_t *msg, FILE *out)
1573 {
1574 if (msg->purge.flags & PURGE_OCSP)
1575 {
1576 iterator_t *iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1577 ca_info_t *ca_info;
1578
1579 while (iterator->iterate(iterator, (void**)&ca_info))
1580 {
1581 if (ca_info->is_ca(ca_info))
1582 {
1583 ca_info->purge_ocsp(ca_info);
1584 }
1585 }
1586 iterator->destroy(iterator);
1587 }
1588 }
1589
1590 signal_t get_signal_from_logtype(char *type)
1591 {
1592 if (strcasecmp(type, "any") == 0) return SIG_ANY;
1593 else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
1594 else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
1595 else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
1596 else if (strcasecmp(type, "job") == 0) return DBG_JOB;
1597 else if (strcasecmp(type, "cfg") == 0) return DBG_CFG;
1598 else if (strcasecmp(type, "knl") == 0) return DBG_KNL;
1599 else if (strcasecmp(type, "net") == 0) return DBG_NET;
1600 else if (strcasecmp(type, "enc") == 0) return DBG_ENC;
1601 else if (strcasecmp(type, "lib") == 0) return DBG_LIB;
1602 else return -1;
1603 }
1604
1605 /**
1606 * set the verbosity debug output
1607 */
1608 static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
1609 {
1610 signal_t signal;
1611
1612 pop_string(msg, &(msg->loglevel.type));
1613 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
1614 msg->loglevel.level, msg->loglevel.type);
1615
1616 signal = get_signal_from_logtype(msg->loglevel.type);
1617 if (signal < 0)
1618 {
1619 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
1620 return;
1621 }
1622
1623 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
1624 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
1625 }
1626
1627 /**
1628 * process a stroke request from the socket pointed by "fd"
1629 */
1630 static job_requeue_t stroke_process(int *fdp)
1631 {
1632 stroke_msg_t *msg;
1633 u_int16_t msg_length;
1634 ssize_t bytes_read;
1635 FILE *out;
1636 int strokefd = *fdp;
1637
1638 /* peek the length */
1639 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
1640 if (bytes_read != sizeof(msg_length))
1641 {
1642 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
1643 strerror(errno));
1644 close(strokefd);
1645 return JOB_REQUEUE_NONE;
1646 }
1647
1648 /* read message */
1649 msg = malloc(msg_length);
1650 bytes_read = recv(strokefd, msg, msg_length, 0);
1651 if (bytes_read != msg_length)
1652 {
1653 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
1654 close(strokefd);
1655 return JOB_REQUEUE_NONE;
1656 }
1657
1658 out = fdopen(strokefd, "w");
1659 if (out == NULL)
1660 {
1661 DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
1662 close(strokefd);
1663 free(msg);
1664 return JOB_REQUEUE_NONE;
1665 }
1666
1667 DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
1668
1669 /* the stroke_* functions are blocking, as they listen on the bus. Add
1670 * cancellation handlers. */
1671 pthread_cleanup_push((void*)fclose, out);
1672 pthread_cleanup_push(free, msg);
1673
1674 switch (msg->type)
1675 {
1676 case STR_INITIATE:
1677 stroke_initiate(msg, out);
1678 break;
1679 case STR_ROUTE:
1680 stroke_route(msg, out);
1681 break;
1682 case STR_UNROUTE:
1683 stroke_unroute(msg, out);
1684 break;
1685 case STR_TERMINATE:
1686 stroke_terminate(msg, out);
1687 break;
1688 case STR_STATUS:
1689 stroke_status(msg, out, FALSE);
1690 break;
1691 case STR_STATUS_ALL:
1692 stroke_status(msg, out, TRUE);
1693 break;
1694 case STR_ADD_CONN:
1695 stroke_add_conn(msg, out);
1696 break;
1697 case STR_DEL_CONN:
1698 stroke_del_conn(msg, out);
1699 break;
1700 case STR_ADD_CA:
1701 stroke_add_ca(msg, out);
1702 break;
1703 case STR_DEL_CA:
1704 stroke_del_ca(msg, out);
1705 break;
1706 case STR_LOGLEVEL:
1707 stroke_loglevel(msg, out);
1708 break;
1709 case STR_LIST:
1710 stroke_list(msg, out);
1711 break;
1712 case STR_REREAD:
1713 stroke_reread(msg, out);
1714 break;
1715 case STR_PURGE:
1716 stroke_purge(msg, out);
1717 break;
1718 default:
1719 DBG1(DBG_CFG, "received unknown stroke");
1720 }
1721 /* remove and execute cancellation handlers */
1722 pthread_cleanup_pop(1);
1723 pthread_cleanup_pop(1);
1724
1725 return JOB_REQUEUE_NONE;
1726 }
1727
1728 /**
1729 * Implementation of private_stroke_interface_t.stroke_receive.
1730 */
1731 static job_requeue_t stroke_receive(private_stroke_interface_t *this)
1732 {
1733 struct sockaddr_un strokeaddr;
1734 int strokeaddrlen = sizeof(strokeaddr);
1735 int strokefd, *fdp;
1736 int oldstate;
1737 callback_job_t *job;
1738
1739 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
1740 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
1741 pthread_setcancelstate(oldstate, NULL);
1742
1743 if (strokefd < 0)
1744 {
1745 DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
1746 return JOB_REQUEUE_FAIR;
1747 }
1748
1749 fdp = malloc_thing(int);
1750 *fdp = strokefd;
1751 job = callback_job_create((callback_job_cb_t)stroke_process, fdp, free, this->job);
1752 charon->processor->queue_job(charon->processor, (job_t*)job);
1753
1754 return JOB_REQUEUE_FAIR;
1755 }
1756
1757 /**
1758 * Implementation of interface_t.destroy.
1759 */
1760 static void destroy(private_stroke_interface_t *this)
1761 {
1762 this->job->cancel(this->job);
1763 free(this);
1764 }
1765
1766 /*
1767 * Described in header-file
1768 */
1769 interface_t *interface_create()
1770 {
1771 struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
1772 private_stroke_interface_t *this = malloc_thing(private_stroke_interface_t);
1773 mode_t old;
1774
1775 /* public functions */
1776 this->public.interface.destroy = (void (*)(interface_t*))destroy;
1777
1778 /* set up unix socket */
1779 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
1780 if (this->socket == -1)
1781 {
1782 DBG1(DBG_CFG, "could not create stroke socket");
1783 free(this);
1784 return NULL;
1785 }
1786
1787 unlink(socket_addr.sun_path);
1788 old = umask(~(S_IRWXU | S_IRWXG));
1789 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
1790 {
1791 DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno));
1792 close(this->socket);
1793 free(this);
1794 return NULL;
1795 }
1796 umask(old);
1797 if (chown(socket_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0)
1798 {
1799 DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
1800 strerror(errno));
1801 }
1802
1803 if (listen(this->socket, 0) < 0)
1804 {
1805 DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno));
1806 close(this->socket);
1807 unlink(socket_addr.sun_path);
1808 free(this);
1809 return NULL;
1810 }
1811
1812 this->job = callback_job_create((callback_job_cb_t)stroke_receive,
1813 this, NULL, NULL);
1814 charon->processor->queue_job(charon->processor, (job_t*)this->job);
1815
1816 return &this->public.interface;
1817 }
1818