accepting stroke initiation by a name of a child_cfg
[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 my_host->destroy(my_host);
452 my_id->destroy(my_id);
453 my_ca->destroy(my_ca);
454 other_host->destroy(other_host);
455 other_id->destroy(other_id);
456 other_ca->destroy(other_ca);
457 }
458 else
459 {
460 ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
461 my_host, other_host);
462
463 if (msg->add_conn.algorithms.ike)
464 {
465 char *proposal_string;
466 char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
467
468 if (*strict == '!')
469 *strict = '\0';
470 else
471 strict = NULL;
472
473 while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
474 {
475 proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
476 if (proposal == NULL)
477 {
478 DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
479 my_id->destroy(my_id);
480 other_id->destroy(other_id);
481 my_ts->destroy(my_ts);
482 other_ts->destroy(other_ts);
483 my_ca->destroy(my_ca);
484 other_ca->destroy(other_ca);
485 ike_cfg->destroy(ike_cfg);
486 return;
487 }
488 ike_cfg->add_proposal(ike_cfg, proposal);
489 }
490 if (!strict)
491 {
492 proposal = proposal_create_default(PROTO_IKE);
493 ike_cfg->add_proposal(ike_cfg, proposal);
494 }
495 }
496 else
497 {
498 proposal = proposal_create_default(PROTO_IKE);
499 ike_cfg->add_proposal(ike_cfg, proposal);
500 }
501
502
503 peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
504 ike_cfg, my_id, other_id, my_ca, other_ca, msg->add_conn.me.sendcert,
505 msg->add_conn.auth_method, msg->add_conn.eap_type,
506 msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
507 msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
508 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
509 msg->add_conn.rekey.reauth, msg->add_conn.dpd.delay,
510 msg->add_conn.dpd.action,my_vip, other_vip);
511 }
512
513 child_cfg = child_cfg_create(
514 msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
515 msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
516 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
517 msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
518 msg->add_conn.mode);
519
520 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
521
522 child_cfg->add_traffic_selector(child_cfg, TRUE, my_ts);
523 child_cfg->add_traffic_selector(child_cfg, FALSE, other_ts);
524
525 if (msg->add_conn.algorithms.esp)
526 {
527 char *proposal_string;
528 char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
529
530 if (*strict == '!')
531 *strict = '\0';
532 else
533 strict = NULL;
534
535 while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
536 {
537 proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
538 if (proposal == NULL)
539 {
540 DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
541 peer_cfg->destroy(peer_cfg);
542 return;
543 }
544 child_cfg->add_proposal(child_cfg, proposal);
545 }
546 if (!strict)
547 {
548 proposal = proposal_create_default(PROTO_ESP);
549 child_cfg->add_proposal(child_cfg, proposal);
550 }
551 }
552 else
553 {
554 proposal = proposal_create_default(PROTO_ESP);
555 child_cfg->add_proposal(child_cfg, proposal);
556 }
557
558 if (!use_existing)
559 {
560 /* add config to backend */
561 this->backend->add_peer_cfg(this->backend, peer_cfg);
562 DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]",
563 msg->add_conn.name, my_host, my_id, other_host, other_id);
564 }
565 return;
566
567 /* mopping up after parsing errors */
568
569 destroy_ids:
570 my_id->destroy(my_id);
571 other_id->destroy(other_id);
572
573 destroy_hosts:
574 my_host->destroy(my_host);
575 other_host->destroy(other_host);
576 }
577
578 /**
579 * Delete a connection from the list
580 */
581 static void stroke_del_conn(private_stroke_interface_t *this,
582 stroke_msg_t *msg, FILE *out)
583 {
584 iterator_t *peer_iter, *child_iter;
585 peer_cfg_t *peer, *child;
586
587 pop_string(msg, &(msg->del_conn.name));
588 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
589
590 peer_iter = this->backend->create_peer_cfg_iterator(this->backend);
591 while (peer_iter->iterate(peer_iter, (void**)&peer))
592 {
593 /* remove peer config with such a name */
594 if (streq(peer->get_name(peer), msg->del_conn.name))
595 {
596 peer_iter->remove(peer_iter);
597 peer->destroy(peer);
598 continue;
599 }
600 /* remove any child with such a name */
601 child_iter = peer->create_child_cfg_iterator(peer);
602 while (child_iter->iterate(child_iter, (void**)&child))
603 {
604 if (streq(child->get_name(child), msg->del_conn.name))
605 {
606 child_iter->remove(child_iter);
607 child->destroy(child);
608 }
609 }
610 child_iter->destroy(child_iter);
611 }
612 peer_iter->destroy(peer_iter);
613
614 fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
615 }
616
617 /**
618 * get the child_cfg with the same name as the peer cfg
619 */
620 static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
621 {
622 child_cfg_t *current, *found = NULL;
623 iterator_t *iterator;
624
625 iterator = peer_cfg->create_child_cfg_iterator(peer_cfg);
626 while (iterator->iterate(iterator, (void**)&current))
627 {
628 if (streq(current->get_name(current), name))
629 {
630 found = current;
631 found->get_ref(found);
632 break;
633 }
634 }
635 iterator->destroy(iterator);
636 return found;
637 }
638
639 /**
640 * initiate a connection by name
641 */
642 static void stroke_initiate(private_stroke_interface_t *this,
643 stroke_msg_t *msg, FILE *out)
644 {
645 initiate_job_t *job;
646 peer_cfg_t *peer_cfg;
647 child_cfg_t *child_cfg;
648 ike_sa_t *init_ike_sa = NULL;
649 signal_t signal;
650
651 pop_string(msg, &(msg->initiate.name));
652 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
653
654 peer_cfg = this->backend->get_peer_cfg_by_name(this->backend,
655 msg->initiate.name);
656 if (peer_cfg == NULL)
657 {
658 if (msg->output_verbosity >= 0)
659 {
660 fprintf(out, "no config named '%s'\n", msg->initiate.name);
661 }
662 return;
663 }
664 if (peer_cfg->get_ike_version(peer_cfg) != 2)
665 {
666 DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
667 peer_cfg->get_ike_version(peer_cfg));
668 peer_cfg->destroy(peer_cfg);
669 return;
670 }
671
672 child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
673 if (child_cfg == NULL)
674 {
675 if (msg->output_verbosity >= 0)
676 {
677 fprintf(out, "no child config named '%s'\n", msg->initiate.name);
678 }
679 peer_cfg->destroy(peer_cfg);
680 return;
681 }
682
683 job = initiate_job_create(peer_cfg, child_cfg);
684 charon->bus->set_listen_state(charon->bus, TRUE);
685 charon->job_queue->add(charon->job_queue, (job_t*)job);
686 while (TRUE)
687 {
688 level_t level;
689 int thread;
690 ike_sa_t *ike_sa;
691 char* format;
692 va_list args;
693
694 signal = charon->bus->listen(charon->bus, &level, &thread, &ike_sa, &format, &args);
695
696 if ((init_ike_sa == NULL || ike_sa == init_ike_sa) &&
697 level <= msg->output_verbosity)
698 {
699 if (vfprintf(out, format, args) < 0 ||
700 fprintf(out, "\n") < 0 ||
701 fflush(out))
702 {
703 charon->bus->set_listen_state(charon->bus, FALSE);
704 break;
705 }
706 }
707
708 switch (signal)
709 {
710 case CHILD_UP_SUCCESS:
711 case CHILD_UP_FAILED:
712 case IKE_UP_FAILED:
713 if (ike_sa == init_ike_sa)
714 {
715 charon->bus->set_listen_state(charon->bus, FALSE);
716 return;
717 }
718 continue;
719 case CHILD_UP_START:
720 case IKE_UP_START:
721 if (init_ike_sa == NULL)
722 {
723 init_ike_sa = ike_sa;
724 }
725 continue;
726 default:
727 continue;
728 }
729 }
730 }
731
732 /**
733 * route/unroute a policy (install SPD entries)
734 */
735 static void stroke_route(private_stroke_interface_t *this,
736 stroke_msg_t *msg, FILE *out, bool route)
737 {
738 route_job_t *job;
739 peer_cfg_t *peer_cfg;
740 child_cfg_t *child_cfg;
741
742 pop_string(msg, &(msg->route.name));
743 DBG1(DBG_CFG, "received stroke: %s '%s'",
744 route ? "route" : "unroute", msg->route.name);
745
746 peer_cfg = this->backend->get_peer_cfg_by_name(this->backend, msg->route.name);
747 if (peer_cfg == NULL)
748 {
749 fprintf(out, "no config named '%s'\n", msg->route.name);
750 return;
751 }
752 if (peer_cfg->get_ike_version(peer_cfg) != 2)
753 {
754 peer_cfg->destroy(peer_cfg);
755 return;
756 }
757
758 child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
759 if (child_cfg == NULL)
760 {
761 fprintf(out, "no child config named '%s'\n", msg->route.name);
762 peer_cfg->destroy(peer_cfg);
763 return;
764 }
765 fprintf(out, "%s policy '%s'\n",
766 route ? "routing" : "unrouting", msg->route.name);
767 job = route_job_create(peer_cfg, child_cfg, route);
768 charon->job_queue->add(charon->job_queue, (job_t*)job);
769 }
770
771 /**
772 * terminate a connection by name
773 */
774 static void stroke_terminate(private_stroke_interface_t *this,
775 stroke_msg_t *msg, FILE *out)
776 {
777 char *string, *pos = NULL, *name = NULL;
778 u_int32_t id = 0;
779 bool child;
780 int len;
781 status_t status = SUCCESS;;
782 ike_sa_t *ike_sa;
783
784 pop_string(msg, &(msg->terminate.name));
785 string = msg->terminate.name;
786 DBG1(DBG_CFG, "received stroke: terminate '%s'", string);
787
788 len = strlen(string);
789 if (len < 1)
790 {
791 DBG1(DBG_CFG, "error parsing string");
792 return;
793 }
794 switch (string[len-1])
795 {
796 case '}':
797 child = TRUE;
798 pos = strchr(string, '{');
799 break;
800 case ']':
801 child = FALSE;
802 pos = strchr(string, '[');
803 break;
804 default:
805 name = string;
806 child = FALSE;
807 break;
808 }
809
810 if (name)
811 { /* must be a single name */
812 DBG1(DBG_CFG, "check out by single name '%s'", name);
813 ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager,
814 name, child);
815 }
816 else if (pos == string + len - 2)
817 { /* must be name[] or name{} */
818 string[len-2] = '\0';
819 DBG1(DBG_CFG, "check out by name '%s'", string);
820 ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager,
821 string, child);
822 }
823 else
824 { /* must be name[123] or name{23} */
825 string[len-1] = '\0';
826 id = atoi(pos + 1);
827 if (id == 0)
828 {
829 DBG1(DBG_CFG, "error parsing string");
830 return;
831 }
832 DBG1(DBG_CFG, "check out by id '%d'", id);
833 ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
834 id, child);
835 }
836 if (ike_sa == NULL)
837 {
838 DBG1(DBG_CFG, "no such IKE_SA found");
839 return;
840 }
841
842 if (!child)
843 {
844 status = ike_sa->delete(ike_sa);
845 }
846 else
847 {
848 child_sa_t *child_sa;
849 iterator_t *iterator = ike_sa->create_child_sa_iterator(ike_sa);
850 while (iterator->iterate(iterator, (void**)&child_sa))
851 {
852 if ((id && id == child_sa->get_reqid(child_sa)) ||
853 (string && streq(string, child_sa->get_name(child_sa))))
854 {
855 u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
856 protocol_id_t proto = child_sa->get_protocol(child_sa);
857
858 status = ike_sa->delete_child_sa(ike_sa, proto, spi);
859 break;
860 }
861 }
862 iterator->destroy(iterator);
863 }
864 if (status == DESTROY_ME)
865 {
866 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
867 ike_sa);
868 return;
869 }
870 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
871 }
872
873 /**
874 * Add a ca information record to the cainfo list
875 */
876 static void stroke_add_ca(private_stroke_interface_t *this,
877 stroke_msg_t *msg, FILE *out)
878 {
879 x509_t *cacert;
880 ca_info_t *ca_info;
881
882 pop_string(msg, &msg->add_ca.name);
883 pop_string(msg, &msg->add_ca.cacert);
884 pop_string(msg, &msg->add_ca.crluri);
885 pop_string(msg, &msg->add_ca.crluri2);
886 pop_string(msg, &msg->add_ca.ocspuri);
887 pop_string(msg, &msg->add_ca.ocspuri2);
888
889 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
890
891 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
892 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
893 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
894 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
895 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
896 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
897
898 if (msg->add_ca.cacert == NULL)
899 {
900 DBG1(DBG_CFG, "missing cacert parameter\n");
901 return;
902 }
903
904 cacert = load_ca_certificate(msg->add_ca.cacert);
905
906 if (cacert == NULL)
907 {
908 return;
909 }
910 ca_info = ca_info_create(msg->add_ca.name, cacert);
911
912 if (msg->add_ca.crluri)
913 {
914 chunk_t uri = { msg->add_ca.crluri, strlen(msg->add_ca.crluri) };
915
916 ca_info->add_crluri(ca_info, uri);
917 }
918 if (msg->add_ca.crluri2)
919 {
920 chunk_t uri = { msg->add_ca.crluri2, strlen(msg->add_ca.crluri2) };
921
922 ca_info->add_crluri(ca_info, uri);
923 }
924 if (msg->add_ca.ocspuri)
925 {
926 chunk_t uri = { msg->add_ca.ocspuri, strlen(msg->add_ca.ocspuri) };
927
928 ca_info->add_ocspuri(ca_info, uri);
929 }
930 if (msg->add_ca.ocspuri2)
931 {
932 chunk_t uri = { msg->add_ca.ocspuri2, strlen(msg->add_ca.ocspuri2) };
933
934 ca_info->add_ocspuri(ca_info, uri);
935 }
936 charon->credentials->add_ca_info(charon->credentials, ca_info);
937 DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
938
939 }
940
941 /**
942 * Delete a ca information record from the cainfo list
943 */
944 static void stroke_del_ca(private_stroke_interface_t *this,
945 stroke_msg_t *msg, FILE *out)
946 {
947 status_t status;
948
949 pop_string(msg, &(msg->del_ca.name));
950 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
951
952 status = charon->credentials->release_ca_info(charon->credentials,
953 msg->del_ca.name);
954
955 if (status == SUCCESS)
956 {
957 fprintf(out, "deleted ca '%s'\n", msg->del_ca.name);
958 }
959 else
960 {
961 fprintf(out, "no ca named '%s'\n", msg->del_ca.name);
962 }
963 }
964
965 /**
966 * show status of daemon
967 */
968 static void stroke_statusall(private_stroke_interface_t *this,
969 stroke_msg_t *msg, FILE *out)
970 {
971 iterator_t *iterator, *children;
972 linked_list_t *list;
973 host_t *host;
974 peer_cfg_t *peer_cfg;
975 ike_cfg_t *ike_cfg;
976 child_cfg_t *child_cfg;
977 ike_sa_t *ike_sa;
978 char *name = NULL;
979
980 leak_detective_status(out);
981
982 fprintf(out, "Performance:\n");
983 fprintf(out, " worker threads: %d idle of %d,",
984 charon->thread_pool->get_idle_threads(charon->thread_pool),
985 charon->thread_pool->get_pool_size(charon->thread_pool));
986 fprintf(out, " job queue load: %d,",
987 charon->job_queue->get_count(charon->job_queue));
988 fprintf(out, " scheduled events: %d\n",
989 charon->event_queue->get_count(charon->event_queue));
990 list = charon->kernel_interface->create_address_list(charon->kernel_interface);
991
992 fprintf(out, "Listening on %d IP addresses:\n", list->get_count(list));
993 while (list->remove_first(list, (void**)&host) == SUCCESS)
994 {
995 fprintf(out, " %H\n", host);
996 host->destroy(host);
997 }
998 list->destroy(list);
999
1000 if (msg->status.name)
1001 {
1002 pop_string(msg, &(msg->status.name));
1003 name = msg->status.name;
1004 }
1005
1006 fprintf(out, "Connections:\n");
1007 iterator = this->backend->create_peer_cfg_iterator(this->backend);
1008 while (iterator->iterate(iterator, (void**)&peer_cfg))
1009 {
1010 if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
1011 (name && !streq(name, peer_cfg->get_name(peer_cfg))))
1012 {
1013 continue;
1014 }
1015
1016 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
1017 fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
1018 ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
1019 ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
1020 children = peer_cfg->create_child_cfg_iterator(peer_cfg);
1021 while (children->iterate(children, (void**)&child_cfg))
1022 {
1023 linked_list_t *my_ts, *other_ts;
1024 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
1025 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
1026 fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg),
1027 my_ts, other_ts);
1028 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
1029 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
1030 }
1031 children->destroy(children);
1032 }
1033 iterator->destroy(iterator);
1034
1035
1036 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
1037 if (iterator->get_count(iterator) > 0)
1038 {
1039 fprintf(out, "Security Associations:\n");
1040 }
1041 while (iterator->iterate(iterator, (void**)&ike_sa))
1042 {
1043 bool ike_sa_printed = FALSE;
1044 child_sa_t *child_sa;
1045 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
1046
1047 /* print IKE_SA */
1048 if (name == NULL || strcmp(name, ike_sa->get_name(ike_sa)) == 0)
1049 {
1050 fprintf(out, "%#K\n", ike_sa);
1051 ike_sa_printed = TRUE;
1052 }
1053
1054 while (children->iterate(children, (void**)&child_sa))
1055 {
1056 bool child_sa_match = name == NULL ||
1057 strcmp(name, child_sa->get_name(child_sa)) == 0;
1058
1059 /* print IKE_SA if its name differs from the CHILD_SA's name */
1060 if (!ike_sa_printed && child_sa_match)
1061 {
1062 fprintf(out, "%#K\n", ike_sa);
1063 ike_sa_printed = TRUE;
1064 }
1065
1066 /* print CHILD_SA */
1067 if (child_sa_match)
1068 {
1069 fprintf(out, "%#P\n", child_sa);
1070 }
1071 }
1072 children->destroy(children);
1073 }
1074 iterator->destroy(iterator);
1075 }
1076
1077 /**
1078 * show status of daemon
1079 */
1080 static void stroke_status(private_stroke_interface_t *this,
1081 stroke_msg_t *msg, FILE *out)
1082 {
1083 iterator_t *iterator;
1084 ike_sa_t *ike_sa;
1085 char *name = NULL;
1086
1087 if (msg->status.name)
1088 {
1089 pop_string(msg, &(msg->status.name));
1090 name = msg->status.name;
1091 }
1092
1093 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
1094 while (iterator->iterate(iterator, (void**)&ike_sa))
1095 {
1096 bool ike_sa_printed = FALSE;
1097 child_sa_t *child_sa;
1098 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
1099
1100 /* print IKE_SA */
1101 if (name == NULL || strcmp(name, ike_sa->get_name(ike_sa)) == 0)
1102 {
1103 fprintf(out, "%K\n", ike_sa);
1104 ike_sa_printed = TRUE;
1105 }
1106
1107 while (children->iterate(children, (void**)&child_sa))
1108 {
1109 bool child_sa_match = name == NULL ||
1110 strcmp(name, child_sa->get_name(child_sa)) == 0;
1111
1112 /* print IKE_SA if its name differs from the CHILD_SA's name */
1113 if (!ike_sa_printed && child_sa_match)
1114 {
1115 fprintf(out, "%K\n", ike_sa);
1116 ike_sa_printed = TRUE;
1117 }
1118
1119 /* print CHILD_SA */
1120 if (child_sa_match)
1121 {
1122 fprintf(out, "%P\n", child_sa);
1123 }
1124 }
1125 children->destroy(children);
1126 }
1127 iterator->destroy(iterator);
1128 }
1129
1130 /**
1131 * list all authority certificates matching a specified flag
1132 */
1133 static void list_auth_certificates(private_stroke_interface_t *this, u_int flag,
1134 const char *label, bool utc, FILE *out)
1135 {
1136 bool first = TRUE;
1137 x509_t *cert;
1138
1139 iterator_t *iterator = charon->credentials->create_auth_cert_iterator(charon->credentials);
1140
1141 while (iterator->iterate(iterator, (void**)&cert))
1142 {
1143 if (cert->has_authority_flag(cert, flag))
1144 {
1145 if (first)
1146 {
1147 fprintf(out, "\n");
1148 fprintf(out, "List of X.509 %s Certificates:\n", label);
1149 fprintf(out, "\n");
1150 first = FALSE;
1151 }
1152 fprintf(out, "%#Q\n", cert, utc);
1153 }
1154 }
1155 iterator->destroy(iterator);
1156 }
1157
1158 /**
1159 * list various information
1160 */
1161 static void stroke_list(private_stroke_interface_t *this,
1162 stroke_msg_t *msg, FILE *out)
1163 {
1164 iterator_t *iterator;
1165
1166 if (msg->list.flags & LIST_CERTS)
1167 {
1168 x509_t *cert;
1169
1170 iterator = charon->credentials->create_cert_iterator(charon->credentials);
1171 if (iterator->get_count(iterator))
1172 {
1173 fprintf(out, "\n");
1174 fprintf(out, "List of X.509 End Entity Certificates:\n");
1175 fprintf(out, "\n");
1176 }
1177 while (iterator->iterate(iterator, (void**)&cert))
1178 {
1179 fprintf(out, "%#Q", cert, msg->list.utc);
1180 if (charon->credentials->has_rsa_private_key(
1181 charon->credentials, cert->get_public_key(cert)))
1182 {
1183 fprintf(out, ", has private key");
1184 }
1185 fprintf(out, "\n");
1186
1187 }
1188 iterator->destroy(iterator);
1189 }
1190 if (msg->list.flags & LIST_CACERTS)
1191 {
1192 list_auth_certificates(this, AUTH_CA, "CA", msg->list.utc, out);
1193 }
1194 if (msg->list.flags & LIST_CAINFOS)
1195 {
1196 ca_info_t *ca_info;
1197
1198 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1199 if (iterator->get_count(iterator))
1200 {
1201 fprintf(out, "\n");
1202 fprintf(out, "List of X.509 CA Information Records:\n");
1203 fprintf(out, "\n");
1204 }
1205 while (iterator->iterate(iterator, (void**)&ca_info))
1206 {
1207 fprintf(out, "%#W", ca_info, msg->list.utc);
1208 }
1209 iterator->destroy(iterator);
1210 }
1211 if (msg->list.flags & LIST_CRLS)
1212 {
1213 ca_info_t *ca_info;
1214 bool first = TRUE;
1215
1216 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1217 while (iterator->iterate(iterator, (void **)&ca_info))
1218 {
1219 if (ca_info->has_crl(ca_info))
1220 {
1221 if (first)
1222 {
1223 fprintf(out, "\n");
1224 fprintf(out, "List of X.509 CRLs:\n");
1225 fprintf(out, "\n");
1226 first = FALSE;
1227 }
1228 ca_info->list_crl(ca_info, out, msg->list.utc);
1229 }
1230 }
1231 iterator->destroy(iterator);
1232 }
1233 if (msg->list.flags & LIST_OCSPCERTS)
1234 {
1235 list_auth_certificates(this, AUTH_OCSP, "OCSP", msg->list.utc, out);
1236 }
1237 if (msg->list.flags & LIST_OCSP)
1238 {
1239 ca_info_t *ca_info;
1240 bool first = TRUE;
1241
1242 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1243 while (iterator->iterate(iterator, (void **)&ca_info))
1244 {
1245 if (ca_info->has_certinfos(ca_info))
1246 {
1247 if (first)
1248 {
1249 fprintf(out, "\n");
1250 fprintf(out, "List of OCSP responses:\n");
1251 first = FALSE;
1252 }
1253 fprintf(out, "\n");
1254 ca_info->list_certinfos(ca_info, out, msg->list.utc);
1255 }
1256 }
1257 iterator->destroy(iterator);
1258 }
1259 }
1260
1261 /**
1262 * reread various information
1263 */
1264 static void stroke_reread(private_stroke_interface_t *this,
1265 stroke_msg_t *msg, FILE *out)
1266 {
1267 if (msg->reread.flags & REREAD_CACERTS)
1268 {
1269 charon->credentials->load_ca_certificates(charon->credentials);
1270 }
1271 if (msg->reread.flags & REREAD_OCSPCERTS)
1272 {
1273 charon->credentials->load_ocsp_certificates(charon->credentials);
1274 }
1275 if (msg->reread.flags & REREAD_CRLS)
1276 {
1277 charon->credentials->load_crls(charon->credentials);
1278 }
1279 }
1280
1281 /**
1282 * purge various information
1283 */
1284 static void stroke_purge(private_stroke_interface_t *this,
1285 stroke_msg_t *msg, FILE *out)
1286 {
1287 if (msg->purge.flags & PURGE_OCSP)
1288 {
1289 iterator_t *iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1290 ca_info_t *ca_info;
1291
1292 while (iterator->iterate(iterator, (void**)&ca_info))
1293 {
1294 ca_info->purge_ocsp(ca_info);
1295 }
1296 iterator->destroy(iterator);
1297 }
1298 }
1299
1300 signal_t get_signal_from_logtype(char *type)
1301 {
1302 if (strcasecmp(type, "any") == 0) return SIG_ANY;
1303 else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
1304 else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
1305 else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
1306 else if (strcasecmp(type, "job") == 0) return DBG_JOB;
1307 else if (strcasecmp(type, "cfg") == 0) return DBG_CFG;
1308 else if (strcasecmp(type, "knl") == 0) return DBG_KNL;
1309 else if (strcasecmp(type, "net") == 0) return DBG_NET;
1310 else if (strcasecmp(type, "enc") == 0) return DBG_ENC;
1311 else if (strcasecmp(type, "lib") == 0) return DBG_LIB;
1312 else return -1;
1313 }
1314
1315 /**
1316 * set the verbosity debug output
1317 */
1318 static void stroke_loglevel(private_stroke_interface_t *this,
1319 stroke_msg_t *msg, FILE *out)
1320 {
1321 signal_t signal;
1322
1323 pop_string(msg, &(msg->loglevel.type));
1324 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
1325 msg->loglevel.level, msg->loglevel.type);
1326
1327 signal = get_signal_from_logtype(msg->loglevel.type);
1328 if (signal < 0)
1329 {
1330 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
1331 return;
1332 }
1333
1334 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
1335 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
1336 }
1337
1338 /**
1339 * process a stroke request from the socket pointed by "fd"
1340 */
1341 static void stroke_process(private_stroke_interface_t *this, int strokefd)
1342 {
1343 stroke_msg_t *msg;
1344 u_int16_t msg_length;
1345 ssize_t bytes_read;
1346 FILE *out;
1347
1348 /* peek the length */
1349 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
1350 if (bytes_read != sizeof(msg_length))
1351 {
1352 DBG1(DBG_CFG, "reading length of stroke message failed");
1353 close(strokefd);
1354 return;
1355 }
1356
1357 /* read message */
1358 msg = malloc(msg_length);
1359 bytes_read = recv(strokefd, msg, msg_length, 0);
1360 if (bytes_read != msg_length)
1361 {
1362 DBG1(DBG_CFG, "reading stroke message failed: %m");
1363 close(strokefd);
1364 return;
1365 }
1366
1367 out = fdopen(dup(strokefd), "w");
1368 if (out == NULL)
1369 {
1370 DBG1(DBG_CFG, "opening stroke output channel failed: %m");
1371 close(strokefd);
1372 free(msg);
1373 return;
1374 }
1375
1376 DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
1377
1378 switch (msg->type)
1379 {
1380 case STR_INITIATE:
1381 stroke_initiate(this, msg, out);
1382 break;
1383 case STR_ROUTE:
1384 stroke_route(this, msg, out, TRUE);
1385 break;
1386 case STR_UNROUTE:
1387 stroke_route(this, msg, out, FALSE);
1388 break;
1389 case STR_TERMINATE:
1390 stroke_terminate(this, msg, out);
1391 break;
1392 case STR_STATUS:
1393 stroke_status(this, msg, out);
1394 break;
1395 case STR_STATUS_ALL:
1396 stroke_statusall(this, msg, out);
1397 break;
1398 case STR_ADD_CONN:
1399 stroke_add_conn(this, msg, out);
1400 break;
1401 case STR_DEL_CONN:
1402 stroke_del_conn(this, msg, out);
1403 break;
1404 case STR_ADD_CA:
1405 stroke_add_ca(this, msg, out);
1406 break;
1407 case STR_DEL_CA:
1408 stroke_del_ca(this, msg, out);
1409 break;
1410 case STR_LOGLEVEL:
1411 stroke_loglevel(this, msg, out);
1412 break;
1413 case STR_LIST:
1414 stroke_list(this, msg, out);
1415 break;
1416 case STR_REREAD:
1417 stroke_reread(this, msg, out);
1418 break;
1419 case STR_PURGE:
1420 stroke_purge(this, msg, out);
1421 break;
1422 default:
1423 DBG1(DBG_CFG, "received unknown stroke");
1424 }
1425 fclose(out);
1426 close(strokefd);
1427 free(msg);
1428 }
1429
1430 /**
1431 * Implementation of private_stroke_interface_t.stroke_receive.
1432 */
1433 static void stroke_receive(private_stroke_interface_t *this)
1434 {
1435 struct sockaddr_un strokeaddr;
1436 int strokeaddrlen = sizeof(strokeaddr);
1437 int oldstate;
1438 int strokefd;
1439
1440 /* ignore sigpipe. writing over the pipe back to the console
1441 * only fails if SIGPIPE is ignored. */
1442 signal(SIGPIPE, SIG_IGN);
1443
1444 /* disable cancellation by default */
1445 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1446
1447 while (TRUE)
1448 {
1449 /* wait for connections, but allow thread to terminate */
1450 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
1451 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
1452 pthread_setcancelstate(oldstate, NULL);
1453
1454 if (strokefd < 0)
1455 {
1456 DBG1(DBG_CFG, "accepting stroke connection failed: %m");
1457 continue;
1458 }
1459 stroke_process(this, strokefd);
1460 }
1461 }
1462
1463 /**
1464 * Implementation of stroke_t.destroy.
1465 */
1466 static void destroy(private_stroke_interface_t *this)
1467 {
1468 int i;
1469
1470 for (i = 0; i < STROKE_THREADS; i++)
1471 {
1472 pthread_cancel(this->threads[i]);
1473 pthread_join(this->threads[i], NULL);
1474 }
1475
1476 close(this->socket);
1477 unlink(socket_addr.sun_path);
1478 free(this);
1479 }
1480
1481 /*
1482 * Described in header-file
1483 */
1484 stroke_t *stroke_create(local_backend_t *backend)
1485 {
1486 private_stroke_interface_t *this = malloc_thing(private_stroke_interface_t);
1487 mode_t old;
1488 int i;
1489
1490 /* public functions */
1491 this->public.destroy = (void (*)(stroke_t*))destroy;
1492
1493 this->backend = backend;
1494
1495 /* set up unix socket */
1496 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
1497 if (this->socket == -1)
1498 {
1499 DBG1(DBG_CFG, "could not create whack socket");
1500 free(this);
1501 return NULL;
1502 }
1503
1504 old = umask(~S_IRWXU);
1505 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
1506 {
1507 DBG1(DBG_CFG, "could not bind stroke socket: %m");
1508 close(this->socket);
1509 free(this);
1510 return NULL;
1511 }
1512 umask(old);
1513
1514 if (listen(this->socket, 0) < 0)
1515 {
1516 DBG1(DBG_CFG, "could not listen on stroke socket: %m");
1517 close(this->socket);
1518 unlink(socket_addr.sun_path);
1519 free(this);
1520 return NULL;
1521 }
1522
1523 /* start threads reading from the socket */
1524 for (i = 0; i < STROKE_THREADS; i++)
1525 {
1526 if (pthread_create(&this->threads[i], NULL, (void*(*)(void*))stroke_receive, this) != 0)
1527 {
1528 charon->kill(charon, "unable to create stroke thread");
1529 }
1530 }
1531
1532 return (&this->public);
1533 }