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