added equals() method to peer_cfg, ike_cfg, proposals, auth_info
[strongswan.git] / src / charon / plugins / stroke / stroke.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2006-2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/fcntl.h>
25 #include <unistd.h>
26 #include <dirent.h>
27 #include <errno.h>
28 #include <pthread.h>
29 #include <signal.h>
30
31 #include "stroke.h"
32
33 /* stroke message format definition */
34 #include <stroke_msg.h>
35
36 #include <library.h>
37 #include <daemon.h>
38 #include <credentials/certificates/x509.h>
39 #include <credentials/certificates/crl.h>
40 #include <credentials/certificates/ac.h>
41 #include <credentials/certificates/ocsp_request.h>
42 #include <credentials/certificates/ocsp_response.h>
43 #include <control/controller.h>
44 #include <utils/lexparser.h>
45 #include <asn1/ttodata.h>
46 #include <asn1/pem.h>
47 #include <utils/mutex.h>
48 #include <processing/jobs/callback_job.h>
49 #include <credentials/credential_set.h>
50
51 /* configuration directories and files */
52 #define CONFIG_DIR IPSEC_CONFDIR
53 #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
54 #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
55 #define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
56 #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
57 #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
58 #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
59 #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
60 #define CRL_DIR IPSEC_D_DIR "/crls"
61 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
62
63 /* warning intervals for list functions */
64 #define CERT_WARNING_INTERVAL 30 /* days */
65 #define CRL_WARNING_INTERVAL 7 /* days */
66
67 typedef struct private_stroke_t private_stroke_t;
68 typedef struct stroke_credentials_t stroke_credentials_t;
69 typedef struct ca_creds_t ca_creds_t;
70 typedef struct creds_t creds_t;
71 typedef struct ca_section_t ca_section_t;
72 typedef struct configs_t configs_t;
73
74 /**
75 * loaded ipsec.conf CA sections
76 */
77 struct ca_section_t {
78
79 /**
80 * name of the CA section
81 */
82 char *name;
83
84 /**
85 * reference to cert in trusted_credential_t
86 */
87 certificate_t *cert;
88
89 /**
90 * CRL URIs
91 */
92 linked_list_t *crl;
93
94 /**
95 * OCSP URIs
96 */
97 linked_list_t *ocsp;
98 };
99
100 /**
101 * private credentail_set_t implementation for CA sections
102 */
103 struct ca_creds_t {
104 /**
105 * implements credential set
106 */
107 credential_set_t set;
108
109 /**
110 * list of starters CA sections and its certificates (ca_section_t)
111 */
112 linked_list_t *sections;
113
114 /**
115 * mutex to lock sections list
116 */
117 mutex_t *mutex;
118
119 };
120
121 /**
122 * private credential_set_t implementation for trusted certificates and keys
123 */
124 struct creds_t {
125 /**
126 * implements credential set
127 */
128 credential_set_t set;
129
130 /**
131 * list of trusted peer/signer/CA certificates (certificate_t)
132 */
133 linked_list_t *certs;
134
135 /**
136 * list of shared secrets (private_shared_key_t)
137 */
138 linked_list_t *shared;
139
140 /**
141 * list of private keys (private_key_t)
142 */
143 linked_list_t *private;
144
145 /**
146 * mutex to lock lists above
147 */
148 mutex_t *mutex;
149 };
150
151
152 typedef struct private_shared_key_t private_shared_key_t;
153 /**
154 * private data of shared_key
155 */
156 struct private_shared_key_t {
157
158 /**
159 * implements shared_key_t
160 */
161 shared_key_t public;
162
163 /**
164 * type of this key
165 */
166 shared_key_type_t type;
167
168 /**
169 * data of the key
170 */
171 chunk_t key;
172
173 /**
174 * list of key owners, as identification_t
175 */
176 linked_list_t *owners;
177
178 /**
179 * reference counter
180 */
181 refcount_t ref;
182 };
183
184
185 /**
186 * configuration backend including peer_cfg list
187 */
188 struct configs_t {
189
190 /**
191 * implements backend_t interface
192 */
193 backend_t backend;
194
195 /**
196 * list of peer_cfg_t
197 */
198 linked_list_t *list;
199
200 /**
201 * mutex to lock config list
202 */
203 mutex_t *mutex;
204 };
205
206 /**
207 * Private data of an stroke_t object.
208 */
209 struct private_stroke_t {
210
211 /**
212 * Public part of stroke_t object.
213 */
214 stroke_t public;
215
216 /**
217 * Unix socket to listen for strokes
218 */
219 int socket;
220
221 /**
222 * job accepting stroke messages
223 */
224 callback_job_t *job;
225
226 /**
227 * CA credentials
228 */
229 ca_creds_t ca_creds;
230
231 /**
232 * other credentials
233 */
234 creds_t creds;
235
236 /**
237 * configuration backend
238 */
239 configs_t configs;
240 };
241
242 typedef struct stroke_log_info_t stroke_log_info_t;
243
244 /**
245 * helper struct to say what and where to log when using controller callback
246 */
247 struct stroke_log_info_t {
248
249 /**
250 * level to log up to
251 */
252 level_t level;
253
254 /**
255 * where to write log
256 */
257 FILE* out;
258 };
259
260 /**
261 * create a new CA section
262 */
263 static ca_section_t *ca_section_create(char *name, certificate_t *cert)
264 {
265 ca_section_t *ca = malloc_thing(ca_section_t);
266
267 ca->name = strdup(name);
268 ca->crl = linked_list_create();
269 ca->ocsp = linked_list_create();
270 ca->cert = cert;
271 return ca;
272 }
273
274 /**
275 * destroy a ca section entry
276 */
277 static void ca_section_destroy(ca_section_t *this)
278 {
279 this->crl->destroy_function(this->crl, free);
280 this->ocsp->destroy_function(this->ocsp, free);
281 free(this->name);
282 free(this);
283 }
284
285 /**
286 * data to pass to create_inner_cdp
287 */
288 typedef struct {
289 ca_creds_t *this;
290 certificate_type_t type;
291 identification_t *id;
292 } cdp_data_t;
293
294 /**
295 * destroy cdp enumerator data and unlock list
296 */
297 static void cdp_data_destroy(cdp_data_t *data)
298 {
299 data->this->mutex->unlock(data->this->mutex);
300 free(data);
301 }
302
303 /**
304 * inner enumerator constructor for CDP URIs
305 */
306 static enumerator_t *create_inner_cdp(ca_section_t *section, cdp_data_t *data)
307 {
308 public_key_t *public;
309 identification_t *keyid;
310 enumerator_t *enumerator = NULL;
311 linked_list_t *list;
312
313 if (data->type == CERT_X509_OCSP_RESPONSE)
314 {
315 list = section->ocsp;
316 }
317 else
318 {
319 list = section->crl;
320 }
321
322 public = section->cert->get_public_key(section->cert);
323 if (public)
324 {
325 if (!data->id)
326 {
327 enumerator = list->create_enumerator(list);
328 }
329 else
330 {
331 keyid = public->get_id(public, data->id->get_type(data->id));
332 if (keyid && keyid->matches(keyid, data->id))
333 {
334 enumerator = list->create_enumerator(list);
335 }
336 }
337 public->destroy(public);
338 }
339 return enumerator;
340 }
341
342 /**
343 * Implementation of ca_creds_t.set.create_cdp_enumerator.
344 */
345 static enumerator_t *create_cdp_enumerator(ca_creds_t *this,
346 certificate_type_t type, identification_t *id)
347 {
348 cdp_data_t *data;
349
350 switch (type)
351 { /* we serve CRLs and OCSP responders */
352 case CERT_X509_CRL:
353 case CERT_X509_OCSP_RESPONSE:
354 case CERT_ANY:
355 break;
356 default:
357 return NULL;
358 }
359 data = malloc_thing(cdp_data_t);
360 data->this = this;
361 data->type = type;
362 data->id = id;
363
364 this->mutex->lock(this->mutex);
365 return enumerator_create_nested(this->sections->create_enumerator(this->sections),
366 (void*)create_inner_cdp, data,
367 (void*)cdp_data_destroy);
368 }
369
370 /**
371 * data to pass to various filters
372 */
373 typedef struct {
374 creds_t *this;
375 identification_t *id;
376 } id_data_t;
377
378 /**
379 * destroy id enumerator data and unlock list
380 */
381 static void id_data_destroy(id_data_t *data)
382 {
383 data->this->mutex->unlock(data->this->mutex);
384 free(data);
385 }
386
387
388 /**
389 * filter function for private key enumerator
390 */
391 static bool private_filter(id_data_t *data,
392 private_key_t **in, private_key_t **out)
393 {
394 identification_t *candidate;
395
396 if (data->id == NULL)
397 {
398 *out = *in;
399 return TRUE;
400 }
401 candidate = (*in)->get_id(*in, data->id->get_type(data->id));
402 if (candidate && data->id->equals(data->id, candidate))
403 {
404 *out = *in;
405 return TRUE;
406 }
407 return FALSE;
408 }
409
410 /**
411 * Implements creds_t.set.create_private_enumerator
412 */
413 static enumerator_t* create_private_enumerator(creds_t *this,
414 key_type_t type, identification_t *id)
415 {
416 id_data_t *data;
417
418 if (type != KEY_RSA && type != KEY_ANY)
419 { /* we only have RSA keys */
420 return NULL;
421 }
422 data = malloc_thing(id_data_t);
423 data->this = this;
424 data->id = id;
425
426 this->mutex->lock(this->mutex);
427 return enumerator_create_filter(this->private->create_enumerator(this->private),
428 (void*)private_filter, data,
429 (void*)id_data_destroy);
430 }
431
432 /**
433 * filter function for certs enumerator
434 */
435 static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out)
436 {
437 public_key_t *public;
438 identification_t *candidate;
439 certificate_t *cert = *in;
440
441 if (cert->get_type(cert) == CERT_X509_CRL)
442 {
443 return FALSE;
444 }
445
446 if (data->id == NULL || cert->has_subject(cert, data->id))
447 {
448 *out = *in;
449 return TRUE;
450 }
451
452 public = (cert)->get_public_key(cert);
453 if (public)
454 {
455 candidate = public->get_id(public, data->id->get_type(data->id));
456 if (candidate && data->id->equals(data->id, candidate))
457 {
458 public->destroy(public);
459 *out = *in;
460 return TRUE;
461 }
462 public->destroy(public);
463 }
464 return FALSE;
465 }
466
467 /**
468 * filter function for crl enumerator
469 */
470 static bool crl_filter(id_data_t *data, certificate_t **in, certificate_t **out)
471 {
472 certificate_t *cert = *in;
473
474 if (cert->get_type(cert) != CERT_X509_CRL)
475 {
476 return FALSE;
477 }
478
479 if (data->id == NULL || cert->has_issuer(cert, data->id))
480 {
481 *out = *in;
482 return TRUE;
483 }
484 return FALSE;
485 }
486
487 /**
488 * Implements creds_t.set.create_cert_enumerator
489 */
490 static enumerator_t* create_cert_enumerator(creds_t *this,
491 certificate_type_t cert, key_type_t key,
492 identification_t *id, bool trusted)
493 {
494 id_data_t *data;
495
496 if (cert == CERT_X509_CRL)
497 {
498 data = malloc_thing(id_data_t);
499 data->this = this;
500 data->id = id;
501
502 this->mutex->lock(this->mutex);
503 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
504 (void*)crl_filter, data,
505 (void*)id_data_destroy);
506 }
507 if (cert != CERT_X509 && cert != CERT_ANY)
508 { /* we only have X509 certificates. TODO: ACs? */
509 return NULL;
510 }
511 if (key != KEY_RSA && key != KEY_ANY)
512 { /* we only have RSA keys */
513 return NULL;
514 }
515 data = malloc_thing(id_data_t);
516 data->this = this;
517 data->id = id;
518
519 this->mutex->lock(this->mutex);
520 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
521 (void*)certs_filter, data,
522 (void*)id_data_destroy);
523 }
524
525 /**
526 * Implementation of shared_key_t.get_type.
527 */
528 static shared_key_type_t get_type(private_shared_key_t *this)
529 {
530 return this->type;
531 }
532
533 /**
534 * Implementation of shared_key_t.get_ref.
535 */
536 static private_shared_key_t* get_ref(private_shared_key_t *this)
537 {
538 ref_get(&this->ref);
539 return this;
540 }
541
542 /**
543 * Implementation of shared_key_t.destroy
544 */
545 static void shared_key_destroy(private_shared_key_t *this)
546 {
547 if (ref_put(&this->ref))
548 {
549 this->owners->destroy_offset(this->owners, offsetof(identification_t, destroy));
550 chunk_free(&this->key);
551 free(this);
552 }
553 }
554
555 /**
556 * Implementation of shared_key_t.get_key.
557 */
558 static chunk_t get_key(private_shared_key_t *this)
559 {
560 return this->key;
561 }
562
563 /**
564 * create a shared key
565 */
566 static private_shared_key_t *private_shared_key_create(shared_key_type_t type, chunk_t key)
567 {
568 private_shared_key_t *this = malloc_thing(private_shared_key_t);
569
570 this->public.get_type = (shared_key_type_t(*)(shared_key_t*))get_type;
571 this->public.get_key = (chunk_t(*)(shared_key_t*))get_key;
572 this->public.get_ref = (shared_key_t*(*)(shared_key_t*))get_ref;
573 this->public.destroy = (void(*)(shared_key_t*))shared_key_destroy;
574
575 this->owners = linked_list_create();
576 this->type = type;
577 this->key = key;
578 this->ref = 1;
579 return this;
580 }
581
582 /**
583 * Check if a key has such an owner
584 */
585 static id_match_t has_owner(private_shared_key_t *this, identification_t *owner)
586 {
587 enumerator_t *enumerator;
588 id_match_t match, best = ID_MATCH_NONE;
589 identification_t *current;
590
591 enumerator = this->owners->create_enumerator(this->owners);
592 while (enumerator->enumerate(enumerator, &current))
593 {
594 match = owner->matches(owner, current);
595 if (match > best)
596 {
597 best = match;
598 }
599 }
600 enumerator->destroy(enumerator);
601 return best;
602 }
603
604 typedef struct {
605 creds_t *this;
606 identification_t *me;
607 identification_t *other;
608 shared_key_type_t type;
609 } shared_data_t;
610
611 /**
612 * free shared key enumerator data and unlock list
613 */
614 static void shared_data_destroy(shared_data_t *data)
615 {
616 data->this->mutex->unlock(data->this->mutex);
617 free(data);
618 }
619
620 /**
621 * filter function for certs enumerator
622 */
623 static bool shared_filter(shared_data_t *data,
624 private_shared_key_t **in, private_shared_key_t **out,
625 void **unused1, id_match_t *me,
626 void **unused2, id_match_t *other)
627 {
628 id_match_t my_match, other_match;
629
630 if (data->type != SHARED_ANY && (*in)->type != data->type)
631 {
632 return FALSE;
633 }
634 my_match = has_owner(*in, data->me);
635 other_match = has_owner(*in, data->other);
636 if (!my_match && !other_match)
637 {
638 return FALSE;
639 }
640 *out = *in;
641 if (me)
642 {
643 *me = my_match;
644 }
645 if (other)
646 {
647 *other = other_match;
648 }
649 return TRUE;
650 }
651
652 /**
653 * Implements creds_t.set.create_shared_enumerator
654 */
655 static enumerator_t* create_shared_enumerator(creds_t *this,
656 shared_key_type_t type, identification_t *me,
657 identification_t *other)
658 {
659 shared_data_t *data = malloc_thing(shared_data_t);
660
661 data->this = this;
662 data->me = me;
663 data->other = other;
664 data->type = type;
665 this->mutex->lock(this->mutex);
666 return enumerator_create_filter(this->shared->create_enumerator(this->shared),
667 (void*)shared_filter, data,
668 (void*)shared_data_destroy);
669 }
670
671 /**
672 * Helper function which corrects the string pointers
673 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
674 * contains RELATIVE addresses (relative to the beginning of the
675 * stroke_msg). They must be corrected if they reach our address
676 * space...
677 */
678 static void pop_string(stroke_msg_t *msg, char **string)
679 {
680 if (*string == NULL)
681 {
682 return;
683 }
684
685 /* check for sanity of string pointer and string */
686 if (string < (char**)msg ||
687 string > (char**)msg + sizeof(stroke_msg_t) ||
688 (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
689 (unsigned long)*string > msg->length)
690 {
691 *string = "(invalid pointer in stroke msg)";
692 }
693 else
694 {
695 *string = (char*)msg + (unsigned long)*string;
696 }
697 }
698
699 /**
700 * Add X.509 certificate to chain
701 */
702 static certificate_t* add_x509_cert(private_stroke_t *this, x509_t* x509)
703 {
704 certificate_t *current, *cert = &x509->interface;
705 enumerator_t *enumerator;
706 bool new = TRUE;
707
708 this->creds.mutex->lock(this->creds.mutex);
709 enumerator = this->creds.certs->create_enumerator(this->creds.certs);
710 while (enumerator->enumerate(enumerator, (void**)&current))
711 {
712 if (current->equals(current, cert))
713 {
714 /* cert already in queue */
715 cert->destroy(cert);
716 cert = current;
717 new = FALSE;
718 break;
719 }
720 }
721 enumerator->destroy(enumerator);
722
723 if (new)
724 {
725 this->creds.certs->insert_last(this->creds.certs, cert);
726 }
727 this->creds.mutex->unlock(this->creds.mutex);
728 return cert;
729 }
730
731 /**
732 * Verify the signature of an X.509 CRL
733 */
734 static bool verify_crl(crl_t* crl)
735 {
736 certificate_t *crl_cert = &crl->certificate;
737 identification_t *issuer = crl_cert->get_issuer(crl_cert);
738 identification_t *authKeyIdentifier = crl->get_authKeyIdentifier(crl);
739 certificate_t *issuer_cert;
740
741 DBG1(DBG_CFG, " issuer: %D", issuer);
742 if (authKeyIdentifier)
743 {
744 DBG1(DBG_CFG, " authkey: %D", authKeyIdentifier);
745 }
746
747 issuer_cert = charon->credentials->get_cert(charon->credentials, CERT_X509,
748 KEY_ANY, issuer, TRUE);
749
750 if (issuer_cert)
751 {
752
753 bool ok = crl_cert->issued_by(crl_cert, issuer_cert, TRUE);
754
755 DBG1(DBG_CFG, " crl is %strusted: %s signature",
756 ok? "":"un", ok? "good":"bad");
757 return ok;
758 }
759 else
760 {
761 DBG1(DBG_CFG, " crl is untrusted: issuer certificate not found");
762 return FALSE;
763 }
764 }
765
766 /**
767 * Add X.509 CRL to chain
768 */
769 static void add_crl(private_stroke_t *this, crl_t* crl)
770 {
771 certificate_t *current, *cert = &crl->certificate;
772 enumerator_t *enumerator;
773 bool new = TRUE, found = FALSE;
774
775 this->creds.mutex->lock(this->creds.mutex);
776 enumerator = this->creds.certs->create_enumerator(this->creds.certs);
777 while (enumerator->enumerate(enumerator, (void**)&current))
778 {
779 if (current->get_type(current) == CERT_X509_CRL)
780 {
781 crl_t *crl_c = (crl_t*)current;
782 identification_t *authkey = crl->get_authKeyIdentifier(crl);
783 identification_t *authkey_c = crl_c->get_authKeyIdentifier(crl_c);
784
785 /* if compare authorityKeyIdentifiers if available */
786 if (authkey != NULL && authkey_c != NULL &&
787 authkey->equals(authkey, authkey_c))
788 {
789 found = TRUE;
790 }
791 else
792 {
793 identification_t *issuer = cert->get_issuer(cert);
794 identification_t *issuer_c = current->get_issuer(current);
795
796 /* otherwise compare issuer distinguished names */
797 if (issuer->equals(issuer, issuer_c))
798 {
799 found = TRUE;
800 }
801 }
802 if (found)
803 {
804 new = cert->is_newer(cert, current);
805 if (new)
806 {
807 this->creds.certs->remove_at(this->creds.certs, enumerator);
808 }
809 else
810 {
811 cert->destroy(cert);
812 }
813 break;
814 }
815 }
816 }
817 enumerator->destroy(enumerator);
818
819 if (new)
820 {
821 this->creds.certs->insert_last(this->creds.certs, cert);
822 }
823 this->creds.mutex->unlock(this->creds.mutex);
824 }
825
826 /**
827 * Load end entitity certificate
828 */
829 static void load_peer_cert(private_stroke_t *this,
830 char *filename, identification_t **id)
831 {
832 certificate_t *cert;
833 char path[PATH_MAX];
834 identification_t *peerid = *id;
835
836 if (*filename == '/')
837 {
838 snprintf(path, sizeof(path), "%s", filename);
839 }
840 else
841 {
842 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
843 }
844 cert = lib->creds->create(lib->creds,
845 CRED_CERTIFICATE, CERT_X509,
846 BUILD_FROM_FILE, path,
847 BUILD_X509_FLAG, 0,
848 BUILD_END);
849 if (cert)
850 {
851 identification_t *subject = cert->get_subject(cert);
852
853 if (!cert->has_subject(cert, peerid))
854 {
855 DBG1(DBG_CFG, " peerid %D not confirmed by certificate, "
856 "defaulting to subject DN", peerid);
857 peerid->destroy(peerid);
858 *id = subject->clone(subject);
859 }
860 add_x509_cert(this, (x509_t*)cert);
861 }
862 }
863
864 /**
865 * Load ca certificate
866 */
867 static certificate_t* load_ca_cert(private_stroke_t *this, char *filename)
868 {
869 certificate_t *cert;
870 char path[PATH_MAX];
871
872 if (*filename == '/')
873 {
874 snprintf(path, sizeof(path), "%s", filename);
875 }
876 else
877 {
878 snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
879 }
880 cert = lib->creds->create(lib->creds,
881 CRED_CERTIFICATE, CERT_X509,
882 BUILD_FROM_FILE, path,
883 BUILD_X509_FLAG, X509_CA,
884 BUILD_END);
885 if (cert)
886 {
887 return add_x509_cert(this, (x509_t*)cert);
888 }
889 else
890 {
891 return NULL;
892 }
893 }
894
895 /**
896 * load trusted certificates from a directory
897 */
898 static void load_certdir(private_stroke_t *this, char *path,
899 certificate_type_t type, x509_flag_t flag)
900 {
901 struct stat st;
902 char *file;
903
904 enumerator_t *enumerator = enumerator_create_directory(path);
905
906 if (!enumerator)
907 {
908 DBG1(DBG_CFG, " reading directory failed");
909 return;
910 }
911
912 while (enumerator->enumerate(enumerator, NULL, &file, &st))
913 {
914 certificate_t *cert;
915
916 if (!S_ISREG(st.st_mode))
917 {
918 /* skip special file */
919 continue;
920 }
921 switch (type)
922 {
923 case CERT_X509:
924 cert = lib->creds->create(lib->creds,
925 CRED_CERTIFICATE, CERT_X509,
926 BUILD_FROM_FILE, file,
927 BUILD_X509_FLAG, flag,
928 BUILD_END);
929 if (cert)
930 {
931 add_x509_cert(this, (x509_t*)cert);
932 }
933 break;
934 case CERT_X509_CRL:
935 cert = lib->creds->create(lib->creds,
936 CRED_CERTIFICATE, CERT_X509_CRL,
937 BUILD_FROM_FILE, file,
938 BUILD_END);
939 if (cert)
940 {
941 /* only trusted crls are added to the store */
942 if (verify_crl((crl_t*)cert))
943 {
944 add_crl(this, (crl_t*)cert);
945 }
946 else
947 {
948 DBG1(DBG_CFG, " crl discarded");
949 cert->destroy(cert);
950 }
951 }
952 break;
953 case CERT_X509_AC:
954 cert = lib->creds->create(lib->creds,
955 CRED_CERTIFICATE, CERT_X509_AC,
956 BUILD_FROM_FILE, file,
957 BUILD_END);
958 if (cert)
959 {
960 cert->destroy(cert);
961 }
962 break;
963 default:
964 break;
965 }
966 }
967 enumerator->destroy(enumerator);
968 }
969
970 /**
971 * Convert a string of characters into a binary secret
972 * A string between single or double quotes is treated as ASCII characters
973 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
974 */
975 static err_t extract_secret(chunk_t *secret, chunk_t *line)
976 {
977 chunk_t raw_secret;
978 char delimiter = ' ';
979 bool quotes = FALSE;
980
981 if (!eat_whitespace(line))
982 {
983 return "missing secret";
984 }
985
986 if (*line->ptr == '\'' || *line->ptr == '"')
987 {
988 quotes = TRUE;
989 delimiter = *line->ptr;
990 line->ptr++; line->len--;
991 }
992
993 if (!extract_token(&raw_secret, delimiter, line))
994 {
995 if (delimiter == ' ')
996 {
997 raw_secret = *line;
998 }
999 else
1000 {
1001 return "missing second delimiter";
1002 }
1003 }
1004
1005 if (quotes)
1006 {
1007 /* treat as an ASCII string */
1008 *secret = chunk_clone(raw_secret);
1009 }
1010 else
1011 {
1012 size_t len;
1013 err_t ugh;
1014
1015 /* secret converted to binary form doesn't use more space than the raw_secret */
1016 *secret = chunk_alloc(raw_secret.len);
1017
1018 /* convert from HEX or Base64 to binary */
1019 ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len);
1020
1021 if (ugh != NULL)
1022 {
1023 chunk_free_randomized(secret);
1024 return ugh;
1025 }
1026 secret->len = len;
1027 }
1028 return NULL;
1029 }
1030
1031 /**
1032 * reload ipsec.secrets
1033 */
1034 static void load_secrets(private_stroke_t *this)
1035 {
1036 size_t bytes;
1037 int line_nr = 0;
1038 chunk_t chunk, src, line;
1039 FILE *fd;
1040 private_key_t *private;
1041 shared_key_t *shared;
1042
1043 DBG1(DBG_CFG, "loading secrets from '%s'", SECRETS_FILE);
1044
1045 fd = fopen(SECRETS_FILE, "r");
1046 if (fd == NULL)
1047 {
1048 DBG1(DBG_CFG, "opening secrets file '%s' failed");
1049 return;
1050 }
1051
1052 /* TODO: do error checks */
1053 fseek(fd, 0, SEEK_END);
1054 chunk.len = ftell(fd);
1055 rewind(fd);
1056 chunk.ptr = malloc(chunk.len);
1057 bytes = fread(chunk.ptr, 1, chunk.len, fd);
1058 fclose(fd);
1059 src = chunk;
1060
1061 this->creds.mutex->lock(this->creds.mutex);
1062 while (this->creds.shared->remove_last(this->creds.shared,
1063 (void**)&shared) == SUCCESS)
1064 {
1065 shared->destroy(shared);
1066 }
1067 while (this->creds.private->remove_last(this->creds.private,
1068 (void**)&private) == SUCCESS)
1069 {
1070 private->destroy(private);
1071 }
1072
1073 while (fetchline(&src, &line))
1074 {
1075 chunk_t ids, token;
1076 shared_key_type_t type;
1077
1078 line_nr++;
1079
1080 if (!eat_whitespace(&line))
1081 {
1082 continue;
1083 }
1084 if (!extract_token(&ids, ':', &line))
1085 {
1086 DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr);
1087 goto error;
1088 }
1089 /* NULL terminate the ids string by replacing the : separator */
1090 *(ids.ptr + ids.len) = '\0';
1091
1092 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
1093 {
1094 DBG1(DBG_CFG, "line %d: missing token", line_nr);
1095 goto error;
1096 }
1097 if (match("RSA", &token))
1098 {
1099 char path[PATH_MAX];
1100 chunk_t filename;
1101 chunk_t secret = chunk_empty;
1102 private_key_t *key;
1103 bool pgp = FALSE;
1104 chunk_t chunk = chunk_empty;
1105
1106 err_t ugh = extract_value(&filename, &line);
1107
1108 if (ugh != NULL)
1109 {
1110 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1111 goto error;
1112 }
1113 if (filename.len == 0)
1114 {
1115 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
1116 goto error;
1117 }
1118 if (*filename.ptr == '/')
1119 {
1120 /* absolute path name */
1121 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
1122 }
1123 else
1124 {
1125 /* relative path name */
1126 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
1127 filename.len, filename.ptr);
1128 }
1129
1130 /* check for optional passphrase */
1131 if (eat_whitespace(&line))
1132 {
1133 ugh = extract_secret(&secret, &line);
1134 if (ugh != NULL)
1135 {
1136 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
1137 goto error;
1138 }
1139 }
1140
1141 if (pem_asn1_load_file(path, &secret, &chunk, &pgp))
1142 {
1143 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
1144 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
1145 if (key)
1146 {
1147 DBG1(DBG_CFG, " loaded private key file '%s'", path);
1148 this->creds.private->insert_last(this->creds.private, key);
1149 }
1150 }
1151 chunk_free_randomized(&secret);
1152 }
1153 else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
1154 (match("EAP", &token) && (type = SHARED_EAP)) ||
1155 (match("XAUTH", &token) && (type = SHARED_EAP)) ||
1156 (match("PIN", &token) && (type = SHARED_PIN)))
1157 {
1158 private_shared_key_t *shared_key;
1159 chunk_t secret = chunk_empty;
1160 bool any = TRUE;
1161
1162 err_t ugh = extract_secret(&secret, &line);
1163 if (ugh != NULL)
1164 {
1165 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
1166 goto error;
1167 }
1168 shared_key = private_shared_key_create(type, secret);
1169 DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
1170 ids.len > 0 ? (char*)ids.ptr : "%any");
1171 DBG4(DBG_CFG, " secret:", secret);
1172
1173 this->creds.shared->insert_last(this->creds.shared, shared_key);
1174 while (ids.len > 0)
1175 {
1176 chunk_t id;
1177 identification_t *peer_id;
1178
1179 ugh = extract_value(&id, &ids);
1180 if (ugh != NULL)
1181 {
1182 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1183 goto error;
1184 }
1185 if (id.len == 0)
1186 {
1187 continue;
1188 }
1189
1190 /* NULL terminate the ID string */
1191 *(id.ptr + id.len) = '\0';
1192
1193 peer_id = identification_create_from_string(id.ptr);
1194 if (peer_id == NULL)
1195 {
1196 DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
1197 goto error;
1198 }
1199 if (peer_id->get_type(peer_id) == ID_ANY)
1200 {
1201 peer_id->destroy(peer_id);
1202 continue;
1203 }
1204
1205 shared_key->owners->insert_last(shared_key->owners, peer_id);
1206 any = FALSE;
1207 }
1208 if (any)
1209 {
1210 shared_key->owners->insert_last(shared_key->owners,
1211 identification_create_from_encoding(ID_ANY, chunk_empty));
1212 }
1213 }
1214 else
1215 {
1216 DBG1(DBG_CFG, "line %d: token must be either "
1217 "RSA, PSK, EAP, or PIN", line_nr);
1218 goto error;
1219 }
1220 }
1221 error:
1222 this->creds.mutex->unlock(this->creds.mutex);
1223 chunk_free_randomized(&chunk);
1224 }
1225
1226 /**
1227 * data to pass peer_filter
1228 */
1229 typedef struct {
1230 configs_t *this;
1231 identification_t *me;
1232 identification_t *other;
1233 } peer_data_t;
1234
1235 /**
1236 * destroy id enumerator data and unlock list
1237 */
1238 static void peer_data_destroy(peer_data_t *data)
1239 {
1240 data->this->mutex->unlock(data->this->mutex);
1241 free(data);
1242 }
1243
1244 /**
1245 * filter function for peer configs
1246 */
1247 static bool peer_filter(peer_data_t *data, peer_cfg_t **in, peer_cfg_t **out)
1248 {
1249 bool match_me = FALSE, match_other = FALSE;
1250 identification_t *me, *other;
1251
1252 me = (*in)->get_my_id(*in);
1253 other = (*in)->get_other_id(*in);
1254
1255 /* own ID may have wildcards in data (no IDr payload) or in config */
1256 match_me = (!data->me || data->me->matches(data->me, me) ||
1257 me->matches(me, data->me));
1258 /* others ID has wildcards in config only */
1259 match_other = (!data->other || data->other->matches(data->other, other));
1260
1261 if (match_me && match_other)
1262 {
1263 *out = *in;
1264 return TRUE;
1265 }
1266 return FALSE;
1267 }
1268
1269 /**
1270 * Implementation of backend_t.create_peer_cfg_enumerator.
1271 */
1272 static enumerator_t* create_peer_cfg_enumerator(configs_t *this,
1273 identification_t *me,
1274 identification_t *other)
1275 {
1276 peer_data_t *data;
1277
1278 data = malloc_thing(peer_data_t);
1279 data->this = this;
1280 data->me = me;
1281 data->other = other;
1282
1283 this->mutex->lock(this->mutex);
1284 return enumerator_create_filter(this->list->create_enumerator(this->list),
1285 (void*)peer_filter, data,
1286 (void*)peer_data_destroy);
1287 }
1288
1289 /**
1290 * data to pass ike_filter
1291 */
1292 typedef struct {
1293 configs_t *this;
1294 host_t *me;
1295 host_t *other;
1296 } ike_data_t;
1297
1298 /**
1299 * destroy id enumerator data and unlock list
1300 */
1301 static void ike_data_destroy(ike_data_t *data)
1302 {
1303 data->this->mutex->unlock(data->this->mutex);
1304 free(data);
1305 }
1306
1307 /**
1308 * filter function for ike configs
1309 */
1310 static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
1311 {
1312 ike_cfg_t *ike_cfg;
1313 host_t *me, *other;
1314
1315 ike_cfg = (*in)->get_ike_cfg(*in);
1316
1317 me = ike_cfg->get_my_host(ike_cfg);
1318 other = ike_cfg->get_other_host(ike_cfg);
1319 if ((!data->me || me->is_anyaddr(me) || me->ip_equals(me, data->me)) &&
1320 (!data->other || other->is_anyaddr(other) || other->ip_equals(other, data->other)))
1321 {
1322 *out = ike_cfg;
1323 return TRUE;
1324 }
1325 return FALSE;
1326 }
1327
1328 /**
1329 * Implementation of backend_t.create_ike_cfg_enumerator.
1330 */
1331 static enumerator_t* create_ike_cfg_enumerator(configs_t *this,
1332 host_t *me, host_t *other)
1333 {
1334 ike_data_t *data;
1335
1336 data = malloc_thing(ike_data_t);
1337 data->this = this;
1338 data->me = me;
1339 data->other = other;
1340
1341 this->mutex->lock(this->mutex);
1342 return enumerator_create_filter(this->list->create_enumerator(this->list),
1343 (void*)ike_filter, data,
1344 (void*)ike_data_destroy);
1345 }
1346
1347 /**
1348 * implements backend_t.get_peer_cfg_by_name.
1349 */
1350 static peer_cfg_t *get_peer_cfg_by_name(configs_t *this, char *name)
1351 {
1352 enumerator_t *e1, *e2;
1353 peer_cfg_t *current, *found = NULL;
1354 child_cfg_t *child;
1355
1356 this->mutex->lock(this->mutex);
1357 e1 = this->list->create_enumerator(this->list);
1358 while (e1->enumerate(e1, &current))
1359 {
1360 /* compare peer_cfgs name first */
1361 if (streq(current->get_name(current), name))
1362 {
1363 found = current;
1364 found->get_ref(found);
1365 break;
1366 }
1367 /* compare all child_cfg names otherwise */
1368 e2 = current->create_child_cfg_enumerator(current);
1369 while (e2->enumerate(e2, &child))
1370 {
1371 if (streq(child->get_name(child), name))
1372 {
1373 found = current;
1374 found->get_ref(found);
1375 break;
1376 }
1377 }
1378 e2->destroy(e2);
1379 if (found)
1380 {
1381 break;
1382 }
1383 }
1384 e1->destroy(e1);
1385 this->mutex->unlock(this->mutex);
1386 return found;
1387 }
1388
1389 /**
1390 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
1391 */
1392 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
1393 {
1394 pop_string(msg, &end->address);
1395 pop_string(msg, &end->subnet);
1396 pop_string(msg, &end->sourceip);
1397 pop_string(msg, &end->id);
1398 pop_string(msg, &end->cert);
1399 pop_string(msg, &end->ca);
1400 pop_string(msg, &end->groups);
1401 pop_string(msg, &end->updown);
1402
1403 DBG2(DBG_CFG, " %s=%s", label, end->address);
1404 DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnet);
1405 DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
1406 DBG2(DBG_CFG, " %sid=%s", label, end->id);
1407 DBG2(DBG_CFG, " %scert=%s", label, end->cert);
1408 DBG2(DBG_CFG, " %sca=%s", label, end->ca);
1409 DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
1410 DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
1411 }
1412
1413 /**
1414 * Add a connection to the configuration list
1415 */
1416 static void stroke_add_conn(private_stroke_t *this,
1417 stroke_msg_t *msg, FILE *out)
1418 {
1419 ike_cfg_t *ike_cfg;
1420 peer_cfg_t *peer_cfg;
1421 peer_cfg_t *mediated_by_cfg = NULL;
1422 child_cfg_t *child_cfg;
1423 auth_info_t *auth;
1424 identification_t *my_id, *other_id;
1425 identification_t *my_ca = NULL;
1426 identification_t *other_ca = NULL;
1427 identification_t *peer_id = NULL;
1428 bool my_ca_same = FALSE;
1429 bool other_ca_same =FALSE;
1430 host_t *my_host = NULL, *other_host = NULL, *my_subnet, *other_subnet;
1431 host_t *my_vip = NULL, *other_vip = NULL;
1432 proposal_t *proposal;
1433 traffic_selector_t *my_ts, *other_ts;
1434 char *interface;
1435 bool use_existing = FALSE;
1436 enumerator_t *enumerator;
1437 u_int32_t vendor;
1438
1439 pop_string(msg, &msg->add_conn.name);
1440 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
1441 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
1442 pop_end(msg, "left", &msg->add_conn.me);
1443 pop_end(msg, "right", &msg->add_conn.other);
1444 pop_string(msg, &msg->add_conn.algorithms.ike);
1445 pop_string(msg, &msg->add_conn.algorithms.esp);
1446 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
1447 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
1448 pop_string(msg, &msg->add_conn.p2p.mediated_by);
1449 pop_string(msg, &msg->add_conn.p2p.peerid);
1450 DBG2(DBG_CFG, " p2p_mediation=%s", msg->add_conn.p2p.mediation ? "yes" : "no");
1451 DBG2(DBG_CFG, " p2p_mediated_by=%s", msg->add_conn.p2p.mediated_by);
1452 DBG2(DBG_CFG, " p2p_peerid=%s", msg->add_conn.p2p.peerid);
1453
1454 if (msg->add_conn.me.address)
1455 {
1456 my_host = host_create_from_string(msg->add_conn.me.address,
1457 IKEV2_UDP_PORT);
1458 }
1459 if (my_host == NULL)
1460 {
1461 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.me.address);
1462 return;
1463 }
1464 if (msg->add_conn.other.address)
1465 {
1466 other_host = host_create_from_string(msg->add_conn.other.address,
1467 IKEV2_UDP_PORT);
1468 }
1469 if (other_host == NULL)
1470 {
1471 DBG1(DBG_CFG, "invalid host: %s\n", msg->add_conn.other.address);
1472 my_host->destroy(my_host);
1473 return;
1474 }
1475
1476 interface = charon->kernel_interface->get_interface(charon->kernel_interface,
1477 other_host);
1478 if (interface)
1479 {
1480 stroke_end_t tmp_end;
1481 host_t *tmp_host;
1482
1483 DBG2(DBG_CFG, "left is other host, swapping ends\n");
1484
1485 tmp_host = my_host;
1486 my_host = other_host;
1487 other_host = tmp_host;
1488
1489 tmp_end = msg->add_conn.me;
1490 msg->add_conn.me = msg->add_conn.other;
1491 msg->add_conn.other = tmp_end;
1492 free(interface);
1493 }
1494 else
1495 {
1496 interface = charon->kernel_interface->get_interface(
1497 charon->kernel_interface, my_host);
1498 if (!interface)
1499 {
1500 DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
1501 }
1502 else
1503 {
1504 free(interface);
1505 }
1506 }
1507
1508 my_id = identification_create_from_string(msg->add_conn.me.id ?
1509 msg->add_conn.me.id : msg->add_conn.me.address);
1510 if (my_id == NULL)
1511 {
1512 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.me.id);
1513 goto destroy_hosts;
1514 }
1515
1516 other_id = identification_create_from_string(msg->add_conn.other.id ?
1517 msg->add_conn.other.id : msg->add_conn.other.address);
1518 if (other_id == NULL)
1519 {
1520 DBG1(DBG_CFG, "invalid ID: %s\n", msg->add_conn.other.id);
1521 my_id->destroy(my_id);
1522 goto destroy_hosts;
1523 }
1524
1525 #ifdef P2P
1526 if (msg->add_conn.p2p.mediation && msg->add_conn.p2p.mediated_by)
1527 {
1528 DBG1(DBG_CFG, "a mediation connection cannot be a"
1529 " mediated connection at the same time, aborting");
1530 goto destroy_ids;
1531 }
1532
1533 if (msg->add_conn.p2p.mediated_by)
1534 {
1535 mediated_by_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
1536 msg->add_conn.p2p.mediated_by);
1537 if (!mediated_by_cfg)
1538 {
1539 DBG1(DBG_CFG, "mediation connection '%s' not found, aborting",
1540 msg->add_conn.p2p.mediated_by);
1541 goto destroy_ids;
1542 }
1543
1544 if (!mediated_by_cfg->is_mediation(mediated_by_cfg))
1545 {
1546 DBG1(DBG_CFG, "connection '%s' as referred to by '%s' is"
1547 "no mediation connection, aborting",
1548 msg->add_conn.p2p.mediated_by, msg->add_conn.name);
1549 goto destroy_ids;
1550 }
1551 }
1552
1553 if (msg->add_conn.p2p.peerid)
1554 {
1555 peer_id = identification_create_from_string(msg->add_conn.p2p.peerid);
1556 if (!peer_id)
1557 {
1558 DBG1(DBG_CFG, "invalid peer ID: %s\n", msg->add_conn.p2p.peerid);
1559 goto destroy_ids;
1560 }
1561 }
1562 else
1563 {
1564 /* no peer ID supplied, assume right ID */
1565 peer_id = other_id->clone(other_id);
1566 }
1567 #endif /* P2P */
1568
1569 my_subnet = host_create_from_string(
1570 msg->add_conn.me.subnet ? msg->add_conn.me.subnet
1571 : msg->add_conn.me.address,
1572 IKEV2_UDP_PORT);
1573 if (my_subnet == NULL)
1574 {
1575 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
1576 goto destroy_ids;
1577 }
1578
1579 other_subnet = host_create_from_string(
1580 msg->add_conn.other.subnet ? msg->add_conn.other.subnet
1581 : msg->add_conn.other.address,
1582 IKEV2_UDP_PORT);
1583 if (other_subnet == NULL)
1584 {
1585 DBG1(DBG_CFG, "invalid subnet: %s\n", msg->add_conn.me.subnet);
1586 my_subnet->destroy(my_subnet);
1587 goto destroy_ids;
1588 }
1589
1590 if (msg->add_conn.me.virtual_ip && msg->add_conn.me.sourceip)
1591 {
1592 my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
1593 }
1594 if (msg->add_conn.other.virtual_ip && msg->add_conn.other.sourceip)
1595 {
1596 other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
1597 }
1598
1599 if (msg->add_conn.me.tohost)
1600 {
1601 my_ts = traffic_selector_create_dynamic(msg->add_conn.me.protocol,
1602 my_host->get_family(my_host) == AF_INET ?
1603 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
1604 msg->add_conn.me.port ? msg->add_conn.me.port : 0,
1605 msg->add_conn.me.port ? msg->add_conn.me.port : 65535);
1606 }
1607 else
1608 {
1609 my_ts = traffic_selector_create_from_subnet(my_subnet,
1610 msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 0,
1611 msg->add_conn.me.protocol, msg->add_conn.me.port);
1612 }
1613 my_subnet->destroy(my_subnet);
1614
1615 if (msg->add_conn.other.tohost)
1616 {
1617 other_ts = traffic_selector_create_dynamic(msg->add_conn.other.protocol,
1618 other_host->get_family(other_host) == AF_INET ?
1619 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE,
1620 msg->add_conn.other.port ? msg->add_conn.other.port : 0,
1621 msg->add_conn.other.port ? msg->add_conn.other.port : 65535);
1622 }
1623 else
1624 {
1625 other_ts = traffic_selector_create_from_subnet(other_subnet,
1626 msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 0,
1627 msg->add_conn.other.protocol, msg->add_conn.other.port);
1628 }
1629 other_subnet->destroy(other_subnet);
1630
1631 if (msg->add_conn.me.ca)
1632 {
1633 if (streq(msg->add_conn.me.ca, "%same"))
1634 {
1635 my_ca_same = TRUE;
1636 }
1637 else
1638 {
1639 my_ca = identification_create_from_string(msg->add_conn.me.ca);
1640 }
1641 }
1642 if (msg->add_conn.other.ca)
1643 {
1644 if (streq(msg->add_conn.other.ca, "%same"))
1645 {
1646 other_ca_same = TRUE;
1647 }
1648 else
1649 {
1650 other_ca = identification_create_from_string(msg->add_conn.other.ca);
1651 }
1652 }
1653 if (msg->add_conn.me.cert)
1654 {
1655 load_peer_cert(this, msg->add_conn.me.cert, &my_id);
1656 }
1657 if (msg->add_conn.other.cert)
1658 {
1659 load_peer_cert(this, msg->add_conn.other.cert, &other_id);
1660 }
1661 if (other_ca_same && my_ca)
1662 {
1663 other_ca = my_ca->clone(my_ca);
1664 }
1665 else if (my_ca_same && other_ca)
1666 {
1667 my_ca = other_ca->clone(other_ca);
1668 }
1669
1670 if (my_ca)
1671 {
1672 DBG2(DBG_CFG, " my ca: %D", my_ca);
1673 }
1674 if (other_ca)
1675 {
1676 DBG2(DBG_CFG, " other ca: %D", other_ca);
1677 }
1678
1679 if (msg->add_conn.other.groups)
1680 {
1681 /* TODO: AC groups */
1682 }
1683
1684 /* TODO: update matching */
1685 /* have a look for an (almost) identical peer config to reuse */
1686 enumerator = create_peer_cfg_enumerator(&this->configs, NULL, NULL);
1687 while (enumerator->enumerate(enumerator, &peer_cfg))
1688 {
1689 host_t *my_vip_conf, *other_vip_conf;
1690 bool my_vip_equals = FALSE, other_vip_equals = FALSE;
1691
1692 my_vip_conf = peer_cfg->get_my_virtual_ip(peer_cfg);
1693 if ((my_vip && my_vip_conf && my_vip->equals(my_vip, my_vip_conf)) ||
1694 (!my_vip_conf && !my_vip))
1695 {
1696 my_vip_equals = TRUE;
1697 }
1698 DESTROY_IF(my_vip_conf);
1699 other_vip_conf = peer_cfg->get_other_virtual_ip(peer_cfg, NULL);
1700 if ((other_vip && other_vip_conf && other_vip->equals(other_vip, other_vip_conf)) ||
1701 (!other_vip_conf && !other_vip))
1702 {
1703 other_vip_equals = TRUE;
1704 }
1705 DESTROY_IF(other_vip_conf);
1706
1707 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
1708 if (my_id->equals(my_id, peer_cfg->get_my_id(peer_cfg))
1709 && other_id->equals(other_id, peer_cfg->get_other_id(peer_cfg))
1710 && my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg))
1711 && other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg))
1712 && peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
1713 && peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
1714 && peer_cfg->get_eap_type(peer_cfg, &vendor) == msg->add_conn.eap_type
1715 && vendor == msg->add_conn.eap_vendor
1716 && my_vip_equals && other_vip_equals)
1717 {
1718 DBG1(DBG_CFG, "reusing existing configuration '%s'",
1719 peer_cfg->get_name(peer_cfg));
1720 use_existing = TRUE;
1721 break;
1722 }
1723 }
1724 enumerator->destroy(enumerator);
1725
1726 if (use_existing)
1727 {
1728 DESTROY_IF(my_vip);
1729 DESTROY_IF(other_vip);
1730 my_host->destroy(my_host);
1731 my_id->destroy(my_id);
1732 DESTROY_IF(my_ca);
1733 other_host->destroy(other_host);
1734 other_id->destroy(other_id);
1735 DESTROY_IF(other_ca);
1736 DESTROY_IF(peer_id);
1737 DESTROY_IF(mediated_by_cfg);
1738 }
1739 else
1740 {
1741 ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
1742 msg->add_conn.force_encap, my_host, other_host);
1743
1744 if (msg->add_conn.algorithms.ike)
1745 {
1746 char *proposal_string;
1747 char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1;
1748
1749 if (*strict == '!')
1750 *strict = '\0';
1751 else
1752 strict = NULL;
1753
1754 while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ",")))
1755 {
1756 proposal = proposal_create_from_string(PROTO_IKE, proposal_string);
1757 if (proposal == NULL)
1758 {
1759 DBG1(DBG_CFG, "invalid IKE proposal string: %s", proposal_string);
1760 my_id->destroy(my_id);
1761 other_id->destroy(other_id);
1762 my_ts->destroy(my_ts);
1763 other_ts->destroy(other_ts);
1764 DESTROY_IF(my_ca);
1765 DESTROY_IF(other_ca);
1766 ike_cfg->destroy(ike_cfg);
1767 return;
1768 }
1769 ike_cfg->add_proposal(ike_cfg, proposal);
1770 }
1771 if (!strict)
1772 {
1773 proposal = proposal_create_default(PROTO_IKE);
1774 ike_cfg->add_proposal(ike_cfg, proposal);
1775 }
1776 }
1777 else
1778 {
1779 proposal = proposal_create_default(PROTO_IKE);
1780 ike_cfg->add_proposal(ike_cfg, proposal);
1781 }
1782
1783 u_int32_t rekey = 0, reauth = 0, over, jitter;
1784 cert_validation_t valid;
1785
1786 jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
1787 over = msg->add_conn.rekey.margin;
1788 if (msg->add_conn.rekey.reauth)
1789 {
1790 reauth = msg->add_conn.rekey.ike_lifetime - over;
1791 }
1792 else
1793 {
1794 rekey = msg->add_conn.rekey.ike_lifetime - over;
1795 }
1796
1797 peer_cfg = peer_cfg_create(msg->add_conn.name,
1798 msg->add_conn.ikev2 ? 2 : 1, ike_cfg, my_id, other_id,
1799 msg->add_conn.me.sendcert, msg->add_conn.auth_method,
1800 msg->add_conn.eap_type, msg->add_conn.eap_vendor,
1801 msg->add_conn.rekey.tries, rekey, reauth, jitter, over,
1802 msg->add_conn.mobike,
1803 msg->add_conn.dpd.delay, msg->add_conn.dpd.action, my_vip, other_vip,
1804 msg->add_conn.p2p.mediation, mediated_by_cfg, peer_id);
1805 auth = peer_cfg->get_auth(peer_cfg);
1806 switch (msg->add_conn.crl_policy)
1807 {
1808 case CRL_STRICT_YES:
1809 valid = VALIDATION_GOOD;
1810 auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
1811 break;
1812 case CRL_STRICT_IFURI:
1813 valid = VALIDATION_SKIPPED;
1814 auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
1815 break;
1816 default:
1817 break;
1818 }
1819
1820 if (other_ca)
1821 {
1822 DBG1(DBG_CFG, " required other CA: %D", other_ca);
1823 certificate_t *cert = charon->credentials->get_cert(charon->credentials,
1824 CERT_X509, KEY_ANY, other_ca, TRUE);
1825 if (!cert)
1826 {
1827 DBG1(DBG_CFG, "deleted connection '%s': "
1828 "no trusted certificate found for required other CA",
1829 msg->add_conn.name);
1830 peer_cfg->destroy(peer_cfg);
1831 other_ca->destroy(other_ca);
1832 my_ts->destroy(my_ts);
1833 other_ts->destroy(other_ts);
1834 return;
1835 }
1836 /* require peer to authenticate against this cert */
1837 auth->add_item(auth, AUTHZ_CA_CERT, cert);
1838 cert->destroy(cert);
1839 other_ca->destroy(other_ca);
1840 }
1841 if (my_ca)
1842 {
1843 certificate_t *cert = charon->credentials->get_cert(charon->credentials,
1844 CERT_X509, KEY_ANY, my_ca, TRUE);
1845 if (!cert)
1846 {
1847 DBG1(DBG_CFG, "deleted connection '%s': "
1848 "no trusted certificate found for my CA",
1849 msg->add_conn.name);
1850 peer_cfg->destroy(peer_cfg);
1851 my_ca->destroy(my_ca);
1852 my_ts->destroy(my_ts);
1853 other_ts->destroy(other_ts);
1854 return;
1855 }
1856 /* we authenticate against this cert */
1857 auth->add_item(auth, AUTHN_CA_CERT, cert);
1858 cert->destroy(cert);
1859 }
1860 }
1861 child_cfg = child_cfg_create(
1862 msg->add_conn.name, msg->add_conn.rekey.ipsec_lifetime,
1863 msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
1864 msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100,
1865 msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
1866 msg->add_conn.mode);
1867
1868 peer_cfg->add_child_cfg(peer_cfg, child_cfg);
1869
1870 child_cfg->add_traffic_selector(child_cfg, TRUE, my_ts);
1871 child_cfg->add_traffic_selector(child_cfg, FALSE, other_ts);
1872
1873 if (msg->add_conn.algorithms.esp)
1874 {
1875 char *proposal_string;
1876 char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1;
1877
1878 if (*strict == '!')
1879 *strict = '\0';
1880 else
1881 strict = NULL;
1882
1883 while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ",")))
1884 {
1885 proposal = proposal_create_from_string(PROTO_ESP, proposal_string);
1886 if (proposal == NULL)
1887 {
1888 DBG1(DBG_CFG, "invalid ESP proposal string: %s", proposal_string);
1889 peer_cfg->destroy(peer_cfg);
1890 return;
1891 }
1892 child_cfg->add_proposal(child_cfg, proposal);
1893 }
1894 if (!strict)
1895 {
1896 proposal = proposal_create_default(PROTO_ESP);
1897 child_cfg->add_proposal(child_cfg, proposal);
1898 }
1899 }
1900 else
1901 {
1902 proposal = proposal_create_default(PROTO_ESP);
1903 child_cfg->add_proposal(child_cfg, proposal);
1904 }
1905
1906 if (!use_existing)
1907 {
1908 /* add config to backend */
1909 this->configs.mutex->lock(this->configs.mutex);
1910 this->configs.list->insert_last(this->configs.list, peer_cfg);
1911 this->configs.mutex->unlock(this->configs.mutex);
1912 DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]",
1913 msg->add_conn.name, my_host, my_id, other_host, other_id);
1914 }
1915 return;
1916
1917 /* mopping up after parsing errors */
1918
1919 destroy_ids:
1920 my_id->destroy(my_id);
1921 other_id->destroy(other_id);
1922 DESTROY_IF(mediated_by_cfg);
1923 DESTROY_IF(peer_id);
1924
1925 destroy_hosts:
1926 my_host->destroy(my_host);
1927 other_host->destroy(other_host);
1928 }
1929
1930 /**
1931 * Delete a connection from the list
1932 */
1933 static void stroke_del_conn(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
1934 {
1935 enumerator_t *enumerator, *children;
1936 peer_cfg_t *peer;
1937 child_cfg_t *child;
1938
1939 pop_string(msg, &(msg->del_conn.name));
1940 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
1941
1942 this->configs.mutex->lock(this->configs.mutex);
1943 enumerator = this->configs.list->create_enumerator(this->configs.list);
1944 while (enumerator->enumerate(enumerator, (void**)&peer))
1945 {
1946 /* remove peer config with such a name */
1947 if (streq(peer->get_name(peer), msg->del_conn.name))
1948 {
1949 this->configs.list->remove_at(this->configs.list, enumerator);
1950 peer->destroy(peer);
1951 continue;
1952 }
1953 /* remove any child with such a name */
1954 children = peer->create_child_cfg_enumerator(peer);
1955 while (children->enumerate(children, &child))
1956 {
1957 if (streq(child->get_name(child), msg->del_conn.name))
1958 {
1959 peer->remove_child_cfg(peer, enumerator);
1960 child->destroy(child);
1961 }
1962 }
1963 children->destroy(children);
1964 }
1965 enumerator->destroy(enumerator);
1966 this->configs.mutex->unlock(this->configs.mutex);
1967
1968 fprintf(out, "deleted connection '%s'\n", msg->del_conn.name);
1969 }
1970
1971 /**
1972 * get the child_cfg with the same name as the peer cfg
1973 */
1974 static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
1975 {
1976 child_cfg_t *current, *found = NULL;
1977 enumerator_t *enumerator;
1978
1979 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1980 while (enumerator->enumerate(enumerator, &current))
1981 {
1982 if (streq(current->get_name(current), name))
1983 {
1984 found = current;
1985 found->get_ref(found);
1986 break;
1987 }
1988 }
1989 enumerator->destroy(enumerator);
1990 return found;
1991 }
1992
1993 /**
1994 * logging to the stroke interface
1995 */
1996 static bool stroke_log(stroke_log_info_t *info, signal_t signal, level_t level,
1997 ike_sa_t *ike_sa, char *format, va_list args)
1998 {
1999 if (level <= info->level)
2000 {
2001 if (vfprintf(info->out, format, args) < 0 ||
2002 fprintf(info->out, "\n") < 0 ||
2003 fflush(info->out) != 0)
2004 {
2005 return FALSE;
2006 }
2007 }
2008 return TRUE;
2009 }
2010
2011 /**
2012 * initiate a connection by name
2013 */
2014 static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2015 {
2016 peer_cfg_t *peer_cfg;
2017 child_cfg_t *child_cfg;
2018 stroke_log_info_t info;
2019
2020 pop_string(msg, &(msg->initiate.name));
2021 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
2022
2023 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
2024 msg->initiate.name);
2025 if (peer_cfg == NULL)
2026 {
2027 fprintf(out, "no config named '%s'\n", msg->initiate.name);
2028 return;
2029 }
2030 if (peer_cfg->get_ike_version(peer_cfg) != 2)
2031 {
2032 DBG1(DBG_CFG, "ignoring initiation request for IKEv%d config",
2033 peer_cfg->get_ike_version(peer_cfg));
2034 peer_cfg->destroy(peer_cfg);
2035 return;
2036 }
2037
2038 child_cfg = get_child_from_peer(peer_cfg, msg->initiate.name);
2039 if (child_cfg == NULL)
2040 {
2041 fprintf(out, "no child config named '%s'\n", msg->initiate.name);
2042 peer_cfg->destroy(peer_cfg);
2043 return;
2044 }
2045
2046 if (msg->output_verbosity < 0)
2047 {
2048 charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
2049 NULL, NULL);
2050 }
2051 else
2052 {
2053 info.out = out;
2054 info.level = msg->output_verbosity;
2055 charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
2056 (controller_cb_t)stroke_log, &info);
2057 }
2058 }
2059
2060 /**
2061 * route a policy (install SPD entries)
2062 */
2063 static void stroke_route(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2064 {
2065 peer_cfg_t *peer_cfg;
2066 child_cfg_t *child_cfg;
2067 stroke_log_info_t info;
2068
2069 pop_string(msg, &(msg->route.name));
2070 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
2071
2072 peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends,
2073 msg->route.name);
2074 if (peer_cfg == NULL)
2075 {
2076 fprintf(out, "no config named '%s'\n", msg->route.name);
2077 return;
2078 }
2079 if (peer_cfg->get_ike_version(peer_cfg) != 2)
2080 {
2081 peer_cfg->destroy(peer_cfg);
2082 return;
2083 }
2084
2085 child_cfg = get_child_from_peer(peer_cfg, msg->route.name);
2086 if (child_cfg == NULL)
2087 {
2088 fprintf(out, "no child config named '%s'\n", msg->route.name);
2089 peer_cfg->destroy(peer_cfg);
2090 return;
2091 }
2092
2093 info.out = out;
2094 info.level = msg->output_verbosity;
2095 charon->controller->route(charon->controller, peer_cfg, child_cfg,
2096 (controller_cb_t)stroke_log, &info);
2097 peer_cfg->destroy(peer_cfg);
2098 child_cfg->destroy(child_cfg);
2099 }
2100
2101 /**
2102 * unroute a policy
2103 */
2104 static void stroke_unroute(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2105 {
2106 char *name;
2107 ike_sa_t *ike_sa;
2108 iterator_t *iterator;
2109 stroke_log_info_t info;
2110
2111 pop_string(msg, &(msg->terminate.name));
2112 name = msg->terminate.name;
2113
2114 info.out = out;
2115 info.level = msg->output_verbosity;
2116
2117 iterator = charon->controller->create_ike_sa_iterator(charon->controller);
2118 while (iterator->iterate(iterator, (void**)&ike_sa))
2119 {
2120 child_sa_t *child_sa;
2121 iterator_t *children;
2122 u_int32_t id;
2123
2124 children = ike_sa->create_child_sa_iterator(ike_sa);
2125 while (children->iterate(children, (void**)&child_sa))
2126 {
2127 if (child_sa->get_state(child_sa) == CHILD_ROUTED &&
2128 streq(name, child_sa->get_name(child_sa)))
2129 {
2130 id = child_sa->get_reqid(child_sa);
2131 children->destroy(children);
2132 iterator->destroy(iterator);
2133 charon->controller->unroute(charon->controller, id,
2134 (controller_cb_t)stroke_log, &info);
2135 return;
2136 }
2137 }
2138 children->destroy(children);
2139 }
2140 iterator->destroy(iterator);
2141 DBG1(DBG_CFG, "no such SA found");
2142 }
2143
2144 /**
2145 * terminate a connection by name
2146 */
2147 static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2148 {
2149 char *string, *pos = NULL, *name = NULL;
2150 u_int32_t id = 0;
2151 bool child;
2152 int len;
2153 ike_sa_t *ike_sa;
2154 iterator_t *iterator;
2155 stroke_log_info_t info;
2156
2157 pop_string(msg, &(msg->terminate.name));
2158 string = msg->terminate.name;
2159 DBG1(DBG_CFG, "received stroke: terminate '%s'", string);
2160
2161 len = strlen(string);
2162 if (len < 1)
2163 {
2164 DBG1(DBG_CFG, "error parsing string");
2165 return;
2166 }
2167 switch (string[len-1])
2168 {
2169 case '}':
2170 child = TRUE;
2171 pos = strchr(string, '{');
2172 break;
2173 case ']':
2174 child = FALSE;
2175 pos = strchr(string, '[');
2176 break;
2177 default:
2178 name = string;
2179 child = FALSE;
2180 break;
2181 }
2182
2183 if (name)
2184 {
2185 /* is a single name */
2186 }
2187 else if (pos == string + len - 2)
2188 { /* is name[] or name{} */
2189 string[len-2] = '\0';
2190 name = string;
2191 }
2192 else
2193 { /* is name[123] or name{23} */
2194 string[len-1] = '\0';
2195 id = atoi(pos + 1);
2196 if (id == 0)
2197 {
2198 DBG1(DBG_CFG, "error parsing string");
2199 return;
2200 }
2201 }
2202
2203 info.out = out;
2204 info.level = msg->output_verbosity;
2205
2206 iterator = charon->controller->create_ike_sa_iterator(charon->controller);
2207 while (iterator->iterate(iterator, (void**)&ike_sa))
2208 {
2209 child_sa_t *child_sa;
2210 iterator_t *children;
2211
2212 if (child)
2213 {
2214 children = ike_sa->create_child_sa_iterator(ike_sa);
2215 while (children->iterate(children, (void**)&child_sa))
2216 {
2217 if ((name && streq(name, child_sa->get_name(child_sa))) ||
2218 (id && id == child_sa->get_reqid(child_sa)))
2219 {
2220 id = child_sa->get_reqid(child_sa);
2221 children->destroy(children);
2222 iterator->destroy(iterator);
2223
2224 charon->controller->terminate_child(charon->controller, id,
2225 (controller_cb_t)stroke_log, &info);
2226 return;
2227 }
2228 }
2229 children->destroy(children);
2230 }
2231 else if ((name && streq(name, ike_sa->get_name(ike_sa))) ||
2232 (id && id == ike_sa->get_unique_id(ike_sa)))
2233 {
2234 id = ike_sa->get_unique_id(ike_sa);
2235 /* unlock manager first */
2236 iterator->destroy(iterator);
2237
2238 charon->controller->terminate_ike(charon->controller, id,
2239 (controller_cb_t)stroke_log, &info);
2240 return;
2241 }
2242
2243 }
2244 iterator->destroy(iterator);
2245 DBG1(DBG_CFG, "no such SA found");
2246 }
2247
2248 /**
2249 * Add a ca information record to the cainfo list
2250 */
2251 static void stroke_add_ca(private_stroke_t *this,
2252 stroke_msg_t *msg, FILE *out)
2253 {
2254 certificate_t *cert;
2255 ca_section_t *ca;
2256
2257 pop_string(msg, &msg->add_ca.name);
2258 pop_string(msg, &msg->add_ca.cacert);
2259 pop_string(msg, &msg->add_ca.crluri);
2260 pop_string(msg, &msg->add_ca.crluri2);
2261 pop_string(msg, &msg->add_ca.ocspuri);
2262 pop_string(msg, &msg->add_ca.ocspuri2);
2263
2264 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
2265
2266 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
2267 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
2268 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
2269 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
2270 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
2271 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
2272
2273 if (msg->add_ca.cacert == NULL)
2274 {
2275 DBG1(DBG_CFG, "missing cacert parameter");
2276 return;
2277 }
2278
2279 cert = load_ca_cert(this, msg->add_ca.cacert);
2280 if (cert)
2281 {
2282 ca = ca_section_create(msg->add_ca.name, cert);
2283 if (msg->add_ca.crluri)
2284 {
2285 ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri));
2286 }
2287 if (msg->add_ca.crluri2)
2288 {
2289 ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri2));
2290 }
2291 if (msg->add_ca.ocspuri)
2292 {
2293 ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri));
2294 }
2295 if (msg->add_ca.ocspuri2)
2296 {
2297 ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri2));
2298 }
2299 this->ca_creds.mutex->lock(this->ca_creds.mutex);
2300 this->ca_creds.sections->insert_last(this->ca_creds.sections, ca);
2301 this->ca_creds.mutex->unlock(this->ca_creds.mutex);
2302 DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
2303 }
2304 }
2305
2306 /**
2307 * Delete a ca information record from the cainfo list
2308 */
2309 static void stroke_del_ca(private_stroke_t *this,
2310 stroke_msg_t *msg, FILE *out)
2311 {
2312 enumerator_t *enumerator;
2313 ca_section_t *ca = NULL;
2314
2315 pop_string(msg, &(msg->del_ca.name));
2316 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
2317
2318 this->ca_creds.mutex->lock(this->ca_creds.mutex);
2319 enumerator = this->ca_creds.sections->create_enumerator(this->ca_creds.sections);
2320 while (enumerator->enumerate(enumerator, &ca))
2321 {
2322 if (streq(ca->name, msg->del_ca.name))
2323 {
2324 this->ca_creds.sections->remove_at(this->ca_creds.sections, enumerator);
2325 break;
2326 }
2327 ca = NULL;
2328 }
2329 enumerator->destroy(enumerator);
2330 this->ca_creds.mutex->unlock(this->ca_creds.mutex);
2331 if (ca == NULL)
2332 {
2333 fprintf(out, "no ca named '%s' found\n", msg->del_ca.name);
2334 return;
2335 }
2336 ca_section_destroy(ca);
2337 /* TODO: flush cached certs */
2338 }
2339
2340 /**
2341 * log an IKE_SA to out
2342 */
2343 static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
2344 {
2345 ike_sa_id_t *id = ike_sa->get_id(ike_sa);
2346 u_int32_t rekey, reauth;
2347
2348 fprintf(out, "%12s[%d]: %N, %H[%D]...%H[%D]\n",
2349 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
2350 ike_sa_state_names, ike_sa->get_state(ike_sa),
2351 ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
2352 ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
2353
2354 if (all)
2355 {
2356 fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s",
2357 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
2358 id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
2359 id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
2360
2361 rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY_TIME);
2362 reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH_TIME);
2363 if (rekey)
2364 {
2365 fprintf(out, ", rekeying in %V", &rekey);
2366 }
2367 if (reauth)
2368 {
2369 fprintf(out, ", reauthentication in %V", &reauth);
2370 }
2371 if (!rekey && !reauth)
2372 {
2373 fprintf(out, ", rekeying disabled");
2374 }
2375 fprintf(out, "\n");
2376 }
2377 }
2378
2379 /**
2380 * log an CHILD_SA to out
2381 */
2382 static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
2383 {
2384 u_int32_t rekey, now = time(NULL);
2385 u_int32_t use_in, use_out, use_fwd;
2386 encryption_algorithm_t encr_alg;
2387 integrity_algorithm_t int_alg;
2388 size_t encr_len, int_len;
2389 mode_t mode;
2390
2391 child_sa->get_stats(child_sa, &mode, &encr_alg, &encr_len,
2392 &int_alg, &int_len, &rekey, &use_in, &use_out,
2393 &use_fwd);
2394
2395 fprintf(out, "%12s{%d}: %N, %N",
2396 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
2397 child_sa_state_names, child_sa->get_state(child_sa),
2398 mode_names, mode);
2399
2400 if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
2401 {
2402 fprintf(out, ", %N SPIs: %.8x_i %.8x_o",
2403 protocol_id_names, child_sa->get_protocol(child_sa),
2404 htonl(child_sa->get_spi(child_sa, TRUE)),
2405 htonl(child_sa->get_spi(child_sa, FALSE)));
2406
2407 if (all)
2408 {
2409 fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa),
2410 child_sa->get_reqid(child_sa));
2411
2412
2413 if (child_sa->get_protocol(child_sa) == PROTO_ESP)
2414 {
2415 fprintf(out, "%N", encryption_algorithm_names, encr_alg);
2416
2417 if (encr_len)
2418 {
2419 fprintf(out, "-%d", encr_len);
2420 }
2421 fprintf(out, "/");
2422 }
2423
2424 fprintf(out, "%N", integrity_algorithm_names, int_alg);
2425 if (int_len)
2426 {
2427 fprintf(out, "-%d", int_len);
2428 }
2429 fprintf(out, ", rekeying ");
2430
2431 if (rekey)
2432 {
2433 fprintf(out, "in %#V", &now, &rekey);
2434 }
2435 else
2436 {
2437 fprintf(out, "disabled");
2438 }
2439
2440 fprintf(out, ", last use: ");
2441 use_in = max(use_in, use_fwd);
2442 if (use_in)
2443 {
2444 fprintf(out, "%ds_i ", now - use_in);
2445 }
2446 else
2447 {
2448 fprintf(out, "no_i ");
2449 }
2450 if (use_out)
2451 {
2452 fprintf(out, "%ds_o ", now - use_out);
2453 }
2454 else
2455 {
2456 fprintf(out, "no_o ");
2457 }
2458 }
2459 }
2460
2461 fprintf(out, "\n%12s{%d}: %#R=== %#R\n",
2462 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
2463 child_sa->get_traffic_selectors(child_sa, TRUE),
2464 child_sa->get_traffic_selectors(child_sa, FALSE));
2465 }
2466
2467 /**
2468 * show status of daemon
2469 */
2470 static void stroke_status(private_stroke_t *this, stroke_msg_t *msg, FILE *out,
2471 bool all)
2472 {
2473 enumerator_t *enumerator, *children;
2474 iterator_t *iterator;
2475 host_t *host;
2476 peer_cfg_t *peer_cfg;
2477 ike_cfg_t *ike_cfg;
2478 child_cfg_t *child_cfg;
2479 ike_sa_t *ike_sa;
2480 char *name = NULL;
2481
2482 if (msg->status.name)
2483 {
2484 pop_string(msg, &(msg->status.name));
2485 name = msg->status.name;
2486 }
2487
2488 if (all)
2489 {
2490 fprintf(out, "Performance:\n");
2491 fprintf(out, " worker threads: %d idle of %d,",
2492 charon->processor->get_idle_threads(charon->processor),
2493 charon->processor->get_total_threads(charon->processor));
2494 fprintf(out, " job queue load: %d,",
2495 charon->processor->get_job_load(charon->processor));
2496 fprintf(out, " scheduled events: %d\n",
2497 charon->scheduler->get_job_load(charon->scheduler));
2498 iterator = charon->kernel_interface->create_address_iterator(
2499 charon->kernel_interface);
2500 fprintf(out, "Listening IP addresses:\n");
2501 while (iterator->iterate(iterator, (void**)&host))
2502 {
2503 fprintf(out, " %H\n", host);
2504 }
2505 iterator->destroy(iterator);
2506
2507 fprintf(out, "Connections:\n");
2508 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends);
2509 while (enumerator->enumerate(enumerator, (void**)&peer_cfg))
2510 {
2511 if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
2512 (name && !streq(name, peer_cfg->get_name(peer_cfg))))
2513 {
2514 continue;
2515 }
2516
2517 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
2518 fprintf(out, "%12s: %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
2519 ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
2520 ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
2521 /* TODO: list CAs and groups */
2522 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
2523 while (children->enumerate(children, &child_cfg))
2524 {
2525 linked_list_t *my_ts, *other_ts;
2526 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
2527 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
2528 fprintf(out, "%12s: %#R=== %#R\n", child_cfg->get_name(child_cfg),
2529 my_ts, other_ts);
2530 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
2531 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
2532 }
2533 children->destroy(children);
2534 }
2535 enumerator->destroy(enumerator);
2536 }
2537
2538 iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
2539 if (all && iterator->get_count(iterator) > 0)
2540 {
2541 fprintf(out, "Security Associations:\n");
2542 }
2543 while (iterator->iterate(iterator, (void**)&ike_sa))
2544 {
2545 bool ike_printed = FALSE;
2546 child_sa_t *child_sa;
2547 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
2548
2549 if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
2550 {
2551 log_ike_sa(out, ike_sa, all);
2552 ike_printed = TRUE;
2553 }
2554
2555 while (children->iterate(children, (void**)&child_sa))
2556 {
2557 if (name == NULL || streq(name, child_sa->get_name(child_sa)))
2558 {
2559 if (!ike_printed)
2560 {
2561 log_ike_sa(out, ike_sa, all);
2562 ike_printed = TRUE;
2563 }
2564 log_child_sa(out, child_sa, all);
2565 }
2566 }
2567 children->destroy(children);
2568 }
2569 iterator->destroy(iterator);
2570 }
2571
2572 /**
2573 * list all X.509 certificates matching the flags
2574 */
2575 static void stroke_list_certs(char *label, x509_flag_t flags, bool utc, FILE *out)
2576 {
2577 bool first = TRUE;
2578 time_t now = time(NULL);
2579 certificate_t *cert;
2580 enumerator_t *enumerator;
2581
2582 enumerator = charon->credentials->create_cert_enumerator(
2583 charon->credentials, CERT_X509, KEY_ANY, NULL, FALSE);
2584 while (enumerator->enumerate(enumerator, (void**)&cert))
2585 {
2586 x509_t *x509 = (x509_t*)cert;
2587 x509_flag_t x509_flags = x509->get_flags(x509);
2588
2589 /* list only if flag is set, or flags == 0 (ignoring self-signed) */
2590 if ((x509_flags & flags) || (flags == (x509_flags & ~X509_SELF_SIGNED)))
2591 {
2592 enumerator_t *enumerator;
2593 identification_t *altName;
2594 bool first_altName = TRUE;
2595 chunk_t serial = x509->get_serial(x509);
2596 identification_t *authkey = x509->get_authKeyIdentifier(x509);
2597 time_t notBefore, notAfter;
2598 public_key_t *public = cert->get_public_key(cert);
2599
2600 if (first)
2601 {
2602 fprintf(out, "\n");
2603 fprintf(out, "List of %s:\n", label);
2604 first = FALSE;
2605 }
2606 fprintf(out, "\n");
2607
2608 /* list subjectAltNames */
2609 enumerator = x509->create_subjectAltName_enumerator(x509);
2610 while (enumerator->enumerate(enumerator, (void**)&altName))
2611 {
2612 if (first_altName)
2613 {
2614 fprintf(out, " altNames: ");
2615 first_altName = FALSE;
2616 }
2617 else
2618 {
2619 fprintf(out, ", ");
2620 }
2621 fprintf(out, "%D", altName);
2622 }
2623 if (!first_altName)
2624 {
2625 fprintf(out, "\n");
2626 }
2627 enumerator->destroy(enumerator);
2628
2629 fprintf(out, " subject: %D\n", cert->get_subject(cert));
2630 fprintf(out, " issuer: %D\n", cert->get_issuer(cert));
2631 fprintf(out, " serial: %#B\n", &serial);
2632
2633 /* list validity */
2634 cert->get_validity(cert, &now, &notBefore, &notAfter);
2635 fprintf(out, " validity: not before %#T, ", &notBefore, utc);
2636 if (now < notBefore)
2637 {
2638 fprintf(out, "not valid yet (valid in %#V)\n", &now, &notBefore);
2639 }
2640 else
2641 {
2642 fprintf(out, "ok\n");
2643 }
2644 fprintf(out, " not after %#T, ", &notAfter, utc);
2645 if (now > notAfter)
2646 {
2647 fprintf(out, "expired (%#V ago)\n", &now, &notAfter);
2648 }
2649 else
2650 {
2651 fprintf(out, "ok");
2652 if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
2653 {
2654 fprintf(out, " (expires in %#V)", &now, &notAfter);
2655 }
2656 fprintf(out, " \n");
2657 }
2658
2659 /* list public key information */
2660 if (public)
2661 {
2662 private_key_t *private = NULL;
2663 identification_t *id, *keyid;
2664
2665 id = public->get_id(public, ID_PUBKEY_SHA1);
2666 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
2667
2668 private = charon->credentials->get_private(
2669 charon->credentials,
2670 public->get_type(public), keyid, NULL);
2671 fprintf(out, " pubkey: %N %d bits%s\n",
2672 key_type_names, public->get_type(public),
2673 public->get_keysize(public) * 8,
2674 private ? ", has private key" : "");
2675 fprintf(out, " keyid: %D\n", keyid);
2676 fprintf(out, " subjkey: %D\n", id);
2677 DESTROY_IF(private);
2678 public->destroy(public);
2679 }
2680
2681 /* list optional authorityKeyIdentifier */
2682 if (authkey)
2683 {
2684 fprintf(out, " authkey: %D\n", authkey);
2685 }
2686 }
2687 }
2688 enumerator->destroy(enumerator);
2689 }
2690
2691 /**
2692 * list all X.509 CRLs
2693 */
2694 static void stroke_list_crls(bool utc, FILE *out)
2695 {
2696 bool first = TRUE;
2697 time_t thisUpdate, nextUpdate, now = time(NULL);
2698 certificate_t *cert;
2699 enumerator_t *enumerator;
2700
2701 enumerator = charon->credentials->create_cert_enumerator(
2702 charon->credentials, CERT_X509_CRL, KEY_ANY, NULL, FALSE);
2703 while (enumerator->enumerate(enumerator, (void**)&cert))
2704 {
2705 crl_t *crl = (crl_t*)cert;
2706 chunk_t serial = crl->get_serial(crl);
2707 identification_t *authkey = crl->get_authKeyIdentifier(crl);
2708
2709 if (first)
2710 {
2711 fprintf(out, "\n");
2712 fprintf(out, "List of X.509 CRLs:\n");
2713 first = FALSE;
2714 }
2715 fprintf(out, "\n");
2716
2717 fprintf(out, " issuer: %D\n", cert->get_issuer(cert));
2718
2719 /* list optional crlNumber */
2720 if (serial.ptr)
2721 {
2722 fprintf(out, " serial: %#B\n", &serial);
2723 }
2724
2725 /* count the number of revoked certificates */
2726 {
2727 int count = 0;
2728 enumerator_t *enumerator = crl->create_enumerator(crl);
2729
2730 while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
2731 {
2732 count++;
2733 }
2734 fprintf(out, " revoked: %d certificate%s\n", count,
2735 (count == 1)? "" : "s");
2736 enumerator->destroy(enumerator);
2737 }
2738
2739 /* list validity */
2740 cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
2741 fprintf(out, " updates: this %#T\n", &thisUpdate, utc);
2742 fprintf(out, " next %#T, ", &nextUpdate, utc);
2743 if (now > nextUpdate)
2744 {
2745 fprintf(out, "expired (%#V ago)\n", &now, &nextUpdate);
2746 }
2747 else
2748 {
2749 fprintf(out, "ok");
2750 if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
2751 {
2752 fprintf(out, " (expires in %#V)", &now, &nextUpdate);
2753 }
2754 fprintf(out, " \n");
2755 }
2756
2757 /* list optional authorityKeyIdentifier */
2758 if (authkey)
2759 {
2760 fprintf(out, " authkey: %D\n", authkey);
2761 }
2762 }
2763 enumerator->destroy(enumerator);
2764 }
2765
2766 /**
2767 * list all CA information sections
2768 */
2769 static void stroke_list_cainfos(private_stroke_t *this, FILE *out)
2770 {
2771 bool first = TRUE;
2772 ca_section_t *section;
2773 enumerator_t *enumerator;
2774
2775 this->ca_creds.mutex->lock(this->ca_creds.mutex);
2776 enumerator = this->ca_creds.sections->create_enumerator(this->ca_creds.sections);
2777 while (enumerator->enumerate(enumerator, (void**)&section))
2778 {
2779 certificate_t *cert = section->cert;
2780 public_key_t *public = cert->get_public_key(cert);
2781
2782 if (first)
2783 {
2784 fprintf(out, "\n");
2785 fprintf(out, "List of CA Information Sections:\n");
2786 first = FALSE;
2787 }
2788 fprintf(out, "\n");
2789 fprintf(out, " authname: %D\n", cert->get_subject(cert));
2790
2791 /* list authkey and keyid */
2792 if (public)
2793 {
2794 fprintf(out, " authkey: %D\n",
2795 public->get_id(public, ID_PUBKEY_SHA1));
2796 fprintf(out, " keyid: %D\n",
2797 public->get_id(public, ID_PUBKEY_INFO_SHA1));
2798 public->destroy(public);
2799 }
2800
2801 /* list CRL URIs */
2802 {
2803 bool first = TRUE;
2804 char *crluri;
2805 enumerator_t *enumerator;
2806
2807 enumerator = section->crl->create_enumerator(section->crl);
2808 while (enumerator->enumerate(enumerator, (void**)&crluri))
2809 {
2810 if (first)
2811 {
2812 fprintf(out, " crluris: ");
2813 first = FALSE;
2814 }
2815 else
2816 {
2817 fprintf(out, " ");
2818 }
2819 fprintf(out, "'%s'\n", crluri);
2820 }
2821 enumerator->destroy(enumerator);
2822 }
2823
2824 /* list OCSP URIs */
2825 {
2826 bool first = TRUE;
2827 char *ocspuri;
2828 enumerator_t *enumerator;
2829
2830 enumerator = section->ocsp->create_enumerator(section->ocsp);
2831 while (enumerator->enumerate(enumerator, (void**)&ocspuri))
2832 {
2833 if (first)
2834 {
2835 fprintf(out, " ocspuris: ");
2836 first = FALSE;
2837 }
2838 else
2839 {
2840 fprintf(out, " ");
2841 }
2842 fprintf(out, "'%s'\n", ocspuri);
2843 }
2844 enumerator->destroy(enumerator);
2845 }
2846 }
2847 enumerator->destroy(enumerator);
2848 this->ca_creds.mutex->unlock(this->ca_creds.mutex);
2849 }
2850
2851 /**
2852 * list various information
2853 */
2854 static void stroke_list(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2855 {
2856 if (msg->list.flags & LIST_CERTS)
2857 {
2858 stroke_list_certs("X.509 End Entity Certificates",
2859 0, msg->list.utc, out);
2860 }
2861 if (msg->list.flags & LIST_CACERTS)
2862 {
2863 stroke_list_certs("X.509 CA Certificates",
2864 X509_CA, msg->list.utc, out);
2865 }
2866 if (msg->list.flags & LIST_OCSPCERTS)
2867 {
2868 stroke_list_certs("X.509 OCSP Signer Certificates",
2869 X509_OCSP_SIGNER, msg->list.utc, out);
2870 }
2871 if (msg->list.flags & LIST_AACERTS)
2872 {
2873 stroke_list_certs("X.509 AA Certificates",
2874 X509_AA, msg->list.utc, out);
2875 }
2876 if (msg->list.flags & LIST_ACERTS)
2877 {
2878
2879 }
2880 if (msg->list.flags & LIST_CAINFOS)
2881 {
2882 stroke_list_cainfos(this, out);
2883 }
2884 if (msg->list.flags & LIST_CRLS)
2885 {
2886 stroke_list_crls(msg->list.utc, out);
2887 }
2888 if (msg->list.flags & LIST_OCSP)
2889 {
2890
2891 }
2892 }
2893
2894 /**
2895 * reread various information
2896 */
2897 static void stroke_reread(private_stroke_t *this,
2898 stroke_msg_t *msg, FILE *out)
2899 {
2900 if (msg->reread.flags & REREAD_SECRETS)
2901 {
2902 DBG1(DBG_CFG, "rereading secrets");
2903 load_secrets(this);
2904 }
2905 if (msg->reread.flags & REREAD_CACERTS)
2906 {
2907 DBG1(DBG_CFG, "rereading ca certificates from '%s'",
2908 CA_CERTIFICATE_DIR);
2909 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
2910 }
2911 if (msg->reread.flags & REREAD_OCSPCERTS)
2912 {
2913 DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
2914 OCSP_CERTIFICATE_DIR);
2915 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
2916 X509_OCSP_SIGNER);
2917 }
2918 if (msg->reread.flags & REREAD_AACERTS)
2919 {
2920 DBG1(DBG_CFG, "rereading aa certificates from '%s'",
2921 AA_CERTIFICATE_DIR);
2922 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
2923 }
2924 if (msg->reread.flags & REREAD_ACERTS)
2925 {
2926 DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
2927 ATTR_CERTIFICATE_DIR);
2928 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
2929 }
2930 if (msg->reread.flags & REREAD_CRLS)
2931 {
2932 DBG1(DBG_CFG, "rereading crls from '%s'",
2933 CRL_DIR);
2934 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
2935 }
2936 }
2937
2938 /**
2939 * purge various information
2940 */
2941 static void stroke_purge(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2942 {
2943 /* TODO: flush cache */
2944 }
2945
2946 signal_t get_signal_from_logtype(char *type)
2947 {
2948 if (strcasecmp(type, "any") == 0) return SIG_ANY;
2949 else if (strcasecmp(type, "mgr") == 0) return DBG_MGR;
2950 else if (strcasecmp(type, "ike") == 0) return DBG_IKE;
2951 else if (strcasecmp(type, "chd") == 0) return DBG_CHD;
2952 else if (strcasecmp(type, "job") == 0) return DBG_JOB;
2953 else if (strcasecmp(type, "cfg") == 0) return DBG_CFG;
2954 else if (strcasecmp(type, "knl") == 0) return DBG_KNL;
2955 else if (strcasecmp(type, "net") == 0) return DBG_NET;
2956 else if (strcasecmp(type, "enc") == 0) return DBG_ENC;
2957 else if (strcasecmp(type, "lib") == 0) return DBG_LIB;
2958 else return -1;
2959 }
2960
2961 /**
2962 * set the verbosity debug output
2963 */
2964 static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg, FILE *out)
2965 {
2966 signal_t signal;
2967
2968 pop_string(msg, &(msg->loglevel.type));
2969 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
2970 msg->loglevel.level, msg->loglevel.type);
2971
2972 signal = get_signal_from_logtype(msg->loglevel.type);
2973 if (signal < 0)
2974 {
2975 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
2976 return;
2977 }
2978
2979 charon->outlog->set_level(charon->outlog, signal, msg->loglevel.level);
2980 charon->syslog->set_level(charon->syslog, signal, msg->loglevel.level);
2981 }
2982
2983 typedef struct stroke_job_context_t stroke_job_context_t;
2984
2985 /** job context to pass to processing thread */
2986 struct stroke_job_context_t {
2987
2988 /** file descriptor to read from */
2989 int fd;
2990
2991 /** global stroke interface */
2992 private_stroke_t *this;
2993 };
2994
2995 /**
2996 * destroy a job context
2997 */
2998 static void stroke_job_context_destroy(stroke_job_context_t *this)
2999 {
3000 close(this->fd);
3001 free(this);
3002 }
3003
3004 /**
3005 * process a stroke request from the socket pointed by "fd"
3006 */
3007 static job_requeue_t stroke_process(stroke_job_context_t *ctx)
3008 {
3009 stroke_msg_t *msg;