redesigned list output format
[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
34 #include "stroke_interface.h"
35
36 #include <types.h>
37 #include <stroke.h>
38 #include <daemon.h>
39 #include <crypto/x509.h>
40 #include <crypto/crl.h>
41 #include <queues/jobs/initiate_job.h>
42 #include <queues/jobs/route_job.h>
43 #include <utils/leak_detective.h>
44
45 #define IKE_PORT 500
46 #define PATH_BUF 256
47
48
49 struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
50
51
52 typedef struct private_stroke_t private_stroke_t;
53
54 /**
55 * Private data of an stroke_t object.
56 */
57 struct private_stroke_t {
58
59 /**
60 * Public part of stroke_t object.
61 */
62 stroke_t public;
63
64 /**
65 * Output stream (stroke console)
66 */
67 FILE *out;
68
69 /**
70 * Unix socket to listen for strokes
71 */
72 int socket;
73
74 /**
75 * Thread which reads from the Socket
76 */
77 pthread_t assigned_thread;
78 };
79
80 /**
81 * Helper function which corrects the string pointers
82 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
83 * contains RELATIVE addresses (relative to the beginning of the
84 * stroke_msg). They must be corrected if they reach our address
85 * space...
86 */
87 static void pop_string(stroke_msg_t *msg, char **string)
88 {
89 if (*string == NULL)
90 return;
91
92 /* check for sanity of string pointer and string */
93 if (string < (char**)msg
94 || string > (char**)msg + sizeof(stroke_msg_t)
95 || (u_int)*string < (u_int)((char*)msg->buffer - (char*)msg)
96 || (u_int)*string > msg->length)
97 {
98 *string = "(invalid pointer in stroke msg)";
99 }
100 else
101 {
102 *string = (char*)msg + (u_int)*string;
103 }
104 }
105
106 /**
107 * Load end entitity certificate
108 */
109 static x509_t* load_end_certificate(const char *filename, identification_t **idp)
110 {
111 char path[PATH_BUF];
112 x509_t *cert;
113
114 if (*filename == '/')
115 {
116 /* absolute path name */
117 snprintf(path, sizeof(path), "%s", filename);
118 }
119 else
120 {
121 /* relative path name */
122 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
123 }
124
125 cert = x509_create_from_file(path, "end entity certificate");
126
127 if (cert)
128 {
129 identification_t *id = *idp;
130 identification_t *subject = cert->get_subject(cert);
131
132 err_t ugh = cert->is_valid(cert, NULL);
133
134 if (ugh != NULL)
135 {
136 DBG1(SIG_DBG_CFG, "warning: certificate %s", ugh);
137 }
138 if (!id->equals(id, subject) && !cert->equals_subjectAltName(cert, id))
139 {
140 id->destroy(id);
141 id = subject;
142 *idp = id->clone(id);
143 }
144 return charon->credentials->add_end_certificate(charon->credentials, cert);
145 }
146 return NULL;
147 }
148
149 /**
150 * Add a connection to the configuration list
151 */
152 static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
153 {
154 connection_t *connection;
155 policy_t *policy;
156 identification_t *my_id, *other_id;
157 identification_t *my_ca = NULL;
158 identification_t *other_ca = NULL;
159 bool my_ca_same = FALSE;
160 bool other_ca_same =FALSE;
161 host_t *my_host, *other_host, *my_subnet, *other_subnet;
162 proposal_t *proposal;
163 traffic_selector_t *my_ts, *other_ts;
164
165 pop_string(msg, &msg->add_conn.name);
166 pop_string(msg, &msg->add_conn.me.address);
167 pop_string(msg, &msg->add_conn.other.address);
168 pop_string(msg, &msg->add_conn.me.subnet);
169 pop_string(msg, &msg->add_conn.other.subnet);
170 pop_string(msg, &msg->add_conn.me.id);
171 pop_string(msg, &msg->add_conn.other.id);
172 pop_string(msg, &msg->add_conn.me.cert);
173 pop_string(msg, &msg->add_conn.other.cert);
174 pop_string(msg, &msg->add_conn.me.ca);
175 pop_string(msg, &msg->add_conn.other.ca);
176 pop_string(msg, &msg->add_conn.me.updown);
177 pop_string(msg, &msg->add_conn.other.updown);
178 pop_string(msg, &msg->add_conn.algorithms.ike);
179 pop_string(msg, &msg->add_conn.algorithms.esp);
180
181 DBG1(SIG_DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
182
183 DBG2(SIG_DBG_CFG, "conn %s", msg->add_conn.name);
184 DBG2(SIG_DBG_CFG, " right=%s", msg->add_conn.me.address);
185 DBG2(SIG_DBG_CFG, " left=%s", msg->add_conn.other.address);
186 DBG2(SIG_DBG_CFG, " rightsubnet=%s", msg->add_conn.me.subnet);
187 DBG2(SIG_DBG_CFG, " leftsubnet=%s", msg->add_conn.other.subnet);
188 DBG2(SIG_DBG_CFG, " rightid=%s", msg->add_conn.me.id);
189 DBG2(SIG_DBG_CFG, " leftid=%s", msg->add_conn.other.id);
190 DBG2(SIG_DBG_CFG, " rightcert=%s", msg->add_conn.me.cert);
191 DBG2(SIG_DBG_CFG, " leftcert=%s", msg->add_conn.other.cert);
192 DBG2(SIG_DBG_CFG, " rightca=%s", msg->add_conn.me.ca);
193 DBG2(SIG_DBG_CFG, " leftca=%s", msg->add_conn.other.ca);
194 DBG2(SIG_DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
195 DBG2(SIG_DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
196
197 my_host = msg->add_conn.me.address?
198 host_create_from_string(msg->add_conn.me.address, IKE_PORT) : NULL;
199 if (my_host == NULL)
200 {
201 DBG1(SIG_DBG_CFG, "invalid host: %s\n", msg->add_conn.me.address);
202 return;
203 }
204
205 other_host = msg->add_conn.other.address ?
206 host_create_from_string(msg->add_conn.other.address, IKE_PORT) : NULL;
207 if (other_host == NULL)
208 {
209 DBG1(SIG_DBG_CFG, "invalid host: %s\n", msg->add_conn.other.address);
210 my_host->destroy(my_host);
211 return;
212 }
213
214 if (charon->socket->is_local_address(charon->socket, other_host, NULL))
215 {
216 stroke_end_t tmp_end;
217 host_t *tmp_host;
218
219 DBG2(SIG_DBG_CFG, "left is other host, swapping ends\n");
220
221 tmp_host = my_host;
222 my_host = other_host;
223 other_host = tmp_host;
224
225 tmp_end = msg->add_conn.me;
226 msg->add_conn.me = msg->add_conn.other;
227 msg->add_conn.other = tmp_end;
228 }
229 else if (!charon->socket->is_local_address(charon->socket, my_host, NULL))
230 {
231 DBG1(SIG_DBG_CFG, "left nor right host is our side, aborting\n");
232 goto destroy_hosts;
233 }
234
235 my_id = identification_create_from_string(msg->add_conn.me.id ?
236 msg->add_conn.me.id : msg->add_conn.me.address);
237 if (my_id == NULL)
238 {
239 DBG1(SIG_DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
240 goto destroy_hosts;
241 }
242
243 other_id = identification_create_from_string(msg->add_conn.other.id ?
244 msg->add_conn.other.id : msg->add_conn.other.address);
245 if (other_id == NULL)
246 {
247 DBG1(SIG_DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
248 my_id->destroy(my_id);
249 goto destroy_hosts;
250 }
251
252 my_subnet = host_create_from_string(msg->add_conn.me.subnet ?
253 msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT);
254 if (my_subnet == NULL)
255 {
256 DBG1(SIG_DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
257 goto destroy_ids;
258 }
259
260 other_subnet = host_create_from_string(msg->add_conn.other.subnet ?
261 msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT);
262 if (other_subnet == NULL)
263 {
264 DBG1(SIG_DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
265 my_subnet->destroy(my_subnet);
266 goto destroy_ids;
267 }
268
269 my_ts = traffic_selector_create_from_subnet(my_subnet,
270 msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0,
271 msg->add_conn.me.protocol, msg->add_conn.me.port);
272 my_subnet->destroy(my_subnet);
273
274 other_ts = traffic_selector_create_from_subnet(other_subnet,
275 msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0,
276 msg->add_conn.other.protocol, msg->add_conn.other.port);
277 other_subnet->destroy(other_subnet);
278
279 if (msg->add_conn.me.ca)
280 {
281 if (streq(msg->add_conn.me.ca, "%same"))
282 {
283 my_ca_same = TRUE;
284 }
285 else
286 {
287 my_ca = identification_create_from_string(msg->add_conn.me.ca);
288 }
289 }
290 if (msg->add_conn.other.ca)
291 {
292 if (streq(msg->add_conn.other.ca, "%same"))
293 {
294 other_ca_same = TRUE;
295 }
296 else
297 {
298 other_ca = identification_create_from_string(msg->add_conn.other.ca);
299 }
300 }
301 if (msg->add_conn.me.cert)
302 {
303 x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id);
304
305 if (my_ca == NULL && !my_ca_same && cert)
306 {
307 identification_t *issuer = cert->get_issuer(cert);
308
309 my_ca = issuer->clone(issuer);
310 }
311 }
312 if (msg->add_conn.other.cert)
313 {
314 x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id);
315
316 if (other_ca == NULL && !other_ca_same && cert)
317 {
318 identification_t *issuer = cert->get_issuer(cert);
319
320 other_ca = issuer->clone(issuer);
321 }
322 }
323 if (other_ca_same && my_ca)
324 {
325 other_ca = my_ca->clone(my_ca);
326 }
327 else if (my_ca_same && other_ca)
328 {
329 my_ca = other_ca->clone(other_ca);
330 }
331 if (my_ca == NULL)
332 {
333 my_ca = identification_create_from_string("%any");
334 }
335 if (other_ca == NULL)
336 {
337 other_ca = identification_create_from_string("%any");
338 }
339 DBG2(SIG_DBG_CFG, " my ca: '%D'", my_ca);
340 DBG2(SIG_DBG_CFG, " other ca:'%D'", other_ca);
341 DBG2(SIG_DBG_CFG, " updown: '%s'", msg->add_conn.me.updown);
342
343 connection = connection_create(msg->add_conn.name,
344 msg->add_conn.ikev2,
345 msg->add_conn.me.sendcert,
346 msg->add_conn.other.sendcert,
347 my_host, other_host,
348 msg->add_conn.dpd.delay,
349 msg->add_conn.rekey.tries,
350 msg->add_conn.rekey.ike_lifetime,
351 msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
352 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
353
354 if (msg->add_conn.algorithms.ike)
355 {
356 char *proposal_string;
357 char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
358
359 if (*strict == '!')
360 *strict = '\0';
361 else
362 strict = NULL;
363
364 while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
365 {
366 proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
367 if (proposal == NULL)
368 {
369 DBG1(SIG_DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
370 my_id->destroy(my_id);
371 other_id->destroy(other_id);
372 my_ts->destroy(my_ts);
373 other_ts->destroy(other_ts);
374 my_ca->destroy(my_ca);
375 other_ca->destroy(other_ca);
376 connection->destroy(connection);
377 return;
378 }
379 connection->add_proposal(connection, proposal);
380 }
381 if (!strict)
382 {
383 proposal = proposal_create_default(PROTO_IKE);
384 connection->add_proposal(connection, proposal);
385 }
386 }
387 else
388 {
389 proposal = proposal_create_default(PROTO_IKE);
390 connection->add_proposal(connection, proposal);
391 }
392
393 policy = policy_create(msg->add_conn.name, my_id, other_id,
394 msg->add_conn.auth_method,
395 msg->add_conn.rekey.ipsec_lifetime,
396 msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
397 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
398 msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
399 msg->add_conn.dpd.action);
400 policy->add_my_traffic_selector(policy, my_ts);
401 policy->add_other_traffic_selector(policy, other_ts);
402 policy->add_authorities(policy, my_ca, other_ca);
403
404 if (msg->add_conn.algorithms.esp)
405 {
406 char *proposal_string;
407 char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
408
409 if (*strict == '!')
410 *strict = '\0';
411 else
412 strict = NULL;
413
414 while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
415 {
416 proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
417 if (proposal == NULL)
418 {
419 DBG1(SIG_DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
420 policy->destroy(policy);
421 connection->destroy(connection);
422 return;
423 }
424 policy->add_proposal(policy, proposal);
425 }
426 if (!strict)
427 {
428 proposal = proposal_create_default(PROTO_ESP);
429 policy->add_proposal(policy, proposal);
430 }
431 }
432 else
433 {
434 proposal = proposal_create_default(PROTO_ESP);
435 policy->add_proposal(policy, proposal);
436 }
437
438 /* add to global connection list */
439 charon->connections->add_connection(charon->connections, connection);
440 DBG1(SIG_DBG_CFG, "added connection '%s': %H[%D]...%H[%D]",
441 msg->add_conn.name, my_host, my_id, other_host, other_id);
442 /* add to global policy list */
443 charon->policies->add_policy(charon->policies, policy);
444
445 return;
446
447 /* mopping up after parsing errors */
448
449 destroy_ids:
450 my_id->destroy(my_id);
451 other_id->destroy(other_id);
452
453 destroy_hosts:
454 my_host->destroy(my_host);
455 other_host->destroy(other_host);
456 }
457
458 /**
459 * Delete a connection from the list
460 */
461 static void stroke_del_conn(private_stroke_t *this, stroke_msg_t *msg)
462 {
463 status_t status;
464
465 pop_string(msg, &(msg->del_conn.name));
466 DBG1(SIG_DBG_CFG, "received stroke: delete '%s'", msg->del_conn.name);
467
468 status = charon->connections->delete_connection(charon->connections,
469 msg->del_conn.name);
470 charon->policies->delete_policy(charon->policies, msg->del_conn.name);
471 if (status == SUCCESS)
472 {
473 fprintf(this->out, "deleted connection '%s'\n", msg->del_conn.name);
474 }
475 else
476 {
477 fprintf(this->out, "no connection named '%s'\n", msg->del_conn.name);
478 }
479 }
480
481 /**
482 * initiate a connection by name
483 */
484 static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
485 {
486 initiate_job_t *job;
487 connection_t *connection;
488 policy_t *policy;
489 ike_sa_t *init_ike_sa = NULL;
490 signal_t signal;
491
492 pop_string(msg, &(msg->initiate.name));
493 DBG1(SIG_DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
494
495 connection = charon->connections->get_connection_by_name(charon->connections,
496 msg->initiate.name);
497 if (connection == NULL)
498 {
499 if (msg->output_verbosity >= 0)
500 {
501 fprintf(this->out, "no connection named '%s'\n", msg->initiate.name);
502 }
503 return;
504 }
505 if (!connection->is_ikev2(connection))
506 {
507 connection->destroy(connection);
508 return;
509 }
510
511 policy = charon->policies->get_policy_by_name(charon->policies,
512 msg->initiate.name);
513 if (policy == NULL)
514 {
515 if (msg->output_verbosity >= 0)
516 {
517 fprintf(this->out, "no policy named '%s'\n", msg->initiate.name);
518 }
519 connection->destroy(connection);
520 return;
521 }
522 if (msg->output_verbosity >= 0)
523 {
524 fprintf(this->out, "initiating connection '%s'\n", msg->initiate.name);
525 }
526
527 job = initiate_job_create(connection, policy);
528
529 charon->bus->set_listen_state(charon->bus, TRUE);
530 charon->job_queue->add(charon->job_queue, (job_t*)job);
531 while (TRUE)
532 {
533 level_t level;
534 int thread;
535 ike_sa_t *ike_sa;
536 char* format;
537 va_list args;
538
539 signal = charon->bus->listen(charon->bus, &level, &thread, &ike_sa, &format, &args);
540
541 if ((init_ike_sa == NULL || ike_sa == init_ike_sa) &&
542 level <= msg->output_verbosity)
543 {
544 if (vfprintf(this->out, format, args) < 0 ||
545 fprintf(this->out, "\n") < 0 ||
546 fflush(this->out))
547 {
548 break;
549 }
550 }
551
552 /* TODO: Handle INVALID_KE_PAYLOAD signal (ike_sa switch) */
553 switch (signal)
554 {
555 case SIG_IKE_UP:
556 case SIG_IKE_FAILED:
557 case SIG_CHILD_UP:
558 case SIG_CHILD_FAILED:
559 if (ike_sa == init_ike_sa)
560 {
561 charon->bus->set_listen_state(charon->bus, FALSE);
562 return;
563 }
564 continue;
565 case SIG_INITIATE:
566 if (init_ike_sa == NULL)
567 {
568 init_ike_sa = ike_sa;
569 }
570 continue;
571 default:
572 continue;
573 }
574 }
575 }
576
577 /**
578 * route/unroute a policy (install SPD entries)
579 */
580 static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
581 {
582 route_job_t *job;
583 connection_t *connection;
584 policy_t *policy;
585
586 pop_string(msg, &(msg->route.name));
587 DBG1(SIG_DBG_CFG, "received stroke: %s '%s'",
588 route ? "route" : "unroute", msg->route.name);
589
590 /* we wouldn't need a connection, but we only want to route policies
591 * whose connections are keyexchange=ikev2. */
592 connection = charon->connections->get_connection_by_name(charon->connections,
593 msg->route.name);
594 if (connection == NULL)
595 {
596 fprintf(this->out, "no connection named '%s'\n", msg->route.name);
597 return;
598 }
599 if (!connection->is_ikev2(connection))
600 {
601 connection->destroy(connection);
602 return;
603 }
604
605 policy = charon->policies->get_policy_by_name(charon->policies,
606 msg->route.name);
607 if (policy == NULL)
608 {
609 fprintf(this->out, "no policy named '%s'\n", msg->route.name);
610 connection->destroy(connection);
611 return;
612 }
613 fprintf(this->out, "%s policy '%s'\n",
614 route ? "routing" : "unrouting", msg->route.name);
615 job = route_job_create(connection, policy, route);
616 charon->job_queue->add(charon->job_queue, (job_t*)job);
617 }
618
619 /**
620 * terminate a connection by name
621 */
622 static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
623 {
624 pop_string(msg, &(msg->terminate.name));
625 DBG1(SIG_DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
626
627 charon->ike_sa_manager->delete_by_name(charon->ike_sa_manager, msg->terminate.name);
628 }
629
630 /**
631 * show status of daemon
632 */
633 static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
634 {
635 iterator_t *iterator;
636 linked_list_t *list;
637 host_t *host;
638 connection_t *connection;
639 policy_t *policy;
640 ike_sa_t *ike_sa;
641
642 leak_detective_status(this->out);
643
644 fprintf(this->out, "worker threads idle: %d of %d\n",
645 charon->thread_pool->get_idle_threads(charon->thread_pool),
646 charon->thread_pool->get_pool_size(charon->thread_pool));
647 fprintf(this->out, "job queue load: %d\n",
648 charon->job_queue->get_count(charon->job_queue));
649 fprintf(this->out, "scheduled events: %d\n",
650 charon->event_queue->get_count(charon->event_queue));
651 list = charon->socket->create_local_address_list(charon->socket);
652 fprintf(this->out, "listening on %d addresses:\n", list->get_count(list));
653 while (list->remove_first(list, (void**)&host) == SUCCESS)
654 {
655 fprintf(this->out, " %H\n", host);
656 host->destroy(host);
657 }
658 list->destroy(list);
659
660 if (msg->status.name)
661 {
662 pop_string(msg, &(msg->status.name));
663 }
664
665 fprintf(this->out, "connections:\n");
666 iterator = charon->connections->create_iterator(charon->connections);
667 while (iterator->iterate(iterator, (void**)&connection))
668 {
669 if (connection->is_ikev2(connection) && (msg->status.name == NULL ||
670 streq(msg->status.name, connection->get_name(connection))))
671 {
672 fprintf(this->out, "%10s: %H...%H\n",
673 connection->get_name(connection),
674 connection->get_my_host(connection),
675 connection->get_other_host(connection));
676 }
677 }
678 iterator->destroy(iterator);
679
680 fprintf(this->out, "policies:\n");
681 iterator = charon->policies->create_iterator(charon->policies);
682 while (iterator->iterate(iterator, (void**)&policy))
683 {
684 if (msg->status.name == NULL ||
685 streq(msg->status.name, policy->get_name(policy)))
686 {
687 fprintf(this->out, "%10s: %D...%D\n",
688 policy->get_name(policy),
689 policy->get_my_id(policy),
690 policy->get_other_id(policy));
691 }
692 }
693 iterator->destroy(iterator);
694
695 fprintf(this->out, "IKE_SAs:\n");
696 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
697 while (iterator->iterate(iterator, (void**)&ike_sa))
698 {
699 bool ike_sa_printed = FALSE;
700 child_sa_t *child_sa;
701 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
702 while (children->iterate(children, (void**)&child_sa))
703 {
704 if (!ike_sa_printed &&
705 (msg->status.name == NULL ||
706 streq(msg->status.name, child_sa->get_name(child_sa)) ||
707 streq(msg->status.name, ike_sa->get_name(ike_sa))))
708 {
709 fprintf(this->out, "%#K\n", ike_sa);
710 ike_sa_printed = TRUE;
711 }
712 if (ike_sa_printed)
713 {
714 fprintf(this->out, "%#P\n", child_sa);
715 }
716 }
717 children->destroy(children);
718 }
719 iterator->destroy(iterator);
720 }
721
722 /**
723 * show status of daemon
724 */
725 static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
726 {
727 iterator_t *iterator;
728 ike_sa_t *ike_sa;
729
730 if (msg->status.name)
731 {
732 pop_string(msg, &(msg->status.name));
733 }
734
735 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
736 while (iterator->iterate(iterator, (void**)&ike_sa))
737 {
738 bool ike_sa_printed = FALSE;
739 child_sa_t *child_sa;
740 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
741 while (children->iterate(children, (void**)&child_sa))
742 {
743 if (!ike_sa_printed &&
744 (msg->status.name == NULL ||
745 streq(msg->status.name, child_sa->get_name(child_sa)) ||
746 streq(msg->status.name, ike_sa->get_name(ike_sa))))
747 {
748 fprintf(this->out, "%K\n", ike_sa);
749 ike_sa_printed = TRUE;
750 }
751 if (ike_sa_printed)
752 {
753 fprintf(this->out, "%P\n", child_sa);
754 }
755 }
756 children->destroy(children);
757 }
758 iterator->destroy(iterator);
759 }
760
761 /**
762 * list various information
763 */
764 static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
765 {
766 iterator_t *iterator;
767
768 if (msg->list.flags & LIST_CERTS)
769 {
770 x509_t *cert;
771
772 iterator = charon->credentials->create_cert_iterator(charon->credentials);
773 if (iterator->get_count(iterator))
774 {
775 fprintf(this->out, "\n");
776 fprintf(this->out, "List of X.509 End Entity Certificates:\n");
777 fprintf(this->out, "\n");
778 }
779 while (iterator->iterate(iterator, (void**)&cert))
780 {
781 fprintf(this->out, "%#Q", cert, msg->list.utc);
782 if (charon->credentials->has_rsa_private_key(
783 charon->credentials, cert->get_public_key(cert)))
784 {
785 fprintf(this->out, ", has private key");
786 }
787 fprintf(this->out, "\n");
788
789 }
790 iterator->destroy(iterator);
791 }
792 if (msg->list.flags & LIST_CACERTS)
793 {
794 x509_t *cert;
795
796 iterator = charon->credentials->create_cacert_iterator(charon->credentials);
797 if (iterator->get_count(iterator))
798 {
799 fprintf(this->out, "\n");
800 fprintf(this->out, "List of X.509 CA Certificates:\n");
801 fprintf(this->out, "\n");
802 }
803 while (iterator->iterate(iterator, (void**)&cert))
804 {
805 fprintf(this->out, "%#Q\n", cert, msg->list.utc);
806 }
807 iterator->destroy(iterator);
808 }
809 if (msg->list.flags & LIST_CRLS)
810 {
811 crl_t *crl;
812
813 iterator = charon->credentials->create_crl_iterator(charon->credentials);
814 if (iterator->get_count(iterator))
815 {
816 fprintf(this->out, "\n");
817 fprintf(this->out, "List of X.509 CRLs:\n");
818 fprintf(this->out, "\n");
819 }
820 while (iterator->iterate(iterator, (void**)&crl))
821 {
822 fprintf(this->out, "%#U\n", crl, msg->list.utc);
823 }
824 iterator->destroy(iterator);
825 }
826 }
827
828 /**
829 * reread various information
830 */
831 static void stroke_reread(private_stroke_t *this, stroke_msg_t *msg)
832 {
833 if (msg->reread.flags & REREAD_CACERTS)
834 {
835 charon->credentials->load_ca_certificates(charon->credentials);
836 }
837 if (msg->reread.flags & REREAD_CRLS)
838 {
839 charon->credentials->load_crls(charon->credentials);
840 }
841 }
842
843 signal_t get_signal_from_logtype(char *type)
844 {
845 if (strcasecmp(type, "any") == 0) return SIG_ANY;
846 else if (strcasecmp(type, "mgr") == 0) return SIG_DBG_MGR;
847 else if (strcasecmp(type, "ike") == 0) return SIG_DBG_IKE;
848 else if (strcasecmp(type, "chd") == 0) return SIG_DBG_CHD;
849 else if (strcasecmp(type, "job") == 0) return SIG_DBG_JOB;
850 else if (strcasecmp(type, "cfg") == 0) return SIG_DBG_CFG;
851 else if (strcasecmp(type, "knl") == 0) return SIG_DBG_KNL;
852 else if (strcasecmp(type, "net") == 0) return SIG_DBG_NET;
853 else if (strcasecmp(type, "enc") == 0) return SIG_DBG_ENC;
854 else if (strcasecmp(type, "lib") == 0) return SIG_DBG_LIB;
855 else return -1;
856 }
857
858 /**
859 * set the verbosity debug output
860 */
861 static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
862 {
863 signal_t signal;
864
865 pop_string(msg, &(msg->loglevel.type));
866 DBG1(SIG_DBG_CFG, "received stroke: loglevel %d for %s",
867 msg->loglevel.level, msg->loglevel.type);
868
869 signal = get_signal_from_logtype(msg->loglevel.type);
870 if (signal < 0)
871 {
872 fprintf(this->out, "invalid type (%s)!\n", msg->loglevel.type);
873 return;
874 }
875
876 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
877 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
878 }
879
880 /**
881 * Implementation of private_stroke_t.stroke_receive.
882 */
883 static void stroke_receive(private_stroke_t *this)
884 {
885 stroke_msg_t *msg;
886 u_int16_t msg_length;
887 struct sockaddr_un strokeaddr;
888 int strokeaddrlen = sizeof(strokeaddr);
889 ssize_t bytes_read;
890 int strokefd;
891 int oldstate;
892
893 /* disable cancellation by default */
894 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
895
896 while (1)
897 {
898 /* wait for connections, but allow thread to terminate */
899 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
900 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
901 pthread_setcancelstate(oldstate, NULL);
902
903 if (strokefd < 0)
904 {
905 DBG1(SIG_DBG_CFG, "accepting stroke connection failed: %m");
906 continue;
907 }
908
909 /* peek the length */
910 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
911 if (bytes_read != sizeof(msg_length))
912 {
913 DBG1(SIG_DBG_CFG, "reading lenght of stroke message failed");
914 close(strokefd);
915 continue;
916 }
917
918 /* read message */
919 msg = malloc(msg_length);
920 bytes_read = recv(strokefd, msg, msg_length, 0);
921 if (bytes_read != msg_length)
922 {
923 DBG1(SIG_DBG_CFG, "reading stroke message failed: %m");
924 close(strokefd);
925 continue;
926 }
927
928 this->out = fdopen(dup(strokefd), "w");
929 if (this->out == NULL)
930 {
931 DBG1(SIG_DBG_CFG, "opening stroke output channel failed: %m");
932 close(strokefd);
933 free(msg);
934 continue;
935 }
936
937 DBG3(SIG_DBG_CFG, "stroke message %b", (void*)msg, msg_length);
938
939 switch (msg->type)
940 {
941 case STR_INITIATE:
942 stroke_initiate(this, msg);
943 break;
944 case STR_ROUTE:
945 stroke_route(this, msg, TRUE);
946 break;
947 case STR_UNROUTE:
948 stroke_route(this, msg, FALSE);
949 break;
950 case STR_TERMINATE:
951 stroke_terminate(this, msg);
952 break;
953 case STR_STATUS:
954 stroke_status(this, msg);
955 break;
956 case STR_STATUS_ALL:
957 stroke_statusall(this, msg);
958 break;
959 case STR_ADD_CONN:
960 stroke_add_conn(this, msg);
961 break;
962 case STR_DEL_CONN:
963 stroke_del_conn(this, msg);
964 break;
965 case STR_LOGLEVEL:
966 stroke_loglevel(this, msg);
967 break;
968 case STR_LIST:
969 stroke_list(this, msg);
970 break;
971 case STR_REREAD:
972 stroke_reread(this, msg);
973 break;
974 default:
975 DBG1(SIG_DBG_CFG, "received unknown stroke");
976 }
977 fclose(this->out);
978 close(strokefd);
979 free(msg);
980 }
981 }
982
983 /**
984 * Implementation of stroke_t.destroy.
985 */
986 static void destroy(private_stroke_t *this)
987 {
988 pthread_cancel(this->assigned_thread);
989 pthread_join(this->assigned_thread, NULL);
990
991 close(this->socket);
992 unlink(socket_addr.sun_path);
993 free(this);
994 }
995
996 /*
997 * Described in header-file
998 */
999 stroke_t *stroke_create()
1000 {
1001 private_stroke_t *this = malloc_thing(private_stroke_t);
1002 mode_t old;
1003
1004 /* public functions */
1005 this->public.destroy = (void (*)(stroke_t*))destroy;
1006
1007 /* set up unix socket */
1008 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
1009 if (this->socket == -1)
1010 {
1011 DBG1(SIG_DBG_CFG, "could not create whack socket");
1012 free(this);
1013 return NULL;
1014 }
1015
1016 old = umask(~S_IRWXU);
1017 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
1018 {
1019 DBG1(SIG_DBG_CFG, "could not bind stroke socket: %m");
1020 close(this->socket);
1021 free(this);
1022 return NULL;
1023 }
1024 umask(old);
1025
1026 if (listen(this->socket, 0) < 0)
1027 {
1028 DBG1(SIG_DBG_CFG, "could not listen on stroke socket: %m");
1029 close(this->socket);
1030 unlink(socket_addr.sun_path);
1031 free(this);
1032 return NULL;
1033 }
1034
1035 /* start a thread reading from the socket */
1036 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))stroke_receive, this) != 0)
1037 {
1038 DBG1(SIG_DBG_CFG, "Could not spawn stroke thread");
1039 close(this->socket);
1040 unlink(socket_addr.sun_path);
1041 free(this);
1042 return NULL;
1043 }
1044
1045 return (&this->public);
1046 }