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