62d71dd9568fd4469689f4dedab90b7638595d46
[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(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(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
182
183 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
184 DBG2(DBG_CFG, " right=%s", msg->add_conn.me.address);
185 DBG2(DBG_CFG, " left=%s", msg->add_conn.other.address);
186 DBG2(DBG_CFG, " rightsubnet=%s", msg->add_conn.me.subnet);
187 DBG2(DBG_CFG, " leftsubnet=%s", msg->add_conn.other.subnet);
188 DBG2(DBG_CFG, " rightid=%s", msg->add_conn.me.id);
189 DBG2(DBG_CFG, " leftid=%s", msg->add_conn.other.id);
190 DBG2(DBG_CFG, " rightcert=%s", msg->add_conn.me.cert);
191 DBG2(DBG_CFG, " leftcert=%s", msg->add_conn.other.cert);
192 DBG2(DBG_CFG, " rightca=%s", msg->add_conn.me.ca);
193 DBG2(DBG_CFG, " leftca=%s", msg->add_conn.other.ca);
194 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
195 DBG2(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(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(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(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(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(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(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(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(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(DBG_CFG, " my ca: '%D'", my_ca);
340 DBG2(DBG_CFG, " other ca:'%D'", other_ca);
341 DBG2(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(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(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(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(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(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
523 job = initiate_job_create(connection, policy);
524
525 charon->bus->set_listen_state(charon->bus, TRUE);
526 charon->job_queue->add(charon->job_queue, (job_t*)job);
527 while (TRUE)
528 {
529 level_t level;
530 int thread;
531 ike_sa_t *ike_sa;
532 char* format;
533 va_list args;
534
535 signal = charon->bus->listen(charon->bus, &level, &thread, &ike_sa, &format, &args);
536
537 if ((init_ike_sa == NULL || ike_sa == init_ike_sa) &&
538 level <= msg->output_verbosity)
539 {
540 if (vfprintf(this->out, format, args) < 0 ||
541 fprintf(this->out, "\n") < 0 ||
542 fflush(this->out))
543 {
544 break;
545 }
546 }
547
548 /* TODO: Handle INVALID_KE_PAYLOAD signal (ike_sa switch) */
549 switch (signal)
550 {
551 case CHILD_UP_SUCCESS:
552 case CHILD_UP_FAILED:
553 if (ike_sa == init_ike_sa)
554 {
555 charon->bus->set_listen_state(charon->bus, FALSE);
556 return;
557 }
558 continue;
559 case CHILD_UP_START:
560 case IKE_UP_START:
561 if (init_ike_sa == NULL)
562 {
563 init_ike_sa = ike_sa;
564 }
565 continue;
566 default:
567 continue;
568 }
569 }
570 }
571
572 /**
573 * route/unroute a policy (install SPD entries)
574 */
575 static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, bool route)
576 {
577 route_job_t *job;
578 connection_t *connection;
579 policy_t *policy;
580
581 pop_string(msg, &(msg->route.name));
582 DBG1(DBG_CFG, "received stroke: %s '%s'",
583 route ? "route" : "unroute", msg->route.name);
584
585 /* we wouldn't need a connection, but we only want to route policies
586 * whose connections are keyexchange=ikev2. */
587 connection = charon->connections->get_connection_by_name(charon->connections,
588 msg->route.name);
589 if (connection == NULL)
590 {
591 fprintf(this->out, "no connection named '%s'\n", msg->route.name);
592 return;
593 }
594 if (!connection->is_ikev2(connection))
595 {
596 connection->destroy(connection);
597 return;
598 }
599
600 policy = charon->policies->get_policy_by_name(charon->policies,
601 msg->route.name);
602 if (policy == NULL)
603 {
604 fprintf(this->out, "no policy named '%s'\n", msg->route.name);
605 connection->destroy(connection);
606 return;
607 }
608 fprintf(this->out, "%s policy '%s'\n",
609 route ? "routing" : "unrouting", msg->route.name);
610 job = route_job_create(connection, policy, route);
611 charon->job_queue->add(charon->job_queue, (job_t*)job);
612 }
613
614 /**
615 * terminate a connection by name
616 */
617 static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
618 {
619 pop_string(msg, &(msg->terminate.name));
620 DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
621
622 charon->ike_sa_manager->delete_by_name(charon->ike_sa_manager, msg->terminate.name);
623 }
624
625 /**
626 * show status of daemon
627 */
628 static void stroke_statusall(private_stroke_t *this, stroke_msg_t *msg)
629 {
630 iterator_t *iterator;
631 linked_list_t *list;
632 host_t *host;
633 connection_t *connection;
634 policy_t *policy;
635 ike_sa_t *ike_sa;
636
637 leak_detective_status(this->out);
638
639 fprintf(this->out, "worker threads idle: %d of %d\n",
640 charon->thread_pool->get_idle_threads(charon->thread_pool),
641 charon->thread_pool->get_pool_size(charon->thread_pool));
642 fprintf(this->out, "job queue load: %d\n",
643 charon->job_queue->get_count(charon->job_queue));
644 fprintf(this->out, "scheduled events: %d\n",
645 charon->event_queue->get_count(charon->event_queue));
646 list = charon->socket->create_local_address_list(charon->socket);
647 fprintf(this->out, "listening on %d addresses:\n", list->get_count(list));
648 while (list->remove_first(list, (void**)&host) == SUCCESS)
649 {
650 fprintf(this->out, " %H\n", host);
651 host->destroy(host);
652 }
653 list->destroy(list);
654
655 if (msg->status.name)
656 {
657 pop_string(msg, &(msg->status.name));
658 }
659
660 fprintf(this->out, "connections:\n");
661 iterator = charon->connections->create_iterator(charon->connections);
662 while (iterator->iterate(iterator, (void**)&connection))
663 {
664 if (connection->is_ikev2(connection) && (msg->status.name == NULL ||
665 streq(msg->status.name, connection->get_name(connection))))
666 {
667 fprintf(this->out, "%10s: %H...%H\n",
668 connection->get_name(connection),
669 connection->get_my_host(connection),
670 connection->get_other_host(connection));
671 }
672 }
673 iterator->destroy(iterator);
674
675 fprintf(this->out, "policies:\n");
676 iterator = charon->policies->create_iterator(charon->policies);
677 while (iterator->iterate(iterator, (void**)&policy))
678 {
679 if (msg->status.name == NULL ||
680 streq(msg->status.name, policy->get_name(policy)))
681 {
682 fprintf(this->out, "%10s: %D...%D\n",
683 policy->get_name(policy),
684 policy->get_my_id(policy),
685 policy->get_other_id(policy));
686 }
687 }
688 iterator->destroy(iterator);
689
690 fprintf(this->out, "IKE_SAs:\n");
691 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
692 while (iterator->iterate(iterator, (void**)&ike_sa))
693 {
694 bool ike_sa_printed = FALSE;
695 child_sa_t *child_sa;
696 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
697 while (children->iterate(children, (void**)&child_sa))
698 {
699 if (!ike_sa_printed &&
700 (msg->status.name == NULL ||
701 streq(msg->status.name, child_sa->get_name(child_sa)) ||
702 streq(msg->status.name, ike_sa->get_name(ike_sa))))
703 {
704 fprintf(this->out, "%#K\n", ike_sa);
705 ike_sa_printed = TRUE;
706 }
707 if (ike_sa_printed)
708 {
709 fprintf(this->out, "%#P\n", child_sa);
710 }
711 }
712 children->destroy(children);
713 }
714 iterator->destroy(iterator);
715 }
716
717 /**
718 * show status of daemon
719 */
720 static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
721 {
722 iterator_t *iterator;
723 ike_sa_t *ike_sa;
724
725 if (msg->status.name)
726 {
727 pop_string(msg, &(msg->status.name));
728 }
729
730 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
731 while (iterator->iterate(iterator, (void**)&ike_sa))
732 {
733 bool ike_sa_printed = FALSE;
734 child_sa_t *child_sa;
735 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
736 while (children->iterate(children, (void**)&child_sa))
737 {
738 if (!ike_sa_printed &&
739 (msg->status.name == NULL ||
740 streq(msg->status.name, child_sa->get_name(child_sa)) ||
741 streq(msg->status.name, ike_sa->get_name(ike_sa))))
742 {
743 fprintf(this->out, "%K\n", ike_sa);
744 ike_sa_printed = TRUE;
745 }
746 if (ike_sa_printed)
747 {
748 fprintf(this->out, "%P\n", child_sa);
749 }
750 }
751 children->destroy(children);
752 }
753 iterator->destroy(iterator);
754 }
755
756 /**
757 * list various information
758 */
759 static void stroke_list(private_stroke_t *this, stroke_msg_t *msg)
760 {
761 iterator_t *iterator;
762
763 if (msg->list.flags & LIST_CERTS)
764 {
765 x509_t *cert;
766
767 iterator = charon->credentials->create_cert_iterator(charon->credentials);
768 if (iterator->get_count(iterator))
769 {
770 fprintf(this->out, "\n");
771 fprintf(this->out, "List of X.509 End Entity Certificates:\n");
772 fprintf(this->out, "\n");
773 }
774 while (iterator->iterate(iterator, (void**)&cert))
775 {
776 fprintf(this->out, "%#Q", cert, msg->list.utc);
777 if (charon->credentials->has_rsa_private_key(
778 charon->credentials, cert->get_public_key(cert)))
779 {
780 fprintf(this->out, ", has private key");
781 }
782 fprintf(this->out, "\n");
783
784 }
785 iterator->destroy(iterator);
786 }
787 if (msg->list.flags & LIST_CACERTS)
788 {
789 x509_t *cert;
790
791 iterator = charon->credentials->create_cacert_iterator(charon->credentials);
792 if (iterator->get_count(iterator))
793 {
794 fprintf(this->out, "\n");
795 fprintf(this->out, "List of X.509 CA Certificates:\n");
796 fprintf(this->out, "\n");
797 }
798 while (iterator->iterate(iterator, (void**)&cert))
799 {
800 fprintf(this->out, "%#Q\n", cert, msg->list.utc);
801 }
802 iterator->destroy(iterator);
803 }
804 if (msg->list.flags & LIST_CRLS)
805 {
806 crl_t *crl;
807
808 iterator = charon->credentials->create_crl_iterator(charon->credentials);
809 if (iterator->get_count(iterator))
810 {
811 fprintf(this->out, "\n");
812 fprintf(this->out, "List of X.509 CRLs:\n");
813 fprintf(this->out, "\n");
814 }
815 while (iterator->iterate(iterator, (void**)&crl))
816 {
817 fprintf(this->out, "%#U\n", crl, msg->list.utc);
818 }
819 iterator->destroy(iterator);
820 }
821 }
822
823 /**
824 * reread various information
825 */
826 static void stroke_reread(private_stroke_t *this, stroke_msg_t *msg)
827 {
828 if (msg->reread.flags & REREAD_CACERTS)
829 {
830 charon->credentials->load_ca_certificates(charon->credentials);
831 }
832 if (msg->reread.flags & REREAD_CRLS)
833 {
834 charon->credentials->load_crls(charon->credentials);
835 }
836 }
837
838 signal_t get_signal_from_logtype(char *type)
839 {
840 if (strcasecmp(type, "any") == 0) return SIG_ANY;
841 else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
842 else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
843 else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
844 else if (strcasecmp(type, "job") == 0) return DBG_JOB;
845 else if (strcasecmp(type, "cfg") == 0) return DBG_CFG;
846 else if (strcasecmp(type, "knl") == 0) return DBG_KNL;
847 else if (strcasecmp(type, "net") == 0) return DBG_NET;
848 else if (strcasecmp(type, "enc") == 0) return DBG_ENC;
849 else if (strcasecmp(type, "lib") == 0) return DBG_LIB;
850 else return -1;
851 }
852
853 /**
854 * set the verbosity debug output
855 */
856 static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
857 {
858 signal_t signal;
859
860 pop_string(msg, &(msg->loglevel.type));
861 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
862 msg->loglevel.level, msg->loglevel.type);
863
864 signal = get_signal_from_logtype(msg->loglevel.type);
865 if (signal < 0)
866 {
867 fprintf(this->out, "invalid type (%s)!\n", msg->loglevel.type);
868 return;
869 }
870
871 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
872 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
873 }
874
875 /**
876 * Implementation of private_stroke_t.stroke_receive.
877 */
878 static void stroke_receive(private_stroke_t *this)
879 {
880 stroke_msg_t *msg;
881 u_int16_t msg_length;
882 struct sockaddr_un strokeaddr;
883 int strokeaddrlen = sizeof(strokeaddr);
884 ssize_t bytes_read;
885 int strokefd;
886 int oldstate;
887
888 /* disable cancellation by default */
889 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
890
891 while (1)
892 {
893 /* wait for connections, but allow thread to terminate */
894 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
895 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
896 pthread_setcancelstate(oldstate, NULL);
897
898 if (strokefd < 0)
899 {
900 DBG1(DBG_CFG, "accepting stroke connection failed: %m");
901 continue;
902 }
903
904 /* peek the length */
905 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
906 if (bytes_read != sizeof(msg_length))
907 {
908 DBG1(DBG_CFG, "reading lenght of stroke message failed");
909 close(strokefd);
910 continue;
911 }
912
913 /* read message */
914 msg = malloc(msg_length);
915 bytes_read = recv(strokefd, msg, msg_length, 0);
916 if (bytes_read != msg_length)
917 {
918 DBG1(DBG_CFG, "reading stroke message failed: %m");
919 close(strokefd);
920 continue;
921 }
922
923 this->out = fdopen(dup(strokefd), "w");
924 if (this->out == NULL)
925 {
926 DBG1(DBG_CFG, "opening stroke output channel failed: %m");
927 close(strokefd);
928 free(msg);
929 continue;
930 }
931
932 DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
933
934 switch (msg->type)
935 {
936 case STR_INITIATE:
937 stroke_initiate(this, msg);
938 break;
939 case STR_ROUTE:
940 stroke_route(this, msg, TRUE);
941 break;
942 case STR_UNROUTE:
943 stroke_route(this, msg, FALSE);
944 break;
945 case STR_TERMINATE:
946 stroke_terminate(this, msg);
947 break;
948 case STR_STATUS:
949 stroke_status(this, msg);
950 break;
951 case STR_STATUS_ALL:
952 stroke_statusall(this, msg);
953 break;
954 case STR_ADD_CONN:
955 stroke_add_conn(this, msg);
956 break;
957 case STR_DEL_CONN:
958 stroke_del_conn(this, msg);
959 break;
960 case STR_LOGLEVEL:
961 stroke_loglevel(this, msg);
962 break;
963 case STR_LIST:
964 stroke_list(this, msg);
965 break;
966 case STR_REREAD:
967 stroke_reread(this, msg);
968 break;
969 default:
970 DBG1(DBG_CFG, "received unknown stroke");
971 }
972 fclose(this->out);
973 close(strokefd);
974 free(msg);
975 }
976 }
977
978 /**
979 * Implementation of stroke_t.destroy.
980 */
981 static void destroy(private_stroke_t *this)
982 {
983 pthread_cancel(this->assigned_thread);
984 pthread_join(this->assigned_thread, NULL);
985
986 close(this->socket);
987 unlink(socket_addr.sun_path);
988 free(this);
989 }
990
991 /*
992 * Described in header-file
993 */
994 stroke_t *stroke_create()
995 {
996 private_stroke_t *this = malloc_thing(private_stroke_t);
997 mode_t old;
998
999 /* public functions */
1000 this->public.destroy = (void (*)(stroke_t*))destroy;
1001
1002 /* set up unix socket */
1003 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
1004 if (this->socket == -1)
1005 {
1006 DBG1(DBG_CFG, "could not create whack socket");
1007 free(this);
1008 return NULL;
1009 }
1010
1011 old = umask(~S_IRWXU);
1012 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
1013 {
1014 DBG1(DBG_CFG, "could not bind stroke socket: %m");
1015 close(this->socket);
1016 free(this);
1017 return NULL;
1018 }
1019 umask(old);
1020
1021 if (listen(this->socket, 0) < 0)
1022 {
1023 DBG1(DBG_CFG, "could not listen on stroke socket: %m");
1024 close(this->socket);
1025 unlink(socket_addr.sun_path);
1026 free(this);
1027 return NULL;
1028 }
1029
1030 /* start a thread reading from the socket */
1031 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))stroke_receive, this) != 0)
1032 {
1033 DBG1(DBG_CFG, "could not spawn stroke thread");
1034 close(this->socket);
1035 unlink(socket_addr.sun_path);
1036 free(this);
1037 return NULL;
1038 }
1039
1040 return (&this->public);
1041 }