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