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