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