2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
17 #include <sys/types.h>
27 #include "stroke_cred.h"
28 #include "stroke_shared_key.h"
30 #include <credentials/certificates/x509.h>
31 #include <credentials/certificates/crl.h>
32 #include <credentials/certificates/ac.h>
33 #include <credentials/sets/mem_cred.h>
34 #include <credentials/sets/callback_cred.h>
35 #include <utils/linked_list.h>
36 #include <utils/lexparser.h>
37 #include <threading/rwlock.h>
40 /* configuration directories and files */
41 #define CONFIG_DIR IPSEC_CONFDIR
42 #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
43 #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
44 #define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
45 #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
46 #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
47 #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
48 #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
49 #define CRL_DIR IPSEC_D_DIR "/crls"
50 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
52 #define MAX_SECRETS_RECURSION 10
54 typedef struct private_stroke_cred_t private_stroke_cred_t
;
57 * private data of stroke_cred
59 struct private_stroke_cred_t
{
67 * list of trusted peer/signer/CA certificates (certificate_t)
72 * list of shared secrets (private_shared_key_t)
74 linked_list_t
*shared
;
77 * list of private keys (private_key_t)
79 linked_list_t
*private;
82 * read-write lock to lists
93 * data to pass to various filters
96 private_stroke_cred_t
*this;
98 certificate_type_t cert
;
103 * destroy id enumerator data and unlock list
105 static void id_data_destroy(id_data_t
*data
)
107 data
->this->lock
->unlock(data
->this->lock
);
112 * filter function for private key enumerator
114 static bool private_filter(id_data_t
*data
,
115 private_key_t
**in
, private_key_t
**out
)
120 if (data
->key
== KEY_ANY
|| data
->key
== key
->get_type(key
))
122 if (data
->id
== NULL
)
127 if (key
->has_fingerprint(key
, data
->id
->get_encoding(data
->id
)))
137 * Implements credential_set_t.create_private_enumerator
139 static enumerator_t
* create_private_enumerator(private_stroke_cred_t
*this,
140 key_type_t type
, identification_t
*id
)
144 data
= malloc_thing(id_data_t
);
149 this->lock
->read_lock(this->lock
);
150 return enumerator_create_filter(this->private->create_enumerator(this->private),
151 (void*)private_filter
, data
,
152 (void*)id_data_destroy
);
156 * filter function for certs enumerator
158 static bool certs_filter(id_data_t
*data
, certificate_t
**in
, certificate_t
**out
)
160 public_key_t
*public;
161 certificate_t
*cert
= *in
;
163 if (data
->cert
!= CERT_ANY
&& data
->cert
!= cert
->get_type(cert
))
167 if (data
->id
== NULL
|| cert
->has_subject(cert
, data
->id
))
173 public = cert
->get_public_key(cert
);
176 if (data
->key
== KEY_ANY
|| data
->key
!= public->get_type(public))
178 if (public->has_fingerprint(public, data
->id
->get_encoding(data
->id
)))
180 public->destroy(public);
185 public->destroy(public);
191 * Implements credential_set_t.create_cert_enumerator
193 static enumerator_t
* create_cert_enumerator(private_stroke_cred_t
*this,
194 certificate_type_t cert
, key_type_t key
,
195 identification_t
*id
, bool trusted
)
199 if (trusted
&& (cert
== CERT_X509_CRL
|| cert
== CERT_X509_AC
))
203 data
= malloc_thing(id_data_t
);
209 this->lock
->read_lock(this->lock
);
210 return enumerator_create_filter(this->certs
->create_enumerator(this->certs
),
211 (void*)certs_filter
, data
,
212 (void*)id_data_destroy
);
216 private_stroke_cred_t
*this;
217 identification_t
*me
;
218 identification_t
*other
;
219 shared_key_type_t type
;
223 * free shared key enumerator data and unlock list
225 static void shared_data_destroy(shared_data_t
*data
)
227 data
->this->lock
->unlock(data
->this->lock
);
232 * filter function for certs enumerator
234 static bool shared_filter(shared_data_t
*data
,
235 stroke_shared_key_t
**in
, shared_key_t
**out
,
236 void **unused1
, id_match_t
*me
,
237 void **unused2
, id_match_t
*other
)
239 id_match_t my_match
= ID_MATCH_NONE
, other_match
= ID_MATCH_NONE
;
240 stroke_shared_key_t
*stroke
= *in
;
241 shared_key_t
*shared
= &stroke
->shared
;
243 if (data
->type
!= SHARED_ANY
&& shared
->get_type(shared
) != data
->type
)
250 my_match
= stroke
->has_owner(stroke
, data
->me
);
254 other_match
= stroke
->has_owner(stroke
, data
->other
);
256 if ((data
->me
|| data
->other
) && (!my_match
&& !other_match
))
267 *other
= other_match
;
273 * Implements credential_set_t.create_shared_enumerator
275 static enumerator_t
* create_shared_enumerator(private_stroke_cred_t
*this,
276 shared_key_type_t type
, identification_t
*me
,
277 identification_t
*other
)
279 shared_data_t
*data
= malloc_thing(shared_data_t
);
285 this->lock
->read_lock(this->lock
);
286 return enumerator_create_filter(this->shared
->create_enumerator(this->shared
),
287 (void*)shared_filter
, data
,
288 (void*)shared_data_destroy
);
292 * Add a certificate to chain
294 static certificate_t
* add_cert(private_stroke_cred_t
*this, certificate_t
*cert
)
296 certificate_t
*current
;
297 enumerator_t
*enumerator
;
300 this->lock
->read_lock(this->lock
);
301 enumerator
= this->certs
->create_enumerator(this->certs
);
302 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
304 if (current
->equals(current
, cert
))
306 /* cert already in queue */
313 enumerator
->destroy(enumerator
);
317 this->certs
->insert_last(this->certs
, cert
);
319 this->lock
->unlock(this->lock
);
324 * Implementation of stroke_cred_t.load_ca.
326 static certificate_t
* load_ca(private_stroke_cred_t
*this, char *filename
)
331 if (*filename
== '/')
333 snprintf(path
, sizeof(path
), "%s", filename
);
337 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
340 cert
= lib
->creds
->create(lib
->creds
,
341 CRED_CERTIFICATE
, CERT_X509
,
342 BUILD_FROM_FILE
, path
,
346 x509_t
*x509
= (x509_t
*)cert
;
348 if (!(x509
->get_flags(x509
) & X509_CA
))
350 DBG1(DBG_CFG
, " ca certificate \"%Y\" misses ca basic constraint, "
351 "discarded", cert
->get_subject(cert
));
355 return (certificate_t
*)add_cert(this, cert
);
361 * Add X.509 CRL to chain
363 static bool add_crl(private_stroke_cred_t
*this, crl_t
* crl
)
365 certificate_t
*current
, *cert
= &crl
->certificate
;
366 enumerator_t
*enumerator
;
367 bool new = TRUE
, found
= FALSE
;
369 this->lock
->write_lock(this->lock
);
370 enumerator
= this->certs
->create_enumerator(this->certs
);
371 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
373 if (current
->get_type(current
) == CERT_X509_CRL
)
375 crl_t
*crl_c
= (crl_t
*)current
;
376 chunk_t authkey
= crl
->get_authKeyIdentifier(crl
);
377 chunk_t authkey_c
= crl_c
->get_authKeyIdentifier(crl_c
);
379 /* if compare authorityKeyIdentifiers if available */
380 if (authkey
.ptr
&& authkey_c
.ptr
&& chunk_equals(authkey
, authkey_c
))
386 identification_t
*issuer
= cert
->get_issuer(cert
);
387 identification_t
*issuer_c
= current
->get_issuer(current
);
389 /* otherwise compare issuer distinguished names */
390 if (issuer
->equals(issuer
, issuer_c
))
397 new = crl_is_newer(crl
, crl_c
);
400 this->certs
->remove_at(this->certs
, enumerator
);
410 enumerator
->destroy(enumerator
);
414 this->certs
->insert_last(this->certs
, cert
);
416 this->lock
->unlock(this->lock
);
421 * Add X.509 attribute certificate to chain
423 static bool add_ac(private_stroke_cred_t
*this, ac_t
* ac
)
425 certificate_t
*cert
= &ac
->certificate
;
427 this->lock
->write_lock(this->lock
);
428 this->certs
->insert_last(this->certs
, cert
);
429 this->lock
->unlock(this->lock
);
434 * Implementation of stroke_cred_t.load_peer.
436 static certificate_t
* load_peer(private_stroke_cred_t
*this, char *filename
)
441 if (*filename
== '/')
443 snprintf(path
, sizeof(path
), "%s", filename
);
447 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
450 cert
= lib
->creds
->create(lib
->creds
,
451 CRED_CERTIFICATE
, CERT_ANY
,
452 BUILD_FROM_FILE
, path
,
456 cert
= add_cert(this, cert
);
457 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
458 cert
->get_subject(cert
), filename
);
459 return cert
->get_ref(cert
);
461 DBG1(DBG_CFG
, " loading certificate from '%s' failed", filename
);
466 * load trusted certificates from a directory
468 static void load_certdir(private_stroke_cred_t
*this, char *path
,
469 certificate_type_t type
, x509_flag_t flag
)
474 enumerator_t
*enumerator
= enumerator_create_directory(path
);
478 DBG1(DBG_CFG
, " reading directory failed");
482 while (enumerator
->enumerate(enumerator
, NULL
, &file
, &st
))
486 if (!S_ISREG(st
.st_mode
))
488 /* skip special file */
495 { /* for CA certificates, we strictly require
496 * the CA basic constraint to be set */
497 cert
= lib
->creds
->create(lib
->creds
,
498 CRED_CERTIFICATE
, CERT_X509
,
499 BUILD_FROM_FILE
, file
, BUILD_END
);
502 x509_t
*x509
= (x509_t
*)cert
;
504 if (!(x509
->get_flags(x509
) & X509_CA
))
506 DBG1(DBG_CFG
, " ca certificate \"%Y\" lacks "
507 "ca basic constraint, discarded",
508 cert
->get_subject(cert
));
514 DBG1(DBG_CFG
, " loaded ca certificate \"%Y\" from '%s'",
515 cert
->get_subject(cert
), file
);
520 DBG1(DBG_CFG
, " loading ca certificate from '%s' "
525 { /* for all other flags, we add them to the certificate. */
526 cert
= lib
->creds
->create(lib
->creds
,
527 CRED_CERTIFICATE
, CERT_X509
,
528 BUILD_FROM_FILE
, file
,
529 BUILD_X509_FLAG
, flag
, BUILD_END
);
532 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
533 cert
->get_subject(cert
), file
);
537 DBG1(DBG_CFG
, " loading certificate from '%s' "
543 add_cert(this, cert
);
547 cert
= lib
->creds
->create(lib
->creds
,
548 CRED_CERTIFICATE
, CERT_X509_CRL
,
549 BUILD_FROM_FILE
, file
,
553 add_crl(this, (crl_t
*)cert
);
554 DBG1(DBG_CFG
, " loaded crl from '%s'", file
);
558 DBG1(DBG_CFG
, " loading crl from '%s' failed", file
);
562 cert
= lib
->creds
->create(lib
->creds
,
563 CRED_CERTIFICATE
, CERT_X509_AC
,
564 BUILD_FROM_FILE
, file
,
568 add_ac(this, (ac_t
*)cert
);
569 DBG1(DBG_CFG
, " loaded attribute certificate from '%s'",
574 DBG1(DBG_CFG
, " loading attribute certificate from '%s' "
582 enumerator
->destroy(enumerator
);
586 * Implementation of credential_set_t.cache_cert.
588 static void cache_cert(private_stroke_cred_t
*this, certificate_t
*cert
)
590 if (cert
->get_type(cert
) == CERT_X509_CRL
&& this->cachecrl
)
592 /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */
593 crl_t
*crl
= (crl_t
*)cert
;
596 if (add_crl(this, crl
))
601 chunk
= crl
->get_authKeyIdentifier(crl
);
602 hex
= chunk_to_hex(chunk
, NULL
, FALSE
);
603 snprintf(buf
, sizeof(buf
), "%s/%s.crl", CRL_DIR
, hex
);
606 if (cert
->get_encoding(cert
, CERT_ASN1_DER
, &chunk
))
608 chunk_write(chunk
, buf
, "crl", 022, TRUE
);
616 * Implementation of stroke_cred_t.cachecrl.
618 static void cachecrl(private_stroke_cred_t
*this, bool enabled
)
620 DBG1(DBG_CFG
, "crl caching to %s %s",
621 CRL_DIR
, enabled ?
"enabled" : "disabled");
622 this->cachecrl
= enabled
;
627 * Convert a string of characters into a binary secret
628 * A string between single or double quotes is treated as ASCII characters
629 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
631 static err_t
extract_secret(chunk_t
*secret
, chunk_t
*line
)
634 char delimiter
= ' ';
637 if (!eat_whitespace(line
))
639 return "missing secret";
642 if (*line
->ptr
== '\'' || *line
->ptr
== '"')
645 delimiter
= *line
->ptr
;
646 line
->ptr
++; line
->len
--;
649 if (!extract_token(&raw_secret
, delimiter
, line
))
651 if (delimiter
== ' ')
657 return "missing second delimiter";
663 /* treat as an ASCII string */
664 *secret
= chunk_clone(raw_secret
);
667 /* treat 0x as hex, 0s as base64 */
668 if (raw_secret
.len
> 2)
670 if (strncasecmp("0x", raw_secret
.ptr
, 2) == 0)
672 *secret
= chunk_from_hex(chunk_skip(raw_secret
, 2), NULL
);
675 if (strncasecmp("0s", raw_secret
.ptr
, 2) == 0)
677 *secret
= chunk_from_base64(chunk_skip(raw_secret
, 2), NULL
);
681 *secret
= chunk_clone(raw_secret
);
686 * Data for passphrase callback
689 /** socket we use for prompting */
691 /** private key file */
693 /** number of tries */
695 } passphrase_cb_data_t
;
698 * Callback function to receive Passphrases
700 static shared_key_t
* passphrase_cb(passphrase_cb_data_t
*data
,
701 shared_key_type_t type
,
702 identification_t
*me
, identification_t
*other
,
703 id_match_t
*match_me
, id_match_t
*match_other
)
708 if (type
!= SHARED_ANY
&& type
!= SHARED_PRIVATE_KEY_PASS
)
717 fprintf(data
->prompt
, "PIN invalid, giving up.\n");
720 fprintf(data
->prompt
, "PIN invalid!\n");
723 fprintf(data
->prompt
, "Private key '%s' is encrypted.\n", data
->path
);
724 fprintf(data
->prompt
, "Passphrase:\n");
725 if (fgets(buf
, sizeof(buf
), data
->prompt
))
727 secret
= chunk_create(buf
, strlen(buf
));
729 { /* trim appended \n */
733 *match_me
= ID_MATCH_PERFECT
;
737 *match_other
= ID_MATCH_NONE
;
739 return shared_key_create(SHARED_PRIVATE_KEY_PASS
, chunk_clone(secret
));
746 * Data for PIN callback
749 /** socket we use for prompting */
755 /** number of tries */
760 * Callback function to receive PINs
762 static shared_key_t
* pin_cb(pin_cb_data_t
*data
, shared_key_type_t type
,
763 identification_t
*me
, identification_t
*other
,
764 id_match_t
*match_me
, id_match_t
*match_other
)
769 if (type
!= SHARED_ANY
&& type
!= SHARED_PIN
)
774 if (!me
|| !chunk_equals(me
->get_encoding(me
), data
->keyid
))
781 fprintf(data
->prompt
, "PIN invalid, aborting.\n");
785 fprintf(data
->prompt
, "Login to '%s' required\n", data
->card
);
786 fprintf(data
->prompt
, "PIN:\n");
787 if (fgets(buf
, sizeof(buf
), data
->prompt
))
789 secret
= chunk_create(buf
, strlen(buf
));
791 { /* trim appended \n */
795 *match_me
= ID_MATCH_PERFECT
;
799 *match_other
= ID_MATCH_NONE
;
801 return shared_key_create(SHARED_PIN
, chunk_clone(secret
));
808 * Load a smartcard with a PIN
810 static bool load_pin(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
813 chunk_t sc
= chunk_empty
, secret
= chunk_empty
;
814 char smartcard
[64], keyid
[64], module
[64], *pos
;
815 private_key_t
*key
= NULL
;
818 shared_key_t
*shared
;
819 identification_t
*id
;
820 mem_cred_t
*mem
= NULL
;
821 callback_cred_t
*cb
= NULL
;
822 pin_cb_data_t pin_data
;
824 SC_FORMAT_SLOT_MODULE_KEYID
,
825 SC_FORMAT_SLOT_KEYID
,
829 err_t ugh
= extract_value(&sc
, &line
);
833 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
838 DBG1(DBG_CFG
, "line %d: expected %%smartcard specifier", line_nr
);
841 snprintf(smartcard
, sizeof(smartcard
), "%.*s", sc
.len
, sc
.ptr
);
842 smartcard
[sizeof(smartcard
) - 1] = '\0';
844 /* parse slot and key id. Three formats are supported:
845 * - %smartcard<slot>@<module>:<keyid>
846 * - %smartcard<slot>:<keyid>
847 * - %smartcard:<keyid>
849 if (sscanf(smartcard
, "%%smartcard%u@%s", &slot
, module
) == 2)
851 pos
= strchr(module
, ':');
854 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is "
859 strcpy(keyid
, pos
+ 1);
860 format
= SC_FORMAT_SLOT_MODULE_KEYID
;
862 else if (sscanf(smartcard
, "%%smartcard%u:%s", &slot
, keyid
) == 2)
864 format
= SC_FORMAT_SLOT_KEYID
;
866 else if (sscanf(smartcard
, "%%smartcard:%s", keyid
) == 1)
868 format
= SC_FORMAT_KEYID
;
872 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is not"
873 " supported or invalid", line_nr
);
877 if (!eat_whitespace(&line
))
879 DBG1(DBG_CFG
, "line %d: expected PIN", line_nr
);
882 ugh
= extract_secret(&secret
, &line
);
885 DBG1(DBG_CFG
, "line %d: malformed PIN: %s", line_nr
, ugh
);
889 chunk
= chunk_from_hex(chunk_create(keyid
, strlen(keyid
)), NULL
);
890 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
894 { /* no IO channel to prompt, skip */
898 /* use callback credential set to prompt for the pin */
899 pin_data
.prompt
= prompt
;
900 pin_data
.card
= smartcard
;
901 pin_data
.keyid
= chunk
;
903 cb
= callback_cred_create_shared((void*)pin_cb
, &pin_data
);
904 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
);
908 /* provide our pin in a temporary credential set */
909 shared
= shared_key_create(SHARED_PIN
, secret
);
910 id
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
911 mem
= mem_cred_create();
912 mem
->add_shared(mem
, shared
, id
, NULL
);
913 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
);
916 /* unlock: smartcard needs the pin and potentially calls public set */
917 this->lock
->unlock(this->lock
);
920 case SC_FORMAT_SLOT_MODULE_KEYID
:
921 key
= lib
->creds
->create(lib
->creds
,
922 CRED_PRIVATE_KEY
, KEY_ANY
,
923 BUILD_PKCS11_SLOT
, slot
,
924 BUILD_PKCS11_MODULE
, module
,
925 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
927 case SC_FORMAT_SLOT_KEYID
:
928 key
= lib
->creds
->create(lib
->creds
,
929 CRED_PRIVATE_KEY
, KEY_ANY
,
930 BUILD_PKCS11_SLOT
, slot
,
931 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
933 case SC_FORMAT_KEYID
:
934 key
= lib
->creds
->create(lib
->creds
,
935 CRED_PRIVATE_KEY
, KEY_ANY
,
936 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
939 this->lock
->write_lock(this->lock
);
942 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
947 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
953 DBG1(DBG_CFG
, " loaded private key from %.*s", sc
.len
, sc
.ptr
);
954 this->private->insert_last(this->private, key
);
962 static bool load_private(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
963 FILE *prompt
, key_type_t key_type
)
967 chunk_t secret
= chunk_empty
;
970 err_t ugh
= extract_value(&filename
, &line
);
974 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
977 if (filename
.len
== 0)
979 DBG1(DBG_CFG
, "line %d: empty filename", line_nr
);
982 if (*filename
.ptr
== '/')
984 /* absolute path name */
985 snprintf(path
, sizeof(path
), "%.*s", filename
.len
, filename
.ptr
);
989 /* relative path name */
990 snprintf(path
, sizeof(path
), "%s/%.*s", PRIVATE_KEY_DIR
,
991 filename
.len
, filename
.ptr
);
994 /* check for optional passphrase */
995 if (eat_whitespace(&line
))
997 ugh
= extract_secret(&secret
, &line
);
1000 DBG1(DBG_CFG
, "line %d: malformed passphrase: %s", line_nr
, ugh
);
1004 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
1006 callback_cred_t
*cb
= NULL
;
1007 passphrase_cb_data_t pp_data
= {
1018 /* use callback credential set to prompt for the passphrase */
1019 pp_data
.prompt
= prompt
;
1020 pp_data
.path
= path
;
1022 cb
= callback_cred_create_shared((void*)passphrase_cb
, &pp_data
);
1023 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
);
1025 /* unlock, as the builder might ask for a secret */
1026 this->lock
->unlock(this->lock
);
1027 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
1028 BUILD_FROM_FILE
, path
, BUILD_END
);
1029 this->lock
->write_lock(this->lock
);
1031 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
1036 mem_cred_t
*mem
= NULL
;
1037 shared_key_t
*shared
;
1039 /* provide our pin in a temporary credential set */
1040 shared
= shared_key_create(SHARED_PRIVATE_KEY_PASS
, secret
);
1041 mem
= mem_cred_create();
1042 mem
->add_shared(mem
, shared
, NULL
);
1043 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
);
1045 /* unlock, as the builder might ask for a secret */
1046 this->lock
->unlock(this->lock
);
1047 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
1048 BUILD_FROM_FILE
, path
, BUILD_END
);
1049 this->lock
->write_lock(this->lock
);
1051 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
1056 DBG1(DBG_CFG
, " loaded %N private key from '%s'",
1057 key_type_names
, key
->get_type(key
), path
);
1058 this->private->insert_last(this->private, key
);
1062 DBG1(DBG_CFG
, " loading private key from '%s' failed", path
);
1070 static bool load_shared(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
1071 shared_key_type_t type
, chunk_t ids
)
1073 stroke_shared_key_t
*shared_key
;
1074 chunk_t secret
= chunk_empty
;
1077 err_t ugh
= extract_secret(&secret
, &line
);
1080 DBG1(DBG_CFG
, "line %d: malformed secret: %s", line_nr
, ugh
);
1083 shared_key
= stroke_shared_key_create(type
, secret
);
1084 DBG1(DBG_CFG
, " loaded %N secret for %s", shared_key_type_names
, type
,
1085 ids
.len
> 0 ?
(char*)ids
.ptr
: "%any");
1086 DBG4(DBG_CFG
, " secret: %#B", &secret
);
1088 this->shared
->insert_last(this->shared
, shared_key
);
1092 identification_t
*peer_id
;
1094 ugh
= extract_value(&id
, &ids
);
1097 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1105 /* NULL terminate the ID string */
1106 *(id
.ptr
+ id
.len
) = '\0';
1107 peer_id
= identification_create_from_string(id
.ptr
);
1108 if (peer_id
->get_type(peer_id
) == ID_ANY
)
1110 peer_id
->destroy(peer_id
);
1114 shared_key
->add_owner(shared_key
, peer_id
);
1119 shared_key
->add_owner(shared_key
,
1120 identification_create_from_encoding(ID_ANY
, chunk_empty
));
1126 * reload ipsec.secrets
1128 static void load_secrets(private_stroke_cred_t
*this, char *file
, int level
,
1131 int line_nr
= 0, fd
;
1133 private_key_t
*private;
1134 shared_key_t
*shared
;
1138 DBG1(DBG_CFG
, "loading secrets from '%s'", file
);
1139 fd
= open(file
, O_RDONLY
);
1142 DBG1(DBG_CFG
, "opening secrets file '%s' failed: %s", file
,
1146 if (fstat(fd
, &sb
) == -1)
1148 DBG1(DBG_LIB
, "getting file size of '%s' failed: %s", file
,
1153 addr
= mmap(NULL
, sb
.st_size
, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0);
1154 if (addr
== MAP_FAILED
)
1156 DBG1(DBG_LIB
, "mapping '%s' failed: %s", file
, strerror(errno
));
1160 src
= chunk_create(addr
, sb
.st_size
);
1164 this->lock
->write_lock(this->lock
);
1166 /* flush secrets on non-recursive invocation */
1167 while (this->shared
->remove_last(this->shared
,
1168 (void**)&shared
) == SUCCESS
)
1170 shared
->destroy(shared
);
1172 while (this->private->remove_last(this->private,
1173 (void**)&private) == SUCCESS
)
1175 private->destroy(private);
1179 while (fetchline(&src
, &line
))
1182 shared_key_type_t type
;
1186 if (!eat_whitespace(&line
))
1190 if (line
.len
> strlen("include ") &&
1191 strneq(line
.ptr
, "include ", strlen("include ")))
1194 char **expanded
, *dir
, pattern
[PATH_MAX
];
1197 if (level
> MAX_SECRETS_RECURSION
)
1199 DBG1(DBG_CFG
, "maximum level of %d includes reached, ignored",
1200 MAX_SECRETS_RECURSION
);
1203 /* terminate filename by space */
1204 line
= chunk_skip(line
, strlen("include "));
1205 pos
= memchr(line
.ptr
, ' ', line
.len
);
1208 line
.len
= pos
- line
.ptr
;
1210 if (line
.len
&& line
.ptr
[0] == '/')
1212 if (line
.len
+ 1 > sizeof(pattern
))
1214 DBG1(DBG_CFG
, "include pattern too long, ignored");
1217 snprintf(pattern
, sizeof(pattern
), "%.*s", line
.len
, line
.ptr
);
1220 { /* use directory of current file if relative */
1224 if (line
.len
+ 1 + strlen(dir
) + 1 > sizeof(pattern
))
1226 DBG1(DBG_CFG
, "include pattern too long, ignored");
1230 snprintf(pattern
, sizeof(pattern
), "%s/%.*s",
1231 dir
, line
.len
, line
.ptr
);
1234 if (glob(pattern
, GLOB_ERR
, NULL
, &buf
) != 0)
1236 DBG1(DBG_CFG
, "expanding file expression '%s' failed", pattern
);
1240 for (expanded
= buf
.gl_pathv
; *expanded
!= NULL
; expanded
++)
1242 load_secrets(this, *expanded
, level
+ 1, prompt
);
1249 if (line
.len
> 2 && strneq(": ", line
.ptr
, 2))
1251 /* no ids, skip the ':' */
1256 else if (extract_token_str(&ids
, " : ", &line
))
1258 /* NULL terminate the extracted id string */
1259 *(ids
.ptr
+ ids
.len
) = '\0';
1263 DBG1(DBG_CFG
, "line %d: missing ' : ' separator", line_nr
);
1267 if (!eat_whitespace(&line
) || !extract_token(&token
, ' ', &line
))
1269 DBG1(DBG_CFG
, "line %d: missing token", line_nr
);
1272 if (match("RSA", &token
) || match("ECDSA", &token
))
1274 if (!load_private(this, line
, line_nr
, prompt
,
1275 match("RSA", &token
) ? KEY_RSA
: KEY_ECDSA
))
1280 else if (match("PIN", &token
))
1282 if (!load_pin(this, line
, line_nr
, prompt
))
1287 else if ((match("PSK", &token
) && (type
= SHARED_IKE
)) ||
1288 (match("EAP", &token
) && (type
= SHARED_EAP
)) ||
1289 (match("NTLM", &token
) && (type
= SHARED_NT_HASH
)) ||
1290 (match("XAUTH", &token
) && (type
= SHARED_EAP
)))
1292 if (!load_shared(this, line
, line_nr
, type
, ids
))
1299 DBG1(DBG_CFG
, "line %d: token must be either "
1300 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr
);
1306 this->lock
->unlock(this->lock
);
1308 munmap(addr
, sb
.st_size
);
1313 * load all certificates from ipsec.d
1315 static void load_certs(private_stroke_cred_t
*this)
1317 DBG1(DBG_CFG
, "loading ca certificates from '%s'",
1318 CA_CERTIFICATE_DIR
);
1319 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1321 DBG1(DBG_CFG
, "loading aa certificates from '%s'",
1322 AA_CERTIFICATE_DIR
);
1323 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1325 DBG1(DBG_CFG
, "loading ocsp signer certificates from '%s'",
1326 OCSP_CERTIFICATE_DIR
);
1327 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
, X509_OCSP_SIGNER
);
1329 DBG1(DBG_CFG
, "loading attribute certificates from '%s'",
1330 ATTR_CERTIFICATE_DIR
);
1331 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1333 DBG1(DBG_CFG
, "loading crls from '%s'",
1335 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1339 * Implementation of stroke_cred_t.reread.
1341 static void reread(private_stroke_cred_t
*this, stroke_msg_t
*msg
, FILE *prompt
)
1343 if (msg
->reread
.flags
& REREAD_SECRETS
)
1345 DBG1(DBG_CFG
, "rereading secrets");
1346 load_secrets(this, SECRETS_FILE
, 0, prompt
);
1348 if (msg
->reread
.flags
& REREAD_CACERTS
)
1350 DBG1(DBG_CFG
, "rereading ca certificates from '%s'",
1351 CA_CERTIFICATE_DIR
);
1352 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1354 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1356 DBG1(DBG_CFG
, "rereading ocsp signer certificates from '%s'",
1357 OCSP_CERTIFICATE_DIR
);
1358 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
,
1361 if (msg
->reread
.flags
& REREAD_AACERTS
)
1363 DBG1(DBG_CFG
, "rereading aa certificates from '%s'",
1364 AA_CERTIFICATE_DIR
);
1365 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1367 if (msg
->reread
.flags
& REREAD_ACERTS
)
1369 DBG1(DBG_CFG
, "rereading attribute certificates from '%s'",
1370 ATTR_CERTIFICATE_DIR
);
1371 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1373 if (msg
->reread
.flags
& REREAD_CRLS
)
1375 DBG1(DBG_CFG
, "rereading crls from '%s'",
1377 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1382 * Implementation of stroke_cred_t.destroy
1384 static void destroy(private_stroke_cred_t
*this)
1386 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
1387 this->shared
->destroy_offset(this->shared
, offsetof(shared_key_t
, destroy
));
1388 this->private->destroy_offset(this->private, offsetof(private_key_t
, destroy
));
1389 this->lock
->destroy(this->lock
);
1396 stroke_cred_t
*stroke_cred_create()
1398 private_stroke_cred_t
*this = malloc_thing(private_stroke_cred_t
);
1400 this->public.set
.create_private_enumerator
= (void*)create_private_enumerator
;
1401 this->public.set
.create_cert_enumerator
= (void*)create_cert_enumerator
;
1402 this->public.set
.create_shared_enumerator
= (void*)create_shared_enumerator
;
1403 this->public.set
.create_cdp_enumerator
= (void*)return_null
;
1404 this->public.set
.cache_cert
= (void*)cache_cert
;
1405 this->public.reread
= (void(*)(stroke_cred_t
*, stroke_msg_t
*msg
, FILE*))reread
;
1406 this->public.load_ca
= (certificate_t
*(*)(stroke_cred_t
*, char *filename
))load_ca
;
1407 this->public.load_peer
= (certificate_t
*(*)(stroke_cred_t
*, char *filename
))load_peer
;
1408 this->public.cachecrl
= (void(*)(stroke_cred_t
*, bool enabled
))cachecrl
;
1409 this->public.destroy
= (void(*)(stroke_cred_t
*))destroy
;
1411 this->certs
= linked_list_create();
1412 this->shared
= linked_list_create();
1413 this->private = linked_list_create();
1414 this->lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
1417 load_secrets(this, SECRETS_FILE
, 0, NULL
);
1419 this->cachecrl
= FALSE
;
1421 return &this->public;