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