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