removed list_crls() and list_ocsp() methods
[strongswan.git] / src / charon / threads / stroke_interface.c
1 /**
2 * @file stroke.c
3 *
4 * @brief Implementation of stroke_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 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 <queues/jobs/initiate_job.h>
44 #include <queues/jobs/route_job.h>
45 #include <utils/leak_detective.h>
46
47 #define IKE_PORT 500
48 #define PATH_BUF 256
49
50
51 struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
52
53
54 typedef struct private_stroke_t private_stroke_t;
55
56 /**
57 * Private data of an stroke_t object.
58 */
59 struct private_stroke_t {
60
61 /**
62 * Public part of stroke_t object.
63 */
64 stroke_t public;
65
66 /**
67 * Output stream (stroke console)
68 */
69 FILE *out;
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 assigned_thread;
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(stroke_msg_t *msg, FILE *out)
191 {
192 connection_t *connection;
193 policy_t *policy;
194 identification_t *my_id, *other_id;
195 identification_t *my_ca = NULL;
196 identification_t *other_ca = NULL;
197 bool my_ca_same = FALSE;
198 bool other_ca_same =FALSE;
199 host_t *my_host, *other_host, *my_subnet, *other_subnet;
200 host_t *my_vip = NULL, *other_vip = NULL;
201 proposal_t *proposal;
202 traffic_selector_t *my_ts, *other_ts;
203 char *interface;
204
205 pop_string(msg, &msg->add_conn.name);
206 pop_string(msg, &msg->add_conn.me.address);
207 pop_string(msg, &msg->add_conn.other.address);
208 pop_string(msg, &msg->add_conn.me.subnet);
209 pop_string(msg, &msg->add_conn.other.subnet);
210 pop_string(msg, &msg->add_conn.me.sourceip);
211 pop_string(msg, &msg->add_conn.other.sourceip);
212 pop_string(msg, &msg->add_conn.me.id);
213 pop_string(msg, &msg->add_conn.other.id);
214 pop_string(msg, &msg->add_conn.me.cert);
215 pop_string(msg, &msg->add_conn.other.cert);
216 pop_string(msg, &msg->add_conn.me.ca);
217 pop_string(msg, &msg->add_conn.other.ca);
218 pop_string(msg, &msg->add_conn.me.updown);
219 pop_string(msg, &msg->add_conn.other.updown);
220 pop_string(msg, &msg->add_conn.algorithms.ike);
221 pop_string(msg, &msg->add_conn.algorithms.esp);
222
223 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
224
225 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
226 DBG2(DBG_CFG, " left=%s", msg->add_conn.me.address);
227 DBG2(DBG_CFG, " right=%s", msg->add_conn.other.address);
228 DBG2(DBG_CFG, " leftsubnet=%s", msg->add_conn.me.subnet);
229 DBG2(DBG_CFG, " rightsubnet=%s", msg->add_conn.other.subnet);
230 DBG2(DBG_CFG, " leftsourceip=%s", msg->add_conn.me.sourceip);
231 DBG2(DBG_CFG, " rightsourceip=%s", msg->add_conn.other.sourceip);
232 DBG2(DBG_CFG, " leftid=%s", msg->add_conn.me.id);
233 DBG2(DBG_CFG, " rightid=%s", msg->add_conn.other.id);
234 DBG2(DBG_CFG, " leftcert=%s", msg->add_conn.me.cert);
235 DBG2(DBG_CFG, " rightcert=%s", msg->add_conn.other.cert);
236 DBG2(DBG_CFG, " leftca=%s", msg->add_conn.me.ca);
237 DBG2(DBG_CFG, " rightca=%s", msg->add_conn.other.ca);
238 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
239 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
240
241 my_host = msg->add_conn.me.address?
242 host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL;
243 if (my_host == NULL)
244 {
245 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.me.address);
246 return;
247 }
248
249 other_host = msg->add_conn.other.address ?
250 host_create_from_string(msg->add_conn.other.address, IKE_PORT) : NULL;
251 if (other_host == NULL)
252 {
253 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.other.address);
254 my_host->destroy(my_host);
255 return;
256 }
257
258 interface = charon->kernel_interface->get_interface(charon->kernel_interface,
259 other_host);
260 if (interface)
261 {
262 stroke_end_t tmp_end;
263 host_t *tmp_host;
264
265 DBG2(DBG_CFG, "left is other host, swapping ends\n");
266
267 tmp_host = my_host;
268 my_host = other_host;
269 other_host = tmp_host;
270
271 tmp_end = msg->add_conn.me;
272 msg->add_conn.me = msg->add_conn.other;
273 msg->add_conn.other = tmp_end;
274 free(interface);
275 }
276 if (!interface)
277 {
278 interface = charon->kernel_interface->get_interface(
279 charon->kernel_interface, my_host);
280 if (!interface)
281 {
282 DBG1(DBG_CFG, "left nor right host is our side, aborting\n");
283 goto destroy_hosts;
284 }
285 free(interface);
286 }
287
288 my_id = identification_create_from_string(msg->add_conn.me.id ?
289 msg->add_conn.me.id : msg->add_conn.me.address);
290 if (my_id == NULL)
291 {
292 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
293 goto destroy_hosts;
294 }
295
296 other_id = identification_create_from_string(msg->add_conn.other.id ?
297 msg->add_conn.other.id : msg->add_conn.other.address);
298 if (other_id == NULL)
299 {
300 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
301 my_id->destroy(my_id);
302 goto destroy_hosts;
303 }
304
305 my_subnet = host_create_from_string(msg->add_conn.me.subnet ?
306 msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT);
307 if (my_subnet == NULL)
308 {
309 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
310 goto destroy_ids;
311 }
312
313 other_subnet = host_create_from_string(msg->add_conn.other.subnet ?
314 msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT);
315 if (other_subnet == NULL)
316 {
317 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
318 my_subnet->destroy(my_subnet);
319 goto destroy_ids;
320 }
321
322 if (msg->add_conn.me.virtual_ip)
323 {
324 my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
325 }
326 other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
327
328 if (msg->add_conn.me.tohost)
329 {
330 my_ts = traffic_selector_create_dynamic(msg->add_conn.me.protocol,
331 my_host->get_family(my_host) == AF_INET ?
332 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
333 msg->add_conn.me.port ? msg->add_conn.me.port : 0,
334 msg->add_conn.me.port ? msg->add_conn.me.port : 65535);
335 }
336 else
337 {
338 my_ts = traffic_selector_create_from_subnet(my_subnet,
339 msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0,
340 msg->add_conn.me.protocol, msg->add_conn.me.port);
341 }
342 my_subnet->destroy(my_subnet);
343
344 if (msg->add_conn.other.tohost)
345 {
346 other_ts = traffic_selector_create_dynamic(msg->add_conn.other.protocol,
347 other_host->get_family(other_host) == AF_INET ?
348 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
349 msg->add_conn.other.port ? msg->add_conn.other.port : 0,
350 msg->add_conn.other.port ? msg->add_conn.other.port : 65535);
351 }
352 else
353 {
354 other_ts = traffic_selector_create_from_subnet(other_subnet,
355 msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0,
356 msg->add_conn.other.protocol, msg->add_conn.other.port);
357 }
358 other_subnet->destroy(other_subnet);
359
360 if (msg->add_conn.me.ca)
361 {
362 if (streq(msg->add_conn.me.ca, "%same"))
363 {
364 my_ca_same = TRUE;
365 }
366 else
367 {
368 my_ca = identification_create_from_string(msg->add_conn.me.ca);
369 }
370 }
371 if (msg->add_conn.other.ca)
372 {
373 if (streq(msg->add_conn.other.ca, "%same"))
374 {
375 other_ca_same = TRUE;
376 }
377 else
378 {
379 other_ca = identification_create_from_string(msg->add_conn.other.ca);
380 }
381 }
382 if (msg->add_conn.me.cert)
383 {
384 x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id);
385
386 if (my_ca == NULL && !my_ca_same && cert)
387 {
388 identification_t *issuer = cert->get_issuer(cert);
389
390 my_ca = issuer->clone(issuer);
391 }
392 }
393 if (msg->add_conn.other.cert)
394 {
395 x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id);
396
397 if (other_ca == NULL && !other_ca_same && cert)
398 {
399 identification_t *issuer = cert->get_issuer(cert);
400
401 other_ca = issuer->clone(issuer);
402 }
403 }
404 if (other_ca_same && my_ca)
405 {
406 other_ca = my_ca->clone(my_ca);
407 }
408 else if (my_ca_same && other_ca)
409 {
410 my_ca = other_ca->clone(other_ca);
411 }
412 if (my_ca == NULL)
413 {
414 my_ca = identification_create_from_string("%any");
415 }
416 if (other_ca == NULL)
417 {
418 other_ca = identification_create_from_string("%any");
419 }
420 DBG2(DBG_CFG, " my ca: '%D'", my_ca);
421 DBG2(DBG_CFG, " other ca:'%D'", other_ca);
422 DBG2(DBG_CFG, " updown: '%s'", msg->add_conn.me.updown);
423
424 connection = connection_create(msg->add_conn.name,
425 msg->add_conn.ikev2,
426 msg->add_conn.me.sendcert,
427 msg->add_conn.other.sendcert,
428 my_host, other_host,
429 msg->add_conn.dpd.delay,
430 msg->add_conn.rekey.reauth,
431 msg->add_conn.rekey.tries,
432 msg->add_conn.rekey.ike_lifetime,
433 msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
434 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
435
436 if (msg->add_conn.algorithms.ike)
437 {
438 char *proposal_string;
439 char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
440
441 if (*strict == '!')
442 *strict = '\0';
443 else
444 strict = NULL;
445
446 while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
447 {
448 proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
449 if (proposal == NULL)
450 {
451 DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
452 my_id->destroy(my_id);
453 other_id->destroy(other_id);
454 my_ts->destroy(my_ts);
455 other_ts->destroy(other_ts);
456 my_ca->destroy(my_ca);
457 other_ca->destroy(other_ca);
458 connection->destroy(connection);
459 return;
460 }
461 connection->add_proposal(connection, proposal);
462 }
463 if (!strict)
464 {
465 proposal = proposal_create_default(PROTO_IKE);
466 connection->add_proposal(connection, proposal);
467 }
468 }
469 else
470 {
471 proposal = proposal_create_default(PROTO_IKE);
472 connection->add_proposal(connection, proposal);
473 }
474
475 policy = policy_create(msg->add_conn.name, my_id, other_id, my_vip, other_vip,
476 msg->add_conn.auth_method, msg->add_conn.eap_type,
477 msg->add_conn.rekey.ipsec_lifetime,
478 msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
479 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
480 msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
481 msg->add_conn.mode, msg->add_conn.dpd.action);
482 policy->add_my_traffic_selector(policy, my_ts);
483 policy->add_other_traffic_selector(policy, other_ts);
484 policy->add_authorities(policy, my_ca, other_ca);
485
486 if (msg->add_conn.algorithms.esp)
487 {
488 char *proposal_string;
489 char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
490
491 if (*strict == '!')
492 *strict = '\0';
493 else
494 strict = NULL;
495
496 while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
497 {
498 proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
499 if (proposal == NULL)
500 {
501 DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
502 policy->destroy(policy);
503 connection->destroy(connection);
504 return;
505 }
506 policy->add_proposal(policy, proposal);
507 }
508 if (!strict)
509 {
510 proposal = proposal_create_default(PROTO_ESP);
511 policy->add_proposal(policy, proposal);
512 }
513 }
514 else
515 {
516 proposal = proposal_create_default(PROTO_ESP);
517 policy->add_proposal(policy, proposal);
518 }
519
520 /* add to global connection list */
521 charon->connections->add_connection(charon->connections, connection);
522 DBG1(DBG_CFG, "added connection '%s': %H[%D]...%H[%D]",
523 msg->add_conn.name, my_host, my_id, other_host, other_id);
524 /* add to global policy list */
525 charon->policies->add_policy(charon->policies, policy);
526
527 return;
528
529 /* mopping up after parsing errors */
530
531 destroy_ids:
532 my_id->destroy(my_id);
533 other_id->destroy(other_id);
534
535 destroy_hosts:
536 my_host->destroy(my_host);
537 other_host->destroy(other_host);
538 }
539
540 /**
541 * Delete a connection from the list
542 */
543 static void stroke_del_conn(stroke_msg_t *msg, FILE *out)
544 {
545 status_t status;
546
547 pop_string(msg, &(msg->del_conn.name));
548 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
549
550 status = charon->connections->delete_connection(charon->connections,
551 msg->del_conn.name);
552 charon->policies->delete_policy(charon->policies, msg->del_conn.name);
553 if (status == SUCCESS)
554 {
555 fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
556 }
557 else
558 {
559 fprintf(out, "no connection named '%s'\n", msg->del_conn.name);
560 }
561 }
562
563 /**
564 * initiate a connection by name
565 */
566 static void stroke_initiate(stroke_msg_t *msg, FILE *out)
567 {
568 initiate_job_t *job;
569 connection_t *connection;
570 policy_t *policy;
571 ike_sa_t *init_ike_sa = NULL;
572 signal_t signal;
573
574 pop_string(msg, &(msg->initiate.name));
575 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
576
577 connection = charon->connections->get_connection_by_name(charon->connections,
578 msg->initiate.name);
579 if (connection == NULL)
580 {
581 if (msg->output_verbosity >= 0)
582 {
583 fprintf(out, "no connection named '%s'\n", msg->initiate.name);
584 }
585 return;
586 }
587 if (!connection->is_ikev2(connection))
588 {
589 connection->destroy(connection);
590 return;
591 }
592
593 policy = charon->policies->get_policy_by_name(charon->policies,
594 msg->initiate.name);
595 if (policy == NULL)
596 {
597 if (msg->output_verbosity >= 0)
598 {
599 fprintf(out, "no policy named '%s'\n", msg->initiate.name);
600 }
601 connection->destroy(connection);
602 return;
603 }
604
605 job = initiate_job_create(connection, policy);
606 charon->bus->set_listen_state(charon->bus, TRUE);
607 charon->job_queue->add(charon->job_queue, (job_t*)job);
608 while (TRUE)
609 {
610 level_t level;
611 int thread;
612 ike_sa_t *ike_sa;
613 char* format;
614 va_list args;
615
616 signal = charon->bus->listen(charon->bus, &level, &thread, &ike_sa, &format, &args);
617
618 if ((init_ike_sa == NULL || ike_sa == init_ike_sa) &&
619 level <= msg->output_verbosity)
620 {
621 if (vfprintf(out, format, args) < 0 ||
622 fprintf(out, "\n") < 0 ||
623 fflush(out))
624 {
625 charon->bus->set_listen_state(charon->bus, FALSE);
626 break;
627 }
628 }
629
630 switch (signal)
631 {
632 case CHILD_UP_SUCCESS:
633 case CHILD_UP_FAILED:
634 case IKE_UP_FAILED:
635 if (ike_sa == init_ike_sa)
636 {
637 charon->bus->set_listen_state(charon->bus, FALSE);
638 return;
639 }
640 continue;
641 case CHILD_UP_START:
642 case IKE_UP_START:
643 if (init_ike_sa == NULL)
644 {
645 init_ike_sa = ike_sa;
646 }
647 continue;
648 default:
649 continue;
650 }
651 }
652 }
653
654 /**
655 * route/unroute a policy (install SPD entries)
656 */
657 static void stroke_route(stroke_msg_t *msg, FILE *out, bool route)
658 {
659 route_job_t *job;
660 connection_t *connection;
661 policy_t *policy;
662
663 pop_string(msg, &(msg->route.name));
664 DBG1(DBG_CFG, "received stroke: %s '%s'",
665 route ? "route" : "unroute", msg->route.name);
666
667 /* we wouldn't need a connection, but we only want to route policies
668 * whose connections are keyexchange=ikev2. */
669 connection = charon->connections->get_connection_by_name(charon->connections,
670 msg->route.name);
671 if (connection == NULL)
672 {
673 fprintf(out, "no connection named '%s'\n", msg->route.name);
674 return;
675 }
676 if (!connection->is_ikev2(connection))
677 {
678 connection->destroy(connection);
679 return;
680 }
681
682 policy = charon->policies->get_policy_by_name(charon->policies,
683 msg->route.name);
684 if (policy == NULL)
685 {
686 fprintf(out, "no policy named '%s'\n", msg->route.name);
687 connection->destroy(connection);
688 return;
689 }
690 fprintf(out, "%s policy '%s'\n",
691 route ? "routing" : "unrouting", msg->route.name);
692 job = route_job_create(connection, policy, route);
693 charon->job_queue->add(charon->job_queue, (job_t*)job);
694 }
695
696 /**
697 * terminate a connection by name
698 */
699 static void stroke_terminate(stroke_msg_t *msg, FILE *out)
700 {
701 char *string, *pos = NULL, *name = NULL;
702 u_int32_t id = 0;
703 bool child;
704 int len;
705 status_t status = SUCCESS;;
706 ike_sa_t *ike_sa;
707
708 pop_string(msg, &(msg->terminate.name));
709 string = msg->terminate.name;
710 DBG1(DBG_CFG, "received stroke: terminate '%s'", string);
711
712 len = strlen(string);
713 if (len < 1)
714 {
715 DBG1(DBG_CFG, "error parsing string");
716 return;
717 }
718 switch (string[len-1])
719 {
720 case '}':
721 child = TRUE;
722 pos = strchr(string, '{');
723 break;
724 case ']':
725 child = FALSE;
726 pos = strchr(string, '[');
727 break;
728 default:
729 name = string;
730 child = FALSE;
731 break;
732 }
733
734 if (name)
735 { /* must be a single name */
736 DBG1(DBG_CFG, "check out by single name '%s'", name);
737 ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager,
738 name, child);
739 }
740 else if (pos == string + len - 2)
741 { /* must be name[] or name{} */
742 string[len-2] = '\0';
743 DBG1(DBG_CFG, "check out by name '%s'", string);
744 ike_sa = charon->ike_sa_manager->checkout_by_name(charon->ike_sa_manager,
745 string, child);
746 }
747 else
748 { /* must be name[123] or name{23} */
749 string[len-1] = '\0';
750 id = atoi(pos + 1);
751 if (id == 0)
752 {
753 DBG1(DBG_CFG, "error parsing string");
754 return;
755 }
756 DBG1(DBG_CFG, "check out by id '%d'", id);
757 ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
758 id, child);
759 }
760 if (ike_sa == NULL)
761 {
762 DBG1(DBG_CFG, "no such IKE_SA found");
763 return;
764 }
765
766 if (!child)
767 {
768 status = ike_sa->delete(ike_sa);
769 }
770 else
771 {
772 child_sa_t *child_sa;
773 iterator_t *iterator = ike_sa->create_child_sa_iterator(ike_sa);
774 while (iterator->iterate(iterator, (void**)&child_sa))
775 {
776 if ((id && id == child_sa->get_reqid(child_sa)) ||
777 (string && streq(string, child_sa->get_name(child_sa))))
778 {
779 u_int32_t spi = child_sa->get_spi(child_sa, TRUE);
780 protocol_id_t proto = child_sa->get_protocol(child_sa);
781
782 status = ike_sa->delete_child_sa(ike_sa, proto, spi);
783 break;
784 }
785 }
786 iterator->destroy(iterator);
787 }
788 if (status == DESTROY_ME)
789 {
790 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
791 ike_sa);
792 return;
793 }
794 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
795 }
796
797 /**
798 * Add a ca information record to the cainfo list
799 */
800 static void stroke_add_ca(stroke_msg_t *msg, FILE *out)
801 {
802 x509_t *cacert;
803 ca_info_t *ca_info;
804
805 pop_string(msg, &msg->add_ca.name);
806 pop_string(msg, &msg->add_ca.cacert);
807 pop_string(msg, &msg->add_ca.crluri);
808 pop_string(msg, &msg->add_ca.crluri2);
809 pop_string(msg, &msg->add_ca.ocspuri);
810 pop_string(msg, &msg->add_ca.ocspuri2);
811
812 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
813
814 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
815 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
816 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
817 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
818 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
819 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
820
821 if (msg->add_ca.cacert == NULL)
822 {
823 DBG1(DBG_CFG, "missing cacert parameter\n");
824 return;
825 }
826
827 cacert = load_ca_certificate(msg->add_ca.cacert);
828
829 if (cacert == NULL)
830 {
831 return;
832 }
833 ca_info = ca_info_create(msg->add_ca.name, cacert);
834
835 if (msg->add_ca.crluri)
836 {
837 chunk_t uri = { msg->add_ca.crluri, strlen(msg->add_ca.crluri) };
838
839 ca_info->add_crluri(ca_info, uri);
840 }
841 if (msg->add_ca.crluri2)
842 {
843 chunk_t uri = { msg->add_ca.crluri2, strlen(msg->add_ca.crluri2) };
844
845 ca_info->add_crluri(ca_info, uri);
846 }
847 if (msg->add_ca.ocspuri)
848 {
849 chunk_t uri = { msg->add_ca.ocspuri, strlen(msg->add_ca.ocspuri) };
850
851 ca_info->add_ocspuri(ca_info, uri);
852 }
853 if (msg->add_ca.ocspuri2)
854 {
855 chunk_t uri = { msg->add_ca.ocspuri2, strlen(msg->add_ca.ocspuri2) };
856
857 ca_info->add_ocspuri(ca_info, uri);
858 }
859 charon->credentials->add_ca_info(charon->credentials, ca_info);
860 DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
861
862 }
863
864 /**
865 * Delete a ca information record from the cainfo list
866 */
867 static void stroke_del_ca(stroke_msg_t *msg, FILE *out)
868 {
869 status_t status;
870
871 pop_string(msg, &(msg->del_ca.name));
872 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
873
874 status = charon->credentials->release_ca_info(charon->credentials,
875 msg->del_ca.name);
876
877 if (status == SUCCESS)
878 {
879 fprintf(out, "deleted ca '%s'\n", msg->del_ca.name);
880 }
881 else
882 {
883 fprintf(out, "no ca named '%s'\n", msg->del_ca.name);
884 }
885 }
886
887 /**
888 * show status of daemon
889 */
890 static void stroke_statusall(stroke_msg_t *msg, FILE *out)
891 {
892 iterator_t *iterator;
893 linked_list_t *list;
894 host_t *host;
895 connection_t *connection;
896 policy_t *policy;
897 ike_sa_t *ike_sa;
898 char *name = NULL;
899
900 leak_detective_status(out);
901
902 fprintf(out, "Performance:\n");
903 fprintf(out, " worker threads: %d idle of %d,",
904 charon->thread_pool->get_idle_threads(charon->thread_pool),
905 charon->thread_pool->get_pool_size(charon->thread_pool));
906 fprintf(out, " job queue load: %d,",
907 charon->job_queue->get_count(charon->job_queue));
908 fprintf(out, " scheduled events: %d\n",
909 charon->event_queue->get_count(charon->event_queue));
910 list = charon->kernel_interface->create_address_list(charon->kernel_interface);
911
912 fprintf(out, "Listening on %d IP addresses:\n", list->get_count(list));
913 while (list->remove_first(list, (void**)&host) == SUCCESS)
914 {
915 fprintf(out, " %H\n", host);
916 host->destroy(host);
917 }
918 list->destroy(list);
919
920 if (msg->status.name)
921 {
922 pop_string(msg, &(msg->status.name));
923 name = msg->status.name;
924 }
925
926 iterator = charon->connections->create_iterator(charon->connections);
927 if (iterator->get_count(iterator) > 0)
928 {
929 fprintf(out, "Connections:\n");
930 }
931 while (iterator->iterate(iterator, (void**)&connection))
932 {
933 if (connection->is_ikev2(connection)
934 && (name == NULL || streq(name, connection->get_name(connection))))
935 {
936 fprintf(out, "%12s: %H...%H\n",
937 connection->get_name(connection),
938 connection->get_my_host(connection),
939 connection->get_other_host(connection));
940 }
941 }
942 iterator->destroy(iterator);
943
944 iterator = charon->policies->create_iterator(charon->policies);
945 if (iterator->get_count(iterator) > 0)
946 {
947 fprintf(out, "Policies:\n");
948 }
949 while (iterator->iterate(iterator, (void**)&policy))
950 {
951 if (name == NULL || streq(name, policy->get_name(policy)))
952 {
953 fprintf(out, "%12s: '%D'...'%D'\n",
954 policy->get_name(policy),
955 policy->get_my_id(policy),
956 policy->get_other_id(policy));
957 }
958 }
959 iterator->destroy(iterator);
960
961 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
962 if (iterator->get_count(iterator) > 0)
963 {
964 fprintf(out, "Security Associations:\n");
965 }
966 while (iterator->iterate(iterator, (void**)&ike_sa))
967 {
968 bool ike_sa_printed = FALSE;
969 child_sa_t *child_sa;
970 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
971
972 /* print IKE_SA */
973 if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
974 {
975 fprintf(out, "%#K\n", ike_sa);
976 ike_sa_printed = TRUE;
977 }
978
979 while (children->iterate(children, (void**)&child_sa))
980 {
981 bool child_sa_match = name == NULL ||
982 strncmp(name, child_sa->get_name(child_sa), strlen(name)) == 0;
983
984 /* print IKE_SA if its name differs from the CHILD_SA's name */
985 if (!ike_sa_printed && child_sa_match)
986 {
987 fprintf(out, "%#K\n", ike_sa);
988 ike_sa_printed = TRUE;
989 }
990
991 /* print CHILD_SA */
992 if (child_sa_match)
993 {
994 fprintf(out, "%#P\n", child_sa);
995 }
996 }
997 children->destroy(children);
998 }
999 iterator->destroy(iterator);
1000 }
1001
1002 /**
1003 * show status of daemon
1004 */
1005 static void stroke_status(stroke_msg_t *msg, FILE *out)
1006 {
1007 iterator_t *iterator;
1008 ike_sa_t *ike_sa;
1009 char *name = NULL;
1010
1011 if (msg->status.name)
1012 {
1013 pop_string(msg, &(msg->status.name));
1014 name = msg->status.name;
1015 }
1016
1017 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
1018 while (iterator->iterate(iterator, (void**)&ike_sa))
1019 {
1020 bool ike_sa_printed = FALSE;
1021 child_sa_t *child_sa;
1022 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
1023
1024 /* print IKE_SA */
1025 if (name == NULL || strncmp(name, ike_sa->get_name(ike_sa), strlen(name)) == 0)
1026 {
1027 fprintf(out, "%K\n", ike_sa);
1028 ike_sa_printed = TRUE;
1029 }
1030
1031 while (children->iterate(children, (void**)&child_sa))
1032 {
1033 bool child_sa_match = name == NULL ||
1034 strncmp(name, child_sa->get_name(child_sa), strlen(name)) == 0;
1035
1036 /* print IKE_SA if its name differs from the CHILD_SA's name */
1037 if (!ike_sa_printed && child_sa_match)
1038 {
1039 fprintf(out, "%K\n", ike_sa);
1040 ike_sa_printed = TRUE;
1041 }
1042
1043 /* print CHILD_SA */
1044 if (child_sa_match)
1045 {
1046 fprintf(out, "%P\n", child_sa);
1047 }
1048 }
1049 children->destroy(children);
1050 }
1051 iterator->destroy(iterator);
1052 }
1053
1054 /**
1055 * list all authority certificates matching a specified flag
1056 */
1057 static void list_auth_certificates(u_int flag, const char *label, bool utc, FILE *out)
1058 {
1059 bool first = TRUE;
1060 x509_t *cert;
1061
1062 iterator_t *iterator = charon->credentials->create_auth_cert_iterator(charon->credentials);
1063
1064 while (iterator->iterate(iterator, (void**)&cert))
1065 {
1066 if (cert->has_authority_flag(cert, flag))
1067 {
1068 if (first)
1069 {
1070 fprintf(out, "\n");
1071 fprintf(out, "List of X.509 %s Certificates:\n", label);
1072 fprintf(out, "\n");
1073 first = FALSE;
1074 }
1075 fprintf(out, "%#Q\n", cert, utc);
1076 }
1077 }
1078 iterator->destroy(iterator);
1079 }
1080
1081 /**
1082 * list various information
1083 */
1084 static void stroke_list(stroke_msg_t *msg, FILE *out)
1085 {
1086 iterator_t *iterator;
1087
1088 if (msg->list.flags & LIST_CERTS)
1089 {
1090 x509_t *cert;
1091
1092 iterator = charon->credentials->create_cert_iterator(charon->credentials);
1093 if (iterator->get_count(iterator))
1094 {
1095 fprintf(out, "\n");
1096 fprintf(out, "List of X.509 End Entity Certificates:\n");
1097 fprintf(out, "\n");
1098 }
1099 while (iterator->iterate(iterator, (void**)&cert))
1100 {
1101 fprintf(out, "%#Q", cert, msg->list.utc);
1102 if (charon->credentials->has_rsa_private_key(
1103 charon->credentials, cert->get_public_key(cert)))
1104 {
1105 fprintf(out, ", has private key");
1106 }
1107 fprintf(out, "\n");
1108
1109 }
1110 iterator->destroy(iterator);
1111 }
1112 if (msg->list.flags & LIST_CACERTS)
1113 {
1114 list_auth_certificates(AUTH_CA, "CA", msg->list.utc, out);
1115 }
1116 if (msg->list.flags & LIST_CAINFOS)
1117 {
1118 ca_info_t *ca_info;
1119
1120 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1121 if (iterator->get_count(iterator))
1122 {
1123 fprintf(out, "\n");
1124 fprintf(out, "List of X.509 CA Information Records:\n");
1125 fprintf(out, "\n");
1126 }
1127 while (iterator->iterate(iterator, (void**)&ca_info))
1128 {
1129 fprintf(out, "%#W", ca_info, msg->list.utc);
1130 }
1131 iterator->destroy(iterator);
1132 }
1133 if (msg->list.flags & LIST_CRLS)
1134 {
1135 ca_info_t *ca_info;
1136 bool first = TRUE;
1137
1138 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1139
1140 while (iterator->iterate(iterator, (void **)&ca_info))
1141 {
1142 if (ca_info->has_crl(ca_info))
1143 {
1144 if (first)
1145 {
1146 fprintf(out, "\n");
1147 fprintf(out, "List of X.509 CRLs:\n");
1148 fprintf(out, "\n");
1149 first = FALSE;
1150 }
1151 ca_info->list_crl(ca_info, out, msg->list.utc);
1152 }
1153 }
1154 iterator->destroy(iterator);
1155 }
1156 if (msg->list.flags & LIST_OCSPCERTS)
1157 {
1158 list_auth_certificates(AUTH_OCSP, "OCSP", msg->list.utc, out);
1159 }
1160 if (msg->list.flags & LIST_OCSP)
1161 {
1162 ca_info_t *ca_info;
1163 bool first = TRUE;
1164
1165 iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1166
1167 while (iterator->iterate(iterator, (void **)&ca_info))
1168 {
1169 if (ca_info->has_certinfos(ca_info))
1170 {
1171 if (first)
1172 {
1173 fprintf(out, "\n");
1174 fprintf(out, "List of OCSP responses:\n");
1175 first = FALSE;
1176 }
1177 fprintf(out, "\n");
1178 ca_info->list_certinfos(ca_info, out, msg->list.utc);
1179 }
1180 }
1181 iterator->destroy(iterator);
1182 }
1183 }
1184
1185 /**
1186 * reread various information
1187 */
1188 static void stroke_reread(stroke_msg_t *msg, FILE *out)
1189 {
1190 if (msg->reread.flags & REREAD_CACERTS)
1191 {
1192 charon->credentials->load_ca_certificates(charon->credentials);
1193 }
1194 if (msg->reread.flags & REREAD_OCSPCERTS)
1195 {
1196 charon->credentials->load_ocsp_certificates(charon->credentials);
1197 }
1198 if (msg->reread.flags & REREAD_CRLS)
1199 {
1200 charon->credentials->load_crls(charon->credentials);
1201 }
1202 }
1203
1204 /**
1205 * purge various information
1206 */
1207 static void stroke_purge(stroke_msg_t *msg, FILE *out)
1208 {
1209 if (msg->purge.flags & PURGE_OCSP)
1210 {
1211 iterator_t *iterator = charon->credentials->create_cainfo_iterator(charon->credentials);
1212 ca_info_t *ca_info;
1213
1214 while (iterator->iterate(iterator, (void**)&ca_info))
1215 {
1216 ca_info->purge_ocsp(ca_info);
1217 }
1218 iterator->destroy(iterator);
1219 }
1220 }
1221
1222 signal_t get_signal_from_logtype(char *type)
1223 {
1224 if (strcasecmp(type, "any") == 0) return SIG_ANY;
1225 else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
1226 else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
1227 else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
1228 else if (strcasecmp(type, "job") == 0) return DBG_JOB;
1229 else if (strcasecmp(type, "cfg") == 0) return DBG_CFG;
1230 else if (strcasecmp(type, "knl") == 0) return DBG_KNL;
1231 else if (strcasecmp(type, "net") == 0) return DBG_NET;
1232 else if (strcasecmp(type, "enc") == 0) return DBG_ENC;
1233 else if (strcasecmp(type, "lib") == 0) return DBG_LIB;
1234 else return -1;
1235 }
1236
1237 /**
1238 * set the verbosity debug output
1239 */
1240 static void stroke_loglevel(stroke_msg_t *msg, FILE *out)
1241 {
1242 signal_t signal;
1243
1244 pop_string(msg, &(msg->loglevel.type));
1245 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
1246 msg->loglevel.level, msg->loglevel.type);
1247
1248 signal = get_signal_from_logtype(msg->loglevel.type);
1249 if (signal < 0)
1250 {
1251 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
1252 return;
1253 }
1254
1255 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
1256 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
1257 }
1258
1259 /**
1260 * process a stroke request from the socket pointed by "fd"
1261 */
1262 static void stroke_process(int *fd)
1263 {
1264 stroke_msg_t *msg;
1265 u_int16_t msg_length;
1266 ssize_t bytes_read;
1267 FILE *out;
1268 int strokefd = *fd;
1269
1270 /* peek the length */
1271 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
1272 if (bytes_read != sizeof(msg_length))
1273 {
1274 DBG1(DBG_CFG, "reading length of stroke message failed");
1275 close(strokefd);
1276 return;
1277 }
1278
1279 /* read message */
1280 msg = malloc(msg_length);
1281 bytes_read = recv(strokefd, msg, msg_length, 0);
1282 if (bytes_read != msg_length)
1283 {
1284 DBG1(DBG_CFG, "reading stroke message failed: %m");
1285 close(strokefd);
1286 return;
1287 }
1288
1289 out = fdopen(dup(strokefd), "w");
1290 if (out == NULL)
1291 {
1292 DBG1(DBG_CFG, "opening stroke output channel failed: %m");
1293 close(strokefd);
1294 free(msg);
1295 return;
1296 }
1297
1298 DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
1299
1300 switch (msg->type)
1301 {
1302 case STR_INITIATE:
1303 stroke_initiate(msg, out);
1304 break;
1305 case STR_ROUTE:
1306 stroke_route(msg, out, TRUE);
1307 break;
1308 case STR_UNROUTE:
1309 stroke_route(msg, out, FALSE);
1310 break;
1311 case STR_TERMINATE:
1312 stroke_terminate(msg, out);
1313 break;
1314 case STR_STATUS:
1315 stroke_status(msg, out);
1316 break;
1317 case STR_STATUS_ALL:
1318 stroke_statusall(msg, out);
1319 break;
1320 case STR_ADD_CONN:
1321 stroke_add_conn(msg, out);
1322 break;
1323 case STR_DEL_CONN:
1324 stroke_del_conn(msg, out);
1325 break;
1326 case STR_ADD_CA:
1327 stroke_add_ca(msg, out);
1328 break;
1329 case STR_DEL_CA:
1330 stroke_del_ca(msg, out);
1331 break;
1332 case STR_LOGLEVEL:
1333 stroke_loglevel(msg, out);
1334 break;
1335 case STR_LIST:
1336 stroke_list(msg, out);
1337 break;
1338 case STR_REREAD:
1339 stroke_reread(msg, out);
1340 break;
1341 case STR_PURGE:
1342 stroke_purge(msg, out);
1343 break;
1344 default:
1345 DBG1(DBG_CFG, "received unknown stroke");
1346 }
1347 fclose(out);
1348 close(strokefd);
1349 free(msg);
1350 }
1351
1352 /**
1353 * Implementation of private_stroke_t.stroke_receive.
1354 */
1355 static void stroke_receive(private_stroke_t *this)
1356 {
1357 struct sockaddr_un strokeaddr;
1358 int strokeaddrlen = sizeof(strokeaddr);
1359 int strokefd;
1360 int oldstate;
1361 pthread_t thread;
1362
1363 /* ignore sigpipe. writing over the pipe back to the console
1364 * only fails if SIGPIPE is ignored. */
1365 signal(SIGPIPE, SIG_IGN);
1366
1367 /* disable cancellation by default */
1368 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1369
1370 while (TRUE)
1371 {
1372 /* wait for connections, but allow thread to terminate */
1373 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
1374 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
1375 pthread_setcancelstate(oldstate, NULL);
1376
1377 if (strokefd < 0)
1378 {
1379 DBG1(DBG_CFG, "accepting stroke connection failed: %m");
1380 continue;
1381 }
1382
1383 /* handle request asynchronously */
1384 if (pthread_create(&thread, NULL, (void*(*)(void*))stroke_process, (void*)&strokefd) != 0)
1385 {
1386 DBG1(DBG_CFG, "failed to spawn stroke thread: %m");
1387 }
1388 /* detach so the thread terminates cleanly */
1389 pthread_detach(thread);
1390 }
1391 }
1392
1393 /**
1394 * Implementation of stroke_t.destroy.
1395 */
1396 static void destroy(private_stroke_t *this)
1397 {
1398 pthread_cancel(this->assigned_thread);
1399 pthread_join(this->assigned_thread, NULL);
1400
1401 close(this->socket);
1402 unlink(socket_addr.sun_path);
1403 free(this);
1404 }
1405
1406 /*
1407 * Described in header-file
1408 */
1409 stroke_t *stroke_create()
1410 {
1411 private_stroke_t *this = malloc_thing(private_stroke_t);
1412 mode_t old;
1413
1414 /* public functions */
1415 this->public.destroy = (void (*)(stroke_t*))destroy;
1416
1417 /* set up unix socket */
1418 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
1419 if (this->socket == -1)
1420 {
1421 DBG1(DBG_CFG, "could not create whack socket");
1422 free(this);
1423 return NULL;
1424 }
1425
1426 old = umask(~S_IRWXU);
1427 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
1428 {
1429 DBG1(DBG_CFG, "could not bind stroke socket: %m");
1430 close(this->socket);
1431 free(this);
1432 return NULL;
1433 }
1434 umask(old);
1435
1436 if (listen(this->socket, 0) < 0)
1437 {
1438 DBG1(DBG_CFG, "could not listen on stroke socket: %m");
1439 close(this->socket);
1440 unlink(socket_addr.sun_path);
1441 free(this);
1442 return NULL;
1443 }
1444
1445 /* start a thread reading from the socket */
1446 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))stroke_receive, this) != 0)
1447 {
1448 DBG1(DBG_CFG, "could not spawn stroke thread");
1449 close(this->socket);
1450 unlink(socket_addr.sun_path);
1451 free(this);
1452 return NULL;
1453 }
1454
1455 return (&this->public);
1456 }