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