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 type
;
102 * destroy id enumerator data and unlock list
104 static void id_data_destroy(id_data_t
*data
)
106 data
->this->lock
->unlock(data
->this->lock
);
111 * filter function for private key enumerator
113 static bool private_filter(id_data_t
*data
,
114 private_key_t
**in
, private_key_t
**out
)
119 if (data
->id
== NULL
)
124 if (key
->has_fingerprint(key
, data
->id
->get_encoding(data
->id
)))
133 * Implements credential_set_t.create_private_enumerator
135 static enumerator_t
* create_private_enumerator(private_stroke_cred_t
*this,
136 key_type_t type
, identification_t
*id
)
140 data
= malloc_thing(id_data_t
);
144 this->lock
->read_lock(this->lock
);
145 return enumerator_create_filter(this->private->create_enumerator(this->private),
146 (void*)private_filter
, data
,
147 (void*)id_data_destroy
);
151 * filter function for certs enumerator
153 static bool certs_filter(id_data_t
*data
, certificate_t
**in
, certificate_t
**out
)
155 public_key_t
*public;
156 certificate_t
*cert
= *in
;
158 if (data
->type
!= CERT_ANY
&& data
->type
!= cert
->get_type(cert
))
162 if (data
->id
== NULL
|| cert
->has_subject(cert
, data
->id
))
168 public = cert
->get_public_key(cert
);
171 if (public->has_fingerprint(public, data
->id
->get_encoding(data
->id
)))
173 public->destroy(public);
177 public->destroy(public);
183 * Implements credential_set_t.create_cert_enumerator
185 static enumerator_t
* create_cert_enumerator(private_stroke_cred_t
*this,
186 certificate_type_t cert
, key_type_t key
,
187 identification_t
*id
, bool trusted
)
191 if (trusted
&& (cert
== CERT_X509_CRL
|| cert
== CERT_X509_AC
))
195 data
= malloc_thing(id_data_t
);
200 this->lock
->read_lock(this->lock
);
201 return enumerator_create_filter(this->certs
->create_enumerator(this->certs
),
202 (void*)certs_filter
, data
,
203 (void*)id_data_destroy
);
207 private_stroke_cred_t
*this;
208 identification_t
*me
;
209 identification_t
*other
;
210 shared_key_type_t type
;
214 * free shared key enumerator data and unlock list
216 static void shared_data_destroy(shared_data_t
*data
)
218 data
->this->lock
->unlock(data
->this->lock
);
223 * filter function for certs enumerator
225 static bool shared_filter(shared_data_t
*data
,
226 stroke_shared_key_t
**in
, shared_key_t
**out
,
227 void **unused1
, id_match_t
*me
,
228 void **unused2
, id_match_t
*other
)
230 id_match_t my_match
= ID_MATCH_NONE
, other_match
= ID_MATCH_NONE
;
231 stroke_shared_key_t
*stroke
= *in
;
232 shared_key_t
*shared
= &stroke
->shared
;
234 if (data
->type
!= SHARED_ANY
&& shared
->get_type(shared
) != data
->type
)
241 my_match
= stroke
->has_owner(stroke
, data
->me
);
245 other_match
= stroke
->has_owner(stroke
, data
->other
);
247 if ((data
->me
|| data
->other
) && (!my_match
&& !other_match
))
258 *other
= other_match
;
264 * Implements credential_set_t.create_shared_enumerator
266 static enumerator_t
* create_shared_enumerator(private_stroke_cred_t
*this,
267 shared_key_type_t type
, identification_t
*me
,
268 identification_t
*other
)
270 shared_data_t
*data
= malloc_thing(shared_data_t
);
276 this->lock
->read_lock(this->lock
);
277 return enumerator_create_filter(this->shared
->create_enumerator(this->shared
),
278 (void*)shared_filter
, data
,
279 (void*)shared_data_destroy
);
283 * Add a certificate to chain
285 static certificate_t
* add_cert(private_stroke_cred_t
*this, certificate_t
*cert
)
287 certificate_t
*current
;
288 enumerator_t
*enumerator
;
291 this->lock
->read_lock(this->lock
);
292 enumerator
= this->certs
->create_enumerator(this->certs
);
293 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
295 if (current
->equals(current
, cert
))
297 /* cert already in queue */
304 enumerator
->destroy(enumerator
);
308 this->certs
->insert_last(this->certs
, cert
);
310 this->lock
->unlock(this->lock
);
315 * Implementation of stroke_cred_t.load_ca.
317 static certificate_t
* load_ca(private_stroke_cred_t
*this, char *filename
)
322 if (*filename
== '/')
324 snprintf(path
, sizeof(path
), "%s", filename
);
328 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
331 cert
= lib
->creds
->create(lib
->creds
,
332 CRED_CERTIFICATE
, CERT_X509
,
333 BUILD_FROM_FILE
, path
,
337 x509_t
*x509
= (x509_t
*)cert
;
339 if (!(x509
->get_flags(x509
) & X509_CA
))
341 DBG1(DBG_CFG
, " ca certificate \"%Y\" misses ca basic constraint, "
342 "discarded", cert
->get_subject(cert
));
346 return (certificate_t
*)add_cert(this, cert
);
352 * Add X.509 CRL to chain
354 static bool add_crl(private_stroke_cred_t
*this, crl_t
* crl
)
356 certificate_t
*current
, *cert
= &crl
->certificate
;
357 enumerator_t
*enumerator
;
358 bool new = TRUE
, found
= FALSE
;
360 this->lock
->write_lock(this->lock
);
361 enumerator
= this->certs
->create_enumerator(this->certs
);
362 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
364 if (current
->get_type(current
) == CERT_X509_CRL
)
366 crl_t
*crl_c
= (crl_t
*)current
;
367 chunk_t authkey
= crl
->get_authKeyIdentifier(crl
);
368 chunk_t authkey_c
= crl_c
->get_authKeyIdentifier(crl_c
);
370 /* if compare authorityKeyIdentifiers if available */
371 if (authkey
.ptr
&& authkey_c
.ptr
&& chunk_equals(authkey
, authkey_c
))
377 identification_t
*issuer
= cert
->get_issuer(cert
);
378 identification_t
*issuer_c
= current
->get_issuer(current
);
380 /* otherwise compare issuer distinguished names */
381 if (issuer
->equals(issuer
, issuer_c
))
388 new = crl_is_newer(crl
, crl_c
);
391 this->certs
->remove_at(this->certs
, enumerator
);
401 enumerator
->destroy(enumerator
);
405 this->certs
->insert_last(this->certs
, cert
);
407 this->lock
->unlock(this->lock
);
412 * Add X.509 attribute certificate to chain
414 static bool add_ac(private_stroke_cred_t
*this, ac_t
* ac
)
416 certificate_t
*cert
= &ac
->certificate
;
418 this->lock
->write_lock(this->lock
);
419 this->certs
->insert_last(this->certs
, cert
);
420 this->lock
->unlock(this->lock
);
425 * Implementation of stroke_cred_t.load_peer.
427 static certificate_t
* load_peer(private_stroke_cred_t
*this, char *filename
)
432 if (*filename
== '/')
434 snprintf(path
, sizeof(path
), "%s", filename
);
438 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
441 cert
= lib
->creds
->create(lib
->creds
,
442 CRED_CERTIFICATE
, CERT_ANY
,
443 BUILD_FROM_FILE
, path
,
447 cert
= add_cert(this, cert
);
448 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
449 cert
->get_subject(cert
), filename
);
450 return cert
->get_ref(cert
);
452 DBG1(DBG_CFG
, " loading certificate from '%s' failed", filename
);
457 * load trusted certificates from a directory
459 static void load_certdir(private_stroke_cred_t
*this, char *path
,
460 certificate_type_t type
, x509_flag_t flag
)
465 enumerator_t
*enumerator
= enumerator_create_directory(path
);
469 DBG1(DBG_CFG
, " reading directory failed");
473 while (enumerator
->enumerate(enumerator
, NULL
, &file
, &st
))
477 if (!S_ISREG(st
.st_mode
))
479 /* skip special file */
486 { /* for CA certificates, we strictly require
487 * the CA basic constraint to be set */
488 cert
= lib
->creds
->create(lib
->creds
,
489 CRED_CERTIFICATE
, CERT_X509
,
490 BUILD_FROM_FILE
, file
, BUILD_END
);
493 x509_t
*x509
= (x509_t
*)cert
;
495 if (!(x509
->get_flags(x509
) & X509_CA
))
497 DBG1(DBG_CFG
, " ca certificate \"%Y\" lacks "
498 "ca basic constraint, discarded",
499 cert
->get_subject(cert
));
505 DBG1(DBG_CFG
, " loaded ca certificate \"%Y\" from '%s'",
506 cert
->get_subject(cert
), file
);
511 DBG1(DBG_CFG
, " loading ca certificate from '%s' "
516 { /* for all other flags, we add them to the certificate. */
517 cert
= lib
->creds
->create(lib
->creds
,
518 CRED_CERTIFICATE
, CERT_X509
,
519 BUILD_FROM_FILE
, file
,
520 BUILD_X509_FLAG
, flag
, BUILD_END
);
523 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
524 cert
->get_subject(cert
), file
);
528 DBG1(DBG_CFG
, " loading certificate from '%s' "
534 add_cert(this, cert
);
538 cert
= lib
->creds
->create(lib
->creds
,
539 CRED_CERTIFICATE
, CERT_X509_CRL
,
540 BUILD_FROM_FILE
, file
,
544 add_crl(this, (crl_t
*)cert
);
545 DBG1(DBG_CFG
, " loaded crl from '%s'", file
);
549 DBG1(DBG_CFG
, " loading crl from '%s' failed", file
);
553 cert
= lib
->creds
->create(lib
->creds
,
554 CRED_CERTIFICATE
, CERT_X509_AC
,
555 BUILD_FROM_FILE
, file
,
559 add_ac(this, (ac_t
*)cert
);
560 DBG1(DBG_CFG
, " loaded attribute certificate from '%s'",
565 DBG1(DBG_CFG
, " loading attribute certificate from '%s' "
573 enumerator
->destroy(enumerator
);
577 * Implementation of credential_set_t.cache_cert.
579 static void cache_cert(private_stroke_cred_t
*this, certificate_t
*cert
)
581 if (cert
->get_type(cert
) == CERT_X509_CRL
&& this->cachecrl
)
583 /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */
584 crl_t
*crl
= (crl_t
*)cert
;
587 if (add_crl(this, crl
))
592 chunk
= crl
->get_authKeyIdentifier(crl
);
593 hex
= chunk_to_hex(chunk
, NULL
, FALSE
);
594 snprintf(buf
, sizeof(buf
), "%s/%s.crl", CRL_DIR
, hex
);
597 if (cert
->get_encoding(cert
, CERT_ASN1_DER
, &chunk
))
599 chunk_write(chunk
, buf
, "crl", 022, TRUE
);
607 * Implementation of stroke_cred_t.cachecrl.
609 static void cachecrl(private_stroke_cred_t
*this, bool enabled
)
611 DBG1(DBG_CFG
, "crl caching to %s %s",
612 CRL_DIR
, enabled ?
"enabled" : "disabled");
613 this->cachecrl
= enabled
;
618 * Convert a string of characters into a binary secret
619 * A string between single or double quotes is treated as ASCII characters
620 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
622 static err_t
extract_secret(chunk_t
*secret
, chunk_t
*line
)
625 char delimiter
= ' ';
628 if (!eat_whitespace(line
))
630 return "missing secret";
633 if (*line
->ptr
== '\'' || *line
->ptr
== '"')
636 delimiter
= *line
->ptr
;
637 line
->ptr
++; line
->len
--;
640 if (!extract_token(&raw_secret
, delimiter
, line
))
642 if (delimiter
== ' ')
648 return "missing second delimiter";
654 /* treat as an ASCII string */
655 *secret
= chunk_clone(raw_secret
);
658 /* treat 0x as hex, 0s as base64 */
659 if (raw_secret
.len
> 2)
661 if (strncasecmp("0x", raw_secret
.ptr
, 2) == 0)
663 *secret
= chunk_from_hex(chunk_skip(raw_secret
, 2), NULL
);
666 if (strncasecmp("0s", raw_secret
.ptr
, 2) == 0)
668 *secret
= chunk_from_base64(chunk_skip(raw_secret
, 2), NULL
);
672 *secret
= chunk_clone(raw_secret
);
677 * Data for passphrase callback
680 /** socket we use for prompting */
682 /** private key file */
684 /** number of tries */
686 } passphrase_cb_data_t
;
689 * Callback function to receive Passphrases
691 static shared_key_t
* passphrase_cb(passphrase_cb_data_t
*data
,
692 shared_key_type_t type
,
693 identification_t
*me
, identification_t
*other
,
694 id_match_t
*match_me
, id_match_t
*match_other
)
699 if (type
!= SHARED_ANY
&& type
!= SHARED_PRIVATE_KEY_PASS
)
708 fprintf(data
->prompt
, "PIN invalid, giving up.\n");
711 fprintf(data
->prompt
, "PIN invalid!\n");
714 fprintf(data
->prompt
, "Private key '%s' is encrypted.\n", data
->path
);
715 fprintf(data
->prompt
, "Passphrase:\n");
716 if (fgets(buf
, sizeof(buf
), data
->prompt
))
718 secret
= chunk_create(buf
, strlen(buf
));
720 { /* trim appended \n */
724 *match_me
= ID_MATCH_PERFECT
;
728 *match_other
= ID_MATCH_NONE
;
730 return shared_key_create(SHARED_PRIVATE_KEY_PASS
, chunk_clone(secret
));
737 * Data for PIN callback
740 /** socket we use for prompting */
746 /** number of tries */
751 * Callback function to receive PINs
753 static shared_key_t
* pin_cb(pin_cb_data_t
*data
, shared_key_type_t type
,
754 identification_t
*me
, identification_t
*other
,
755 id_match_t
*match_me
, id_match_t
*match_other
)
760 if (type
!= SHARED_ANY
&& type
!= SHARED_PIN
)
765 if (!me
|| !chunk_equals(me
->get_encoding(me
), data
->keyid
))
772 fprintf(data
->prompt
, "PIN invalid, aborting.\n");
776 fprintf(data
->prompt
, "Login to '%s' required\n", data
->card
);
777 fprintf(data
->prompt
, "PIN:\n");
778 if (fgets(buf
, sizeof(buf
), data
->prompt
))
780 secret
= chunk_create(buf
, strlen(buf
));
782 { /* trim appended \n */
786 *match_me
= ID_MATCH_PERFECT
;
790 *match_other
= ID_MATCH_NONE
;
792 return shared_key_create(SHARED_PIN
, chunk_clone(secret
));
799 * Load a smartcard with a PIN
801 static bool load_pin(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
804 chunk_t sc
= chunk_empty
, secret
= chunk_empty
;
805 char smartcard
[64], keyid
[64], module
[64], *pos
;
806 private_key_t
*key
= NULL
;
809 shared_key_t
*shared
;
810 identification_t
*id
;
811 mem_cred_t
*mem
= NULL
;
812 callback_cred_t
*cb
= NULL
;
813 pin_cb_data_t pin_data
;
815 SC_FORMAT_SLOT_MODULE_KEYID
,
816 SC_FORMAT_SLOT_KEYID
,
820 err_t ugh
= extract_value(&sc
, &line
);
824 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
829 DBG1(DBG_CFG
, "line %d: expected %%smartcard specifier", line_nr
);
832 snprintf(smartcard
, sizeof(smartcard
), "%.*s", sc
.len
, sc
.ptr
);
833 smartcard
[sizeof(smartcard
) - 1] = '\0';
835 /* parse slot and key id. Three formats are supported:
836 * - %smartcard<slot>@<module>:<keyid>
837 * - %smartcard<slot>:<keyid>
838 * - %smartcard:<keyid>
840 if (sscanf(smartcard
, "%%smartcard%u@%s", &slot
, module
) == 2)
842 pos
= strchr(module
, ':');
845 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is "
850 strcpy(keyid
, pos
+ 1);
851 format
= SC_FORMAT_SLOT_MODULE_KEYID
;
853 else if (sscanf(smartcard
, "%%smartcard%u:%s", &slot
, keyid
) == 2)
855 format
= SC_FORMAT_SLOT_KEYID
;
857 else if (sscanf(smartcard
, "%%smartcard:%s", keyid
) == 1)
859 format
= SC_FORMAT_KEYID
;
863 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is not"
864 " supported or invalid", line_nr
);
868 if (!eat_whitespace(&line
))
870 DBG1(DBG_CFG
, "line %d: expected PIN", line_nr
);
873 ugh
= extract_secret(&secret
, &line
);
876 DBG1(DBG_CFG
, "line %d: malformed PIN: %s", line_nr
, ugh
);
880 chunk
= chunk_from_hex(chunk_create(keyid
, strlen(keyid
)), NULL
);
881 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
885 { /* no IO channel to prompt, skip */
889 /* use callback credential set to prompt for the pin */
890 pin_data
.prompt
= prompt
;
891 pin_data
.card
= smartcard
;
892 pin_data
.keyid
= chunk
;
894 cb
= callback_cred_create_shared((void*)pin_cb
, &pin_data
);
895 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
);
899 /* provide our pin in a temporary credential set */
900 shared
= shared_key_create(SHARED_PIN
, secret
);
901 id
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
902 mem
= mem_cred_create();
903 mem
->add_shared(mem
, shared
, id
, NULL
);
904 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
);
907 /* unlock: smartcard needs the pin and potentially calls public set */
908 this->lock
->unlock(this->lock
);
911 case SC_FORMAT_SLOT_MODULE_KEYID
:
912 key
= lib
->creds
->create(lib
->creds
,
913 CRED_PRIVATE_KEY
, KEY_ANY
,
914 BUILD_PKCS11_SLOT
, slot
,
915 BUILD_PKCS11_MODULE
, module
,
916 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
918 case SC_FORMAT_SLOT_KEYID
:
919 key
= lib
->creds
->create(lib
->creds
,
920 CRED_PRIVATE_KEY
, KEY_ANY
,
921 BUILD_PKCS11_SLOT
, slot
,
922 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
924 case SC_FORMAT_KEYID
:
925 key
= lib
->creds
->create(lib
->creds
,
926 CRED_PRIVATE_KEY
, KEY_ANY
,
927 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
930 this->lock
->write_lock(this->lock
);
933 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
938 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
944 DBG1(DBG_CFG
, " loaded private key from %.*s", sc
.len
, sc
.ptr
);
945 this->private->insert_last(this->private, key
);
953 static bool load_private(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
954 FILE *prompt
, key_type_t key_type
)
958 chunk_t secret
= chunk_empty
;
961 err_t ugh
= extract_value(&filename
, &line
);
965 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
968 if (filename
.len
== 0)
970 DBG1(DBG_CFG
, "line %d: empty filename", line_nr
);
973 if (*filename
.ptr
== '/')
975 /* absolute path name */
976 snprintf(path
, sizeof(path
), "%.*s", filename
.len
, filename
.ptr
);
980 /* relative path name */
981 snprintf(path
, sizeof(path
), "%s/%.*s", PRIVATE_KEY_DIR
,
982 filename
.len
, filename
.ptr
);
985 /* check for optional passphrase */
986 if (eat_whitespace(&line
))
988 ugh
= extract_secret(&secret
, &line
);
991 DBG1(DBG_CFG
, "line %d: malformed passphrase: %s", line_nr
, ugh
);
995 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
997 callback_cred_t
*cb
= NULL
;
998 passphrase_cb_data_t pp_data
= {
1009 /* use callback credential set to prompt for the passphrase */
1010 pp_data
.prompt
= prompt
;
1011 pp_data
.path
= path
;
1013 cb
= callback_cred_create_shared((void*)passphrase_cb
, &pp_data
);
1014 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
);
1016 /* unlock, as the builder might ask for a secret */
1017 this->lock
->unlock(this->lock
);
1018 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
1019 BUILD_FROM_FILE
, path
, BUILD_END
);
1020 this->lock
->write_lock(this->lock
);
1022 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
1027 mem_cred_t
*mem
= NULL
;
1028 shared_key_t
*shared
;
1030 /* provide our pin in a temporary credential set */
1031 shared
= shared_key_create(SHARED_PRIVATE_KEY_PASS
, secret
);
1032 mem
= mem_cred_create();
1033 mem
->add_shared(mem
, shared
, NULL
);
1034 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
);
1036 /* unlock, as the builder might ask for a secret */
1037 this->lock
->unlock(this->lock
);
1038 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
1039 BUILD_FROM_FILE
, path
, BUILD_END
);
1040 this->lock
->write_lock(this->lock
);
1042 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
1047 DBG1(DBG_CFG
, " loaded %N private key from '%s'",
1048 key_type_names
, key
->get_type(key
), path
);
1049 this->private->insert_last(this->private, key
);
1053 DBG1(DBG_CFG
, " loading private key from '%s' failed", path
);
1061 static bool load_shared(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
1062 shared_key_type_t type
, chunk_t ids
)
1064 stroke_shared_key_t
*shared_key
;
1065 chunk_t secret
= chunk_empty
;
1068 err_t ugh
= extract_secret(&secret
, &line
);
1071 DBG1(DBG_CFG
, "line %d: malformed secret: %s", line_nr
, ugh
);
1074 shared_key
= stroke_shared_key_create(type
, secret
);
1075 DBG1(DBG_CFG
, " loaded %N secret for %s", shared_key_type_names
, type
,
1076 ids
.len
> 0 ?
(char*)ids
.ptr
: "%any");
1077 DBG4(DBG_CFG
, " secret: %#B", &secret
);
1079 this->shared
->insert_last(this->shared
, shared_key
);
1083 identification_t
*peer_id
;
1085 ugh
= extract_value(&id
, &ids
);
1088 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1096 /* NULL terminate the ID string */
1097 *(id
.ptr
+ id
.len
) = '\0';
1098 peer_id
= identification_create_from_string(id
.ptr
);
1099 if (peer_id
->get_type(peer_id
) == ID_ANY
)
1101 peer_id
->destroy(peer_id
);
1105 shared_key
->add_owner(shared_key
, peer_id
);
1110 shared_key
->add_owner(shared_key
,
1111 identification_create_from_encoding(ID_ANY
, chunk_empty
));
1117 * reload ipsec.secrets
1119 static void load_secrets(private_stroke_cred_t
*this, char *file
, int level
,
1122 int line_nr
= 0, fd
;
1124 private_key_t
*private;
1125 shared_key_t
*shared
;
1129 DBG1(DBG_CFG
, "loading secrets from '%s'", file
);
1130 fd
= open(file
, O_RDONLY
);
1133 DBG1(DBG_CFG
, "opening secrets file '%s' failed: %s", file
,
1137 if (fstat(fd
, &sb
) == -1)
1139 DBG1(DBG_LIB
, "getting file size of '%s' failed: %s", file
,
1144 addr
= mmap(NULL
, sb
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1145 if (addr
== MAP_FAILED
)
1147 DBG1(DBG_LIB
, "mapping '%s' failed: %s", file
, strerror(errno
));
1151 src
= chunk_create(addr
, sb
.st_size
);
1155 this->lock
->write_lock(this->lock
);
1157 /* flush secrets on non-recursive invocation */
1158 while (this->shared
->remove_last(this->shared
,
1159 (void**)&shared
) == SUCCESS
)
1161 shared
->destroy(shared
);
1163 while (this->private->remove_last(this->private,
1164 (void**)&private) == SUCCESS
)
1166 private->destroy(private);
1170 while (fetchline(&src
, &line
))
1173 shared_key_type_t type
;
1177 if (!eat_whitespace(&line
))
1181 if (line
.len
> strlen("include ") &&
1182 strneq(line
.ptr
, "include ", strlen("include ")))
1185 char **expanded
, *dir
, pattern
[PATH_MAX
];
1188 if (level
> MAX_SECRETS_RECURSION
)
1190 DBG1(DBG_CFG
, "maximum level of %d includes reached, ignored",
1191 MAX_SECRETS_RECURSION
);
1194 /* terminate filename by space */
1195 line
= chunk_skip(line
, strlen("include "));
1196 pos
= memchr(line
.ptr
, ' ', line
.len
);
1199 line
.len
= pos
- line
.ptr
;
1201 if (line
.len
&& line
.ptr
[0] == '/')
1203 if (line
.len
+ 1 > sizeof(pattern
))
1205 DBG1(DBG_CFG
, "include pattern too long, ignored");
1208 snprintf(pattern
, sizeof(pattern
), "%.*s", line
.len
, line
.ptr
);
1211 { /* use directory of current file if relative */
1215 if (line
.len
+ 1 + strlen(dir
) + 1 > sizeof(pattern
))
1217 DBG1(DBG_CFG
, "include pattern too long, ignored");
1221 snprintf(pattern
, sizeof(pattern
), "%s/%.*s",
1222 dir
, line
.len
, line
.ptr
);
1225 if (glob(pattern
, GLOB_ERR
, NULL
, &buf
) != 0)
1227 DBG1(DBG_CFG
, "expanding file expression '%s' failed", pattern
);
1232 for (expanded
= buf
.gl_pathv
; *expanded
!= NULL
; expanded
++)
1234 load_secrets(this, *expanded
, level
+ 1, prompt
);
1241 if (line
.len
> 2 && strneq(": ", line
.ptr
, 2))
1243 /* no ids, skip the ':' */
1248 else if (extract_token_str(&ids
, " : ", &line
))
1250 /* NULL terminate the extracted id string */
1251 *(ids
.ptr
+ ids
.len
) = '\0';
1255 DBG1(DBG_CFG
, "line %d: missing ' : ' separator", line_nr
);
1259 if (!eat_whitespace(&line
) || !extract_token(&token
, ' ', &line
))
1261 DBG1(DBG_CFG
, "line %d: missing token", line_nr
);
1264 if (match("RSA", &token
) || match("ECDSA", &token
))
1266 if (!load_private(this, line
, line_nr
, prompt
,
1267 match("RSA", &token
) ? KEY_RSA
: KEY_ECDSA
))
1272 else if (match("PIN", &token
))
1274 if (!load_pin(this, line
, line_nr
, prompt
))
1279 else if ((match("PSK", &token
) && (type
= SHARED_IKE
)) ||
1280 (match("EAP", &token
) && (type
= SHARED_EAP
)) ||
1281 (match("NTLM", &token
) && (type
= SHARED_NT_HASH
)) ||
1282 (match("XAUTH", &token
) && (type
= SHARED_EAP
)))
1284 if (!load_shared(this, line
, line_nr
, type
, ids
))
1291 DBG1(DBG_CFG
, "line %d: token must be either "
1292 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr
);
1298 this->lock
->unlock(this->lock
);
1300 munmap(addr
, sb
.st_size
);
1305 * load all certificates from ipsec.d
1307 static void load_certs(private_stroke_cred_t
*this)
1309 DBG1(DBG_CFG
, "loading ca certificates from '%s'",
1310 CA_CERTIFICATE_DIR
);
1311 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1313 DBG1(DBG_CFG
, "loading aa certificates from '%s'",
1314 AA_CERTIFICATE_DIR
);
1315 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1317 DBG1(DBG_CFG
, "loading ocsp signer certificates from '%s'",
1318 OCSP_CERTIFICATE_DIR
);
1319 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
, X509_OCSP_SIGNER
);
1321 DBG1(DBG_CFG
, "loading attribute certificates from '%s'",
1322 ATTR_CERTIFICATE_DIR
);
1323 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1325 DBG1(DBG_CFG
, "loading crls from '%s'",
1327 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1331 * Implementation of stroke_cred_t.reread.
1333 static void reread(private_stroke_cred_t
*this, stroke_msg_t
*msg
, FILE *prompt
)
1335 if (msg
->reread
.flags
& REREAD_SECRETS
)
1337 DBG1(DBG_CFG
, "rereading secrets");
1338 load_secrets(this, SECRETS_FILE
, 0, prompt
);
1340 if (msg
->reread
.flags
& REREAD_CACERTS
)
1342 DBG1(DBG_CFG
, "rereading ca certificates from '%s'",
1343 CA_CERTIFICATE_DIR
);
1344 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1346 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1348 DBG1(DBG_CFG
, "rereading ocsp signer certificates from '%s'",
1349 OCSP_CERTIFICATE_DIR
);
1350 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
,
1353 if (msg
->reread
.flags
& REREAD_AACERTS
)
1355 DBG1(DBG_CFG
, "rereading aa certificates from '%s'",
1356 AA_CERTIFICATE_DIR
);
1357 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1359 if (msg
->reread
.flags
& REREAD_ACERTS
)
1361 DBG1(DBG_CFG
, "rereading attribute certificates from '%s'",
1362 ATTR_CERTIFICATE_DIR
);
1363 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1365 if (msg
->reread
.flags
& REREAD_CRLS
)
1367 DBG1(DBG_CFG
, "rereading crls from '%s'",
1369 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1374 * Implementation of stroke_cred_t.destroy
1376 static void destroy(private_stroke_cred_t
*this)
1378 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
1379 this->shared
->destroy_offset(this->shared
, offsetof(shared_key_t
, destroy
));
1380 this->private->destroy_offset(this->private, offsetof(private_key_t
, destroy
));
1381 this->lock
->destroy(this->lock
);
1388 stroke_cred_t
*stroke_cred_create()
1390 private_stroke_cred_t
*this = malloc_thing(private_stroke_cred_t
);
1392 this->public.set
.create_private_enumerator
= (void*)create_private_enumerator
;
1393 this->public.set
.create_cert_enumerator
= (void*)create_cert_enumerator
;
1394 this->public.set
.create_shared_enumerator
= (void*)create_shared_enumerator
;
1395 this->public.set
.create_cdp_enumerator
= (void*)return_null
;
1396 this->public.set
.cache_cert
= (void*)cache_cert
;
1397 this->public.reread
= (void(*)(stroke_cred_t
*, stroke_msg_t
*msg
, FILE*))reread
;
1398 this->public.load_ca
= (certificate_t
*(*)(stroke_cred_t
*, char *filename
))load_ca
;
1399 this->public.load_peer
= (certificate_t
*(*)(stroke_cred_t
*, char *filename
))load_peer
;
1400 this->public.cachecrl
= (void(*)(stroke_cred_t
*, bool enabled
))cachecrl
;
1401 this->public.destroy
= (void(*)(stroke_cred_t
*))destroy
;
1403 this->certs
= linked_list_create();
1404 this->shared
= linked_list_create();
1405 this->private = linked_list_create();
1406 this->lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
1409 load_secrets(this, SECRETS_FILE
, 0, NULL
);
1411 this->cachecrl
= FALSE
;
1413 return &this->public;