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