2 * @file stroke_interface.c
4 * @brief Implementation of stroke_interface_t.
9 * Copyright (C) 2006-2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
24 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/fcntl.h>
35 #include "stroke_interface.h"
40 #include <crypto/x509.h>
41 #include <crypto/ca.h>
42 #include <crypto/crl.h>
43 #include <processing/jobs/initiate_job.h>
44 #include <processing/jobs/route_job.h>
45 #include <utils/leak_detective.h>
49 #define STROKE_THREADS 3
51 struct sockaddr_un socket_addr
= { AF_UNIX
, STROKE_SOCKET
};
54 typedef struct private_stroke_interface_t private_stroke_interface_t
;
57 * Private data of an stroke_t object.
59 struct private_stroke_interface_t
{
62 * Public part of stroke_t object.
67 * backend to store configurations
69 local_backend_t
*backend
;
72 * Unix socket to listen for strokes
77 * Thread which reads from the Socket
79 pthread_t threads
[STROKE_THREADS
];
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
89 static void pop_string(stroke_msg_t
*msg
, char **string
)
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
)
100 *string
= "(invalid pointer in stroke msg)";
104 *string
= (char*)msg
+ (unsigned long)*string
;
109 * Load end entitity certificate
111 static x509_t
* load_end_certificate(const char *filename
, identification_t
**idp
)
116 if (*filename
== '/')
118 /* absolute path name */
119 snprintf(path
, sizeof(path
), "%s", filename
);
123 /* relative path name */
124 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
127 cert
= x509_create_from_file(path
, "end entity");
131 identification_t
*id
= *idp
;
132 identification_t
*subject
= cert
->get_subject(cert
);
134 err_t ugh
= cert
->is_valid(cert
, NULL
);
138 DBG1(DBG_CFG
, "warning: certificate %s", ugh
);
140 if (!id
->equals(id
, subject
) && !cert
->equals_subjectAltName(cert
, id
))
144 *idp
= id
->clone(id
);
146 return charon
->credentials
->add_end_certificate(charon
->credentials
, cert
);
152 * Load ca certificate
154 static x509_t
* load_ca_certificate(const char *filename
)
159 if (*filename
== '/')
161 /* absolute path name */
162 snprintf(path
, sizeof(path
), "%s", filename
);
166 /* relative path name */
167 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
170 cert
= x509_create_from_file(path
, "ca");
174 if (cert
->is_ca(cert
))
176 return charon
->credentials
->add_auth_certificate(charon
->credentials
, cert
, AUTH_CA
);
180 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
188 * Add a connection to the configuration list
190 static void stroke_add_conn(private_stroke_interface_t
*this,
191 stroke_msg_t
*msg
, FILE *out
)
194 peer_cfg_t
*peer_cfg
;
195 child_cfg_t
*child_cfg
;
196 identification_t
*my_id
, *other_id
;
197 identification_t
*my_ca
= NULL
;
198 identification_t
*other_ca
= NULL
;
199 bool my_ca_same
= FALSE
;
200 bool other_ca_same
=FALSE
;
201 host_t
*my_host
, *other_host
, *my_subnet
, *other_subnet
;
202 host_t
*my_vip
= NULL
, *other_vip
= NULL
;
203 proposal_t
*proposal
;
204 traffic_selector_t
*my_ts
, *other_ts
;
206 bool use_existing
= FALSE
;
207 iterator_t
*iterator
;
209 pop_string(msg
, &msg
->add_conn
.name
);
210 pop_string(msg
, &msg
->add_conn
.me
.address
);
211 pop_string(msg
, &msg
->add_conn
.other
.address
);
212 pop_string(msg
, &msg
->add_conn
.me
.subnet
);
213 pop_string(msg
, &msg
->add_conn
.other
.subnet
);
214 pop_string(msg
, &msg
->add_conn
.me
.sourceip
);
215 pop_string(msg
, &msg
->add_conn
.other
.sourceip
);
216 pop_string(msg
, &msg
->add_conn
.me
.id
);
217 pop_string(msg
, &msg
->add_conn
.other
.id
);
218 pop_string(msg
, &msg
->add_conn
.me
.cert
);
219 pop_string(msg
, &msg
->add_conn
.other
.cert
);
220 pop_string(msg
, &msg
->add_conn
.me
.ca
);
221 pop_string(msg
, &msg
->add_conn
.other
.ca
);
222 pop_string(msg
, &msg
->add_conn
.me
.updown
);
223 pop_string(msg
, &msg
->add_conn
.other
.updown
);
224 pop_string(msg
, &msg
->add_conn
.algorithms
.ike
);
225 pop_string(msg
, &msg
->add_conn
.algorithms
.esp
);
227 DBG1(DBG_CFG
, "received stroke: add connection '%s'", msg
->add_conn
.name
);
229 DBG2(DBG_CFG
, "conn %s", msg
->add_conn
.name
);
230 DBG2(DBG_CFG
, " left=%s", msg
->add_conn
.me
.address
);
231 DBG2(DBG_CFG
, " right=%s", msg
->add_conn
.other
.address
);
232 DBG2(DBG_CFG
, " leftsubnet=%s", msg
->add_conn
.me
.subnet
);
233 DBG2(DBG_CFG
, " rightsubnet=%s", msg
->add_conn
.other
.subnet
);
234 DBG2(DBG_CFG
, " leftsourceip=%s", msg
->add_conn
.me
.sourceip
);
235 DBG2(DBG_CFG
, " rightsourceip=%s", msg
->add_conn
.other
.sourceip
);
236 DBG2(DBG_CFG
, " leftid=%s", msg
->add_conn
.me
.id
);
237 DBG2(DBG_CFG
, " rightid=%s", msg
->add_conn
.other
.id
);
238 DBG2(DBG_CFG
, " leftcert=%s", msg
->add_conn
.me
.cert
);
239 DBG2(DBG_CFG
, " rightcert=%s", msg
->add_conn
.other
.cert
);
240 DBG2(DBG_CFG
, " leftca=%s", msg
->add_conn
.me
.ca
);
241 DBG2(DBG_CFG
, " rightca=%s", msg
->add_conn
.other
.ca
);
242 DBG2(DBG_CFG
, " ike=%s", msg
->add_conn
.algorithms
.ike
);
243 DBG2(DBG_CFG
, " esp=%s", msg
->add_conn
.algorithms
.esp
);
245 my_host
= msg
->add_conn
.me
.address
?
246 host_create_from_string(msg
->add_conn
.me
.address
, IKE_PORT
) : NULL
;
249 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.me
.address
);
253 other_host
= msg
->add_conn
.other
.address
?
254 host_create_from_string(msg
->add_conn
.other
.address
, IKE_PORT
) : NULL
;
255 if (other_host
== NULL
)
257 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.other
.address
);
258 my_host
->destroy(my_host
);
262 interface
= charon
->kernel_interface
->get_interface(charon
->kernel_interface
,
266 stroke_end_t tmp_end
;
269 DBG2(DBG_CFG
, "left is other host, swapping ends\n");
272 my_host
= other_host
;
273 other_host
= tmp_host
;
275 tmp_end
= msg
->add_conn
.me
;
276 msg
->add_conn
.me
= msg
->add_conn
.other
;
277 msg
->add_conn
.other
= tmp_end
;
282 interface
= charon
->kernel_interface
->get_interface(
283 charon
->kernel_interface
, my_host
);
286 DBG1(DBG_CFG
, "left nor right host is our side, aborting\n");
292 my_id
= identification_create_from_string(msg
->add_conn
.me
.id
?
293 msg
->add_conn
.me
.id
: msg
->add_conn
.me
.address
);
296 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.me
.id
);
300 other_id
= identification_create_from_string(msg
->add_conn
.other
.id
?
301 msg
->add_conn
.other
.id
: msg
->add_conn
.other
.address
);
302 if (other_id
== NULL
)
304 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.other
.id
);
305 my_id
->destroy(my_id
);
309 my_subnet
= host_create_from_string(msg
->add_conn
.me
.subnet
?
310 msg
->add_conn
.me
.subnet
: msg
->add_conn
.me
.address
, IKE_PORT
);
311 if (my_subnet
== NULL
)
313 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
317 other_subnet
= host_create_from_string(msg
->add_conn
.other
.subnet
?
318 msg
->add_conn
.other
.subnet
: msg
->add_conn
.other
.address
, IKE_PORT
);
319 if (other_subnet
== NULL
)
321 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
322 my_subnet
->destroy(my_subnet
);
326 if (msg
->add_conn
.me
.virtual_ip
)
328 my_vip
= host_create_from_string(msg
->add_conn
.me
.sourceip
, 0);
330 other_vip
= host_create_from_string(msg
->add_conn
.other
.sourceip
, 0);
332 if (msg
->add_conn
.me
.tohost
)
334 my_ts
= traffic_selector_create_dynamic(msg
->add_conn
.me
.protocol
,
335 my_host
->get_family(my_host
) == AF_INET
?
336 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
337 msg
->add_conn
.me
.port
? msg
->add_conn
.me
.port
: 0,
338 msg
->add_conn
.me
.port
? msg
->add_conn
.me
.port
: 65535);
342 my_ts
= traffic_selector_create_from_subnet(my_subnet
,
343 msg
->add_conn
.me
.subnet
? msg
->add_conn
.me
.subnet_mask
: 0,
344 msg
->add_conn
.me
.protocol
, msg
->add_conn
.me
.port
);
346 my_subnet
->destroy(my_subnet
);
348 if (msg
->add_conn
.other
.tohost
)
350 other_ts
= traffic_selector_create_dynamic(msg
->add_conn
.other
.protocol
,
351 other_host
->get_family(other_host
) == AF_INET
?
352 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
353 msg
->add_conn
.other
.port
? msg
->add_conn
.other
.port
: 0,
354 msg
->add_conn
.other
.port
? msg
->add_conn
.other
.port
: 65535);
358 other_ts
= traffic_selector_create_from_subnet(other_subnet
,
359 msg
->add_conn
.other
.subnet
? msg
->add_conn
.other
.subnet_mask
: 0,
360 msg
->add_conn
.other
.protocol
, msg
->add_conn
.other
.port
);
362 other_subnet
->destroy(other_subnet
);
364 if (msg
->add_conn
.me
.ca
)
366 if (streq(msg
->add_conn
.me
.ca
, "%same"))
372 my_ca
= identification_create_from_string(msg
->add_conn
.me
.ca
);
375 if (msg
->add_conn
.other
.ca
)
377 if (streq(msg
->add_conn
.other
.ca
, "%same"))
379 other_ca_same
= TRUE
;
383 other_ca
= identification_create_from_string(msg
->add_conn
.other
.ca
);
386 if (msg
->add_conn
.me
.cert
)
388 x509_t
*cert
= load_end_certificate(msg
->add_conn
.me
.cert
, &my_id
);
390 if (my_ca
== NULL
&& !my_ca_same
&& cert
)
392 identification_t
*issuer
= cert
->get_issuer(cert
);
394 my_ca
= issuer
->clone(issuer
);
397 if (msg
->add_conn
.other
.cert
)
399 x509_t
*cert
= load_end_certificate(msg
->add_conn
.other
.cert
, &other_id
);
401 if (other_ca
== NULL
&& !other_ca_same
&& cert
)
403 identification_t
*issuer
= cert
->get_issuer(cert
);
405 other_ca
= issuer
->clone(issuer
);
408 if (other_ca_same
&& my_ca
)
410 other_ca
= my_ca
->clone(my_ca
);
412 else if (my_ca_same
&& other_ca
)
414 my_ca
= other_ca
->clone(other_ca
);
418 my_ca
= identification_create_from_string("%any");
420 if (other_ca
== NULL
)
422 other_ca
= identification_create_from_string("%any");
424 DBG2(DBG_CFG
, " my ca: '%D'", my_ca
);
425 DBG2(DBG_CFG
, " other ca:'%D'", other_ca
);
426 DBG2(DBG_CFG
, " updown: '%s'", msg
->add_conn
.me
.updown
);
428 /* have a look for an (almost) identical peer config to reuse */
429 iterator
= this->backend
->create_peer_cfg_iterator(this->backend
);
430 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
432 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
433 if (my_id
->equals(my_id
, peer_cfg
->get_my_id(peer_cfg
)) &&
434 other_id
->equals(other_id
, peer_cfg
->get_other_id(peer_cfg
)) &&
435 my_host
->equals(my_host
, ike_cfg
->get_my_host(ike_cfg
)) &&
436 other_host
->equals(other_host
, ike_cfg
->get_other_host(ike_cfg
)) &&
437 peer_cfg
->get_ike_version(peer_cfg
) == (msg
->add_conn
.ikev2
? 2 : 1) &&
438 peer_cfg
->get_auth_method(peer_cfg
) == msg
->add_conn
.auth_method
&&
439 peer_cfg
->get_eap_type(peer_cfg
) == msg
->add_conn
.eap_type
)
441 DBG1(DBG_CFG
, "reusing existing configuration '%s'",
442 peer_cfg
->get_name(peer_cfg
));
447 iterator
->destroy(iterator
);
451 my_host
->destroy(my_host
);
452 my_id
->destroy(my_id
);
453 my_ca
->destroy(my_ca
);
454 other_host
->destroy(other_host
);
455 other_id
->destroy(other_id
);
456 other_ca
->destroy(other_ca
);
460 ike_cfg
= ike_cfg_create(msg
->add_conn
.other
.sendcert
!= CERT_NEVER_SEND
,
461 my_host
, other_host
);
463 if (msg
->add_conn
.algorithms
.ike
)
465 char *proposal_string
;
466 char *strict
= msg
->add_conn
.algorithms
.ike
+ strlen(msg
->add_conn
.algorithms
.ike
) - 1;
473 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.ike
, ",")))
475 proposal
= proposal_create_from_string(PROTO_IKE
, proposal_string
);
476 if (proposal
== NULL
)
478 DBG1(DBG_CFG
, "invalid IKE proposal string: %s", proposal_string
);
479 my_id
->destroy(my_id
);
480 other_id
->destroy(other_id
);
481 my_ts
->destroy(my_ts
);
482 other_ts
->destroy(other_ts
);
483 my_ca
->destroy(my_ca
);
484 other_ca
->destroy(other_ca
);
485 ike_cfg
->destroy(ike_cfg
);
488 ike_cfg
->add_proposal(ike_cfg
, proposal
);
492 proposal
= proposal_create_default(PROTO_IKE
);
493 ike_cfg
->add_proposal(ike_cfg
, proposal
);
498 proposal
= proposal_create_default(PROTO_IKE
);
499 ike_cfg
->add_proposal(ike_cfg
, proposal
);
503 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, msg
->add_conn
.ikev2
? 2 : 1,
504 ike_cfg
, my_id
, other_id
, my_ca
, other_ca
, msg
->add_conn
.me
.sendcert
,
505 msg
->add_conn
.auth_method
, msg
->add_conn
.eap_type
,
506 msg
->add_conn
.rekey
.tries
, msg
->add_conn
.rekey
.ike_lifetime
,
507 msg
->add_conn
.rekey
.ike_lifetime
- msg
->add_conn
.rekey
.margin
,
508 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
509 msg
->add_conn
.rekey
.reauth
, msg
->add_conn
.dpd
.delay
,
510 msg
->add_conn
.dpd
.action
,my_vip
, other_vip
);
513 child_cfg
= child_cfg_create(
514 msg
->add_conn
.name
, msg
->add_conn
.rekey
.ipsec_lifetime
,
515 msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
516 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
517 msg
->add_conn
.me
.updown
, msg
->add_conn
.me
.hostaccess
,
520 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
522 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, my_ts
);
523 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, other_ts
);
525 if (msg
->add_conn
.algorithms
.esp
)
527 char *proposal_string
;
528 char *strict
= msg
->add_conn
.algorithms
.esp
+ strlen(msg
->add_conn
.algorithms
.esp
) - 1;
535 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.esp
, ",")))
537 proposal
= proposal_create_from_string(PROTO_ESP
, proposal_string
);
538 if (proposal
== NULL
)
540 DBG1(DBG_CFG
, "invalid ESP proposal string: %s", proposal_string
);
541 peer_cfg
->destroy(peer_cfg
);
544 child_cfg
->add_proposal(child_cfg
, proposal
);
548 proposal
= proposal_create_default(PROTO_ESP
);
549 child_cfg
->add_proposal(child_cfg
, proposal
);
554 proposal
= proposal_create_default(PROTO_ESP
);
555 child_cfg
->add_proposal(child_cfg
, proposal
);
560 /* add config to backend */
561 this->backend
->add_peer_cfg(this->backend
, peer_cfg
);
562 DBG1(DBG_CFG
, "added configuration '%s': %H[%D]...%H[%D]",
563 msg
->add_conn
.name
, my_host
, my_id
, other_host
, other_id
);
567 /* mopping up after parsing errors */
570 my_id
->destroy(my_id
);
571 other_id
->destroy(other_id
);
574 my_host
->destroy(my_host
);
575 other_host
->destroy(other_host
);
579 * Delete a connection from the list
581 static void stroke_del_conn(private_stroke_interface_t
*this,
582 stroke_msg_t
*msg
, FILE *out
)
584 iterator_t
*peer_iter
, *child_iter
;
585 peer_cfg_t
*peer
, *child
;
587 pop_string(msg
, &(msg
->del_conn
.name
));
588 DBG1(DBG_CFG
, "received stroke: delete connection '%s'", msg
->del_conn
.name
);
590 peer_iter
= this->backend
->create_peer_cfg_iterator(this->backend
);
591 while (peer_iter
->iterate(peer_iter
, (void**)&peer
))
593 /* remove peer config with such a name */
594 if (streq(peer
->get_name(peer
), msg
->del_conn
.name
))
596 peer_iter
->remove(peer_iter
);
600 /* remove any child with such a name */
601 child_iter
= peer
->create_child_cfg_iterator(peer
);
602 while (child_iter
->iterate(child_iter
, (void**)&child
))
604 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
606 child_iter
->remove(child_iter
);
607 child
->destroy(child
);
610 child_iter
->destroy(child_iter
);
612 peer_iter
->destroy(peer_iter
);
614 fprintf(out
, "deleted connection '%s'\n", msg
->del_conn
.name
);
618 * get the child_cfg with the same name as the peer cfg
620 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
)
622 child_cfg_t
*current
, *found
= NULL
;
623 iterator_t
*iterator
;
625 iterator
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
626 while (iterator
->iterate(iterator
, (void**)¤t
))
628 if (streq(current
->get_name(current
), peer_cfg
->get_name(peer_cfg
)))
631 found
->get_ref(found
);
635 iterator
->destroy(iterator
);
640 * initiate a connection by name
642 static void stroke_initiate(private_stroke_interface_t
*this,
643 stroke_msg_t
*msg
, FILE *out
)
646 peer_cfg_t
*peer_cfg
;
647 child_cfg_t
*child_cfg
;
648 ike_sa_t
*init_ike_sa
= NULL
;
651 pop_string(msg
, &(msg
->initiate
.name
));
652 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
654 peer_cfg
= charon
->cfg_store
->get_peer_cfg_by_name(charon
->cfg_store
,
656 if (peer_cfg
== NULL
)
658 if (msg
->output_verbosity
>= 0)
660 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
664 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
666 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
667 peer_cfg
->get_ike_version(peer_cfg
));
668 peer_cfg
->destroy(peer_cfg
);
672 child_cfg
= get_child_from_peer(peer_cfg
);
673 if (child_cfg
== NULL
)
675 if (msg
->output_verbosity
>= 0)
677 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
679 peer_cfg
->destroy(peer_cfg
);
683 job
= initiate_job_create(peer_cfg
, child_cfg
);
684 charon
->bus
->set_listen_state(charon
->bus
, TRUE
);
685 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
694 signal
= charon
->bus
->listen(charon
->bus
, &level
, &thread
, &ike_sa
, &format
, &args
);
696 if ((init_ike_sa
== NULL
|| ike_sa
== init_ike_sa
) &&
697 level
<= msg
->output_verbosity
)
699 if (vfprintf(out
, format
, args
) < 0 ||
700 fprintf(out
, "\n") < 0 ||
703 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
710 case CHILD_UP_SUCCESS
:
711 case CHILD_UP_FAILED
:
713 if (ike_sa
== init_ike_sa
)
715 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
721 if (init_ike_sa
== NULL
)
723 init_ike_sa
= ike_sa
;
733 * route/unroute a policy (install SPD entries)
735 static void stroke_route(private_stroke_interface_t
*this,
736 stroke_msg_t
*msg
, FILE *out
, bool route
)
739 peer_cfg_t
*peer_cfg
;
740 child_cfg_t
*child_cfg
;
742 pop_string(msg
, &(msg
->route
.name
));
743 DBG1(DBG_CFG
, "received stroke: %s '%s'",
744 route
? "route" : "unroute", msg
->route
.name
);
746 peer_cfg
= charon
->cfg_store
->get_peer_cfg_by_name(charon
->cfg_store
,
748 if (peer_cfg
== NULL
)
750 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
753 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
755 peer_cfg
->destroy(peer_cfg
);
759 child_cfg
= get_child_from_peer(peer_cfg
);
760 if (child_cfg
== NULL
)
762 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
763 peer_cfg
->destroy(peer_cfg
);
766 fprintf(out
, "%s policy '%s'\n",
767 route
? "routing" : "unrouting", msg
->route
.name
);
768 job
= route_job_create(peer_cfg
, child_cfg
, route
);
769 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
773 * terminate a connection by name
775 static void stroke_terminate(private_stroke_interface_t
*this,
776 stroke_msg_t
*msg
, FILE *out
)
778 char *string
, *pos
= NULL
, *name
= NULL
;
782 status_t status
= SUCCESS
;;
785 pop_string(msg
, &(msg
->terminate
.name
));
786 string
= msg
->terminate
.name
;
787 DBG1(DBG_CFG
, "received stroke: terminate '%s'", string
);
789 len
= strlen(string
);
792 DBG1(DBG_CFG
, "error parsing string");
795 switch (string
[len
-1])
799 pos
= strchr(string
, '{');
803 pos
= strchr(string
, '[');
812 { /* must be a single name */
813 DBG1(DBG_CFG
, "check out by single name '%s'", name
);
814 ike_sa
= charon
->ike_sa_manager
->checkout_by_name(charon
->ike_sa_manager
,
817 else if (pos
== string
+ len
- 2)
818 { /* must be name[] or name{} */
819 string
[len
-2] = '\0';
820 DBG1(DBG_CFG
, "check out by name '%s'", string
);
821 ike_sa
= charon
->ike_sa_manager
->checkout_by_name(charon
->ike_sa_manager
,
825 { /* must be name[123] or name{23} */
826 string
[len
-1] = '\0';
830 DBG1(DBG_CFG
, "error parsing string");
833 DBG1(DBG_CFG
, "check out by id '%d'", id
);
834 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
839 DBG1(DBG_CFG
, "no such IKE_SA found");
845 status
= ike_sa
->delete(ike_sa
);
849 child_sa_t
*child_sa
;
850 iterator_t
*iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
851 while (iterator
->iterate(iterator
, (void**)&child_sa
))
853 if ((id
&& id
== child_sa
->get_reqid(child_sa
)) ||
854 (string
&& streq(string
, child_sa
->get_name(child_sa
))))
856 u_int32_t spi
= child_sa
->get_spi(child_sa
, TRUE
);
857 protocol_id_t proto
= child_sa
->get_protocol(child_sa
);
859 status
= ike_sa
->delete_child_sa(ike_sa
, proto
, spi
);
863 iterator
->destroy(iterator
);
865 if (status
== DESTROY_ME
)
867 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
,
871 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
875 * Add a ca information record to the cainfo list
877 static void stroke_add_ca(private_stroke_interface_t
*this,
878 stroke_msg_t
*msg
, FILE *out
)
883 pop_string(msg
, &msg
->add_ca
.name
);
884 pop_string(msg
, &msg
->add_ca
.cacert
);
885 pop_string(msg
, &msg
->add_ca
.crluri
);
886 pop_string(msg
, &msg
->add_ca
.crluri2
);
887 pop_string(msg
, &msg
->add_ca
.ocspuri
);
888 pop_string(msg
, &msg
->add_ca
.ocspuri2
);
890 DBG1(DBG_CFG
, "received stroke: add ca '%s'", msg
->add_ca
.name
);
892 DBG2(DBG_CFG
, "ca %s", msg
->add_ca
.name
);
893 DBG2(DBG_CFG
, " cacert=%s", msg
->add_ca
.cacert
);
894 DBG2(DBG_CFG
, " crluri=%s", msg
->add_ca
.crluri
);
895 DBG2(DBG_CFG
, " crluri2=%s", msg
->add_ca
.crluri2
);
896 DBG2(DBG_CFG
, " ocspuri=%s", msg
->add_ca
.ocspuri
);
897 DBG2(DBG_CFG
, " ocspuri2=%s", msg
->add_ca
.ocspuri2
);
899 if (msg
->add_ca
.cacert
== NULL
)
901 DBG1(DBG_CFG
, "missing cacert parameter\n");
905 cacert
= load_ca_certificate(msg
->add_ca
.cacert
);
911 ca_info
= ca_info_create(msg
->add_ca
.name
, cacert
);
913 if (msg
->add_ca
.crluri
)
915 chunk_t uri
= { msg
->add_ca
.crluri
, strlen(msg
->add_ca
.crluri
) };
917 ca_info
->add_crluri(ca_info
, uri
);
919 if (msg
->add_ca
.crluri2
)
921 chunk_t uri
= { msg
->add_ca
.crluri2
, strlen(msg
->add_ca
.crluri2
) };
923 ca_info
->add_crluri(ca_info
, uri
);
925 if (msg
->add_ca
.ocspuri
)
927 chunk_t uri
= { msg
->add_ca
.ocspuri
, strlen(msg
->add_ca
.ocspuri
) };
929 ca_info
->add_ocspuri(ca_info
, uri
);
931 if (msg
->add_ca
.ocspuri2
)
933 chunk_t uri
= { msg
->add_ca
.ocspuri2
, strlen(msg
->add_ca
.ocspuri2
) };
935 ca_info
->add_ocspuri(ca_info
, uri
);
937 charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
938 DBG1(DBG_CFG
, "added ca '%s'", msg
->add_ca
.name
);
943 * Delete a ca information record from the cainfo list
945 static void stroke_del_ca(private_stroke_interface_t
*this,
946 stroke_msg_t
*msg
, FILE *out
)
950 pop_string(msg
, &(msg
->del_ca
.name
));
951 DBG1(DBG_CFG
, "received stroke: delete ca '%s'", msg
->del_ca
.name
);
953 status
= charon
->credentials
->release_ca_info(charon
->credentials
,
956 if (status
== SUCCESS
)
958 fprintf(out
, "deleted ca '%s'\n", msg
->del_ca
.name
);
962 fprintf(out
, "no ca named '%s'\n", msg
->del_ca
.name
);
967 * show status of daemon
969 static void stroke_statusall(private_stroke_interface_t
*this,
970 stroke_msg_t
*msg
, FILE *out
)
972 iterator_t
*iterator
, *children
;
975 peer_cfg_t
*peer_cfg
;
977 child_cfg_t
*child_cfg
;
981 leak_detective_status(out
);
983 fprintf(out
, "Performance:\n");
984 fprintf(out
, " worker threads: %d idle of %d,",
985 charon
->thread_pool
->get_idle_threads(charon
->thread_pool
),
986 charon
->thread_pool
->get_pool_size(charon
->thread_pool
));
987 fprintf(out
, " job queue load: %d,",
988 charon
->job_queue
->get_count(charon
->job_queue
));
989 fprintf(out
, " scheduled events: %d\n",
990 charon
->event_queue
->get_count(charon
->event_queue
));
991 list
= charon
->kernel_interface
->create_address_list(charon
->kernel_interface
);
993 fprintf(out
, "Listening on %d IP addresses:\n", list
->get_count(list
));
994 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
996 fprintf(out
, " %H\n", host
);
1001 if (msg
->status
.name
)
1003 pop_string(msg
, &(msg
->status
.name
));
1004 name
= msg
->status
.name
;
1007 fprintf(out
, "Connections:\n");
1008 iterator
= this->backend
->create_peer_cfg_iterator(this->backend
);
1009 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
1011 if (peer_cfg
->get_ike_version(peer_cfg
) != 2 ||
1012 (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
))))
1017 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
1018 fprintf(out
, "%12s: %H[%D]...%H[%D]\n", peer_cfg
->get_name(peer_cfg
),
1019 ike_cfg
->get_my_host(ike_cfg
), peer_cfg
->get_my_id(peer_cfg
),
1020 ike_cfg
->get_other_host(ike_cfg
), peer_cfg
->get_other_id(peer_cfg
));
1021 children
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
1022 while (children
->iterate(children
, (void**)&child_cfg
))
1024 linked_list_t
*my_ts
, *other_ts
;
1025 my_ts
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
1026 other_ts
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
1027 fprintf(out
, "%12s: %#R=== %#R\n", child_cfg
->get_name(child_cfg
),
1029 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
1030 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
1032 children
->destroy(children
);
1034 iterator
->destroy(iterator
);
1037 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
1038 if (iterator
->get_count(iterator
) > 0)
1040 fprintf(out
, "Security Associations:\n");
1042 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
1044 bool ike_sa_printed
= FALSE
;
1045 child_sa_t
*child_sa
;
1046 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
1049 if (name
== NULL
|| strcmp(name
, ike_sa
->get_name(ike_sa
)) == 0)
1051 fprintf(out
, "%#K\n", ike_sa
);
1052 ike_sa_printed
= TRUE
;
1055 while (children
->iterate(children
, (void**)&child_sa
))
1057 bool child_sa_match
= name
== NULL
||
1058 strcmp(name
, child_sa
->get_name(child_sa
)) == 0;
1060 /* print IKE_SA if its name differs from the CHILD_SA's name */
1061 if (!ike_sa_printed
&& child_sa_match
)
1063 fprintf(out
, "%#K\n", ike_sa
);
1064 ike_sa_printed
= TRUE
;
1067 /* print CHILD_SA */
1070 fprintf(out
, "%#P\n", child_sa
);
1073 children
->destroy(children
);
1075 iterator
->destroy(iterator
);
1079 * show status of daemon
1081 static void stroke_status(private_stroke_interface_t
*this,
1082 stroke_msg_t
*msg
, FILE *out
)
1084 iterator_t
*iterator
;
1088 if (msg
->status
.name
)
1090 pop_string(msg
, &(msg
->status
.name
));
1091 name
= msg
->status
.name
;
1094 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
1095 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
1097 bool ike_sa_printed
= FALSE
;
1098 child_sa_t
*child_sa
;
1099 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
1102 if (name
== NULL
|| strcmp(name
, ike_sa
->get_name(ike_sa
)) == 0)
1104 fprintf(out
, "%K\n", ike_sa
);
1105 ike_sa_printed
= TRUE
;
1108 while (children
->iterate(children
, (void**)&child_sa
))
1110 bool child_sa_match
= name
== NULL
||
1111 strcmp(name
, child_sa
->get_name(child_sa
)) == 0;
1113 /* print IKE_SA if its name differs from the CHILD_SA's name */
1114 if (!ike_sa_printed
&& child_sa_match
)
1116 fprintf(out
, "%K\n", ike_sa
);
1117 ike_sa_printed
= TRUE
;
1120 /* print CHILD_SA */
1123 fprintf(out
, "%P\n", child_sa
);
1126 children
->destroy(children
);
1128 iterator
->destroy(iterator
);
1132 * list all authority certificates matching a specified flag
1134 static void list_auth_certificates(private_stroke_interface_t
*this, u_int flag
,
1135 const char *label
, bool utc
, FILE *out
)
1140 iterator_t
*iterator
= charon
->credentials
->create_auth_cert_iterator(charon
->credentials
);
1142 while (iterator
->iterate(iterator
, (void**)&cert
))
1144 if (cert
->has_authority_flag(cert
, flag
))
1149 fprintf(out
, "List of X.509 %s Certificates:\n", label
);
1153 fprintf(out
, "%#Q\n", cert
, utc
);
1156 iterator
->destroy(iterator
);
1160 * list various information
1162 static void stroke_list(private_stroke_interface_t
*this,
1163 stroke_msg_t
*msg
, FILE *out
)
1165 iterator_t
*iterator
;
1167 if (msg
->list
.flags
& LIST_CERTS
)
1171 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
1172 if (iterator
->get_count(iterator
))
1175 fprintf(out
, "List of X.509 End Entity Certificates:\n");
1178 while (iterator
->iterate(iterator
, (void**)&cert
))
1180 fprintf(out
, "%#Q", cert
, msg
->list
.utc
);
1181 if (charon
->credentials
->has_rsa_private_key(
1182 charon
->credentials
, cert
->get_public_key(cert
)))
1184 fprintf(out
, ", has private key");
1189 iterator
->destroy(iterator
);
1191 if (msg
->list
.flags
& LIST_CACERTS
)
1193 list_auth_certificates(this, AUTH_CA
, "CA", msg
->list
.utc
, out
);
1195 if (msg
->list
.flags
& LIST_CAINFOS
)
1199 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1200 if (iterator
->get_count(iterator
))
1203 fprintf(out
, "List of X.509 CA Information Records:\n");
1206 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1208 fprintf(out
, "%#W", ca_info
, msg
->list
.utc
);
1210 iterator
->destroy(iterator
);
1212 if (msg
->list
.flags
& LIST_CRLS
)
1217 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1218 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1220 if (ca_info
->has_crl(ca_info
))
1225 fprintf(out
, "List of X.509 CRLs:\n");
1229 ca_info
->list_crl(ca_info
, out
, msg
->list
.utc
);
1232 iterator
->destroy(iterator
);
1234 if (msg
->list
.flags
& LIST_OCSPCERTS
)
1236 list_auth_certificates(this, AUTH_OCSP
, "OCSP", msg
->list
.utc
, out
);
1238 if (msg
->list
.flags
& LIST_OCSP
)
1243 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1244 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1246 if (ca_info
->has_certinfos(ca_info
))
1251 fprintf(out
, "List of OCSP responses:\n");
1255 ca_info
->list_certinfos(ca_info
, out
, msg
->list
.utc
);
1258 iterator
->destroy(iterator
);
1263 * reread various information
1265 static void stroke_reread(private_stroke_interface_t
*this,
1266 stroke_msg_t
*msg
, FILE *out
)
1268 if (msg
->reread
.flags
& REREAD_CACERTS
)
1270 charon
->credentials
->load_ca_certificates(charon
->credentials
);
1272 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1274 charon
->credentials
->load_ocsp_certificates(charon
->credentials
);
1276 if (msg
->reread
.flags
& REREAD_CRLS
)
1278 charon
->credentials
->load_crls(charon
->credentials
);
1283 * purge various information
1285 static void stroke_purge(private_stroke_interface_t
*this,
1286 stroke_msg_t
*msg
, FILE *out
)
1288 if (msg
->purge
.flags
& PURGE_OCSP
)
1290 iterator_t
*iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1293 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1295 ca_info
->purge_ocsp(ca_info
);
1297 iterator
->destroy(iterator
);
1301 signal_t
get_signal_from_logtype(char *type
)
1303 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
1304 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
1305 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
1306 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
1307 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
1308 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
1309 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
1310 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
1311 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
1312 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
1317 * set the verbosity debug output
1319 static void stroke_loglevel(private_stroke_interface_t
*this,
1320 stroke_msg_t
*msg
, FILE *out
)
1324 pop_string(msg
, &(msg
->loglevel
.type
));
1325 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
1326 msg
->loglevel
.level
, msg
->loglevel
.type
);
1328 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
1331 fprintf(out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
1335 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
1336 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
1340 * process a stroke request from the socket pointed by "fd"
1342 static void stroke_process(private_stroke_interface_t
*this, int strokefd
)
1345 u_int16_t msg_length
;
1349 /* peek the length */
1350 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
1351 if (bytes_read
!= sizeof(msg_length
))
1353 DBG1(DBG_CFG
, "reading length of stroke message failed");
1359 msg
= malloc(msg_length
);
1360 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
1361 if (bytes_read
!= msg_length
)
1363 DBG1(DBG_CFG
, "reading stroke message failed: %m");
1368 out
= fdopen(dup(strokefd
), "w");
1371 DBG1(DBG_CFG
, "opening stroke output channel failed: %m");
1377 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
1382 stroke_initiate(this, msg
, out
);
1385 stroke_route(this, msg
, out
, TRUE
);
1388 stroke_route(this, msg
, out
, FALSE
);
1391 stroke_terminate(this, msg
, out
);
1394 stroke_status(this, msg
, out
);
1396 case STR_STATUS_ALL
:
1397 stroke_statusall(this, msg
, out
);
1400 stroke_add_conn(this, msg
, out
);
1403 stroke_del_conn(this, msg
, out
);
1406 stroke_add_ca(this, msg
, out
);
1409 stroke_del_ca(this, msg
, out
);
1412 stroke_loglevel(this, msg
, out
);
1415 stroke_list(this, msg
, out
);
1418 stroke_reread(this, msg
, out
);
1421 stroke_purge(this, msg
, out
);
1424 DBG1(DBG_CFG
, "received unknown stroke");
1432 * Implementation of private_stroke_interface_t.stroke_receive.
1434 static void stroke_receive(private_stroke_interface_t
*this)
1436 struct sockaddr_un strokeaddr
;
1437 int strokeaddrlen
= sizeof(strokeaddr
);
1441 /* ignore sigpipe. writing over the pipe back to the console
1442 * only fails if SIGPIPE is ignored. */
1443 signal(SIGPIPE
, SIG_IGN
);
1445 /* disable cancellation by default */
1446 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
1450 /* wait for connections, but allow thread to terminate */
1451 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
1452 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
1453 pthread_setcancelstate(oldstate
, NULL
);
1457 DBG1(DBG_CFG
, "accepting stroke connection failed: %m");
1460 stroke_process(this, strokefd
);
1465 * Implementation of stroke_t.destroy.
1467 static void destroy(private_stroke_interface_t
*this)
1471 for (i
= 0; i
< STROKE_THREADS
; i
++)
1473 pthread_cancel(this->threads
[i
]);
1474 pthread_join(this->threads
[i
], NULL
);
1477 close(this->socket
);
1478 unlink(socket_addr
.sun_path
);
1483 * Described in header-file
1485 stroke_t
*stroke_create(local_backend_t
*backend
)
1487 private_stroke_interface_t
*this = malloc_thing(private_stroke_interface_t
);
1491 /* public functions */
1492 this->public.destroy
= (void (*)(stroke_t
*))destroy
;
1494 this->backend
= backend
;
1496 /* set up unix socket */
1497 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1498 if (this->socket
== -1)
1500 DBG1(DBG_CFG
, "could not create whack socket");
1505 old
= umask(~S_IRWXU
);
1506 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1508 DBG1(DBG_CFG
, "could not bind stroke socket: %m");
1509 close(this->socket
);
1515 if (listen(this->socket
, 0) < 0)
1517 DBG1(DBG_CFG
, "could not listen on stroke socket: %m");
1518 close(this->socket
);
1519 unlink(socket_addr
.sun_path
);
1524 /* start threads reading from the socket */
1525 for (i
= 0; i
< STROKE_THREADS
; i
++)
1527 if (pthread_create(&this->threads
[i
], NULL
, (void*(*)(void*))stroke_receive
, this) != 0)
1529 charon
->kill(charon
, "unable to create stroke thread");
1533 return (&this->public);