2 * Copyright (C) 2008-2012 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>
30 #include "stroke_cred.h"
32 #include <credentials/certificates/x509.h>
33 #include <credentials/certificates/crl.h>
34 #include <credentials/certificates/ac.h>
35 #include <credentials/sets/mem_cred.h>
36 #include <credentials/sets/callback_cred.h>
37 #include <utils/linked_list.h>
38 #include <utils/lexparser.h>
39 #include <threading/rwlock.h>
42 /* configuration directories and files */
43 #define CONFIG_DIR IPSEC_CONFDIR
44 #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
45 #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
46 #define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
47 #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
48 #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
49 #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
50 #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
51 #define CRL_DIR IPSEC_D_DIR "/crls"
52 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
54 #define MAX_SECRETS_RECURSION 10
56 typedef struct private_stroke_cred_t private_stroke_cred_t
;
59 * private data of stroke_cred
61 struct private_stroke_cred_t
{
74 * ignore missing CA basic constraint (i.e. treat all certificates in
75 * ipsec.conf ca sections and ipsec.d/cacert as CA certificates)
85 METHOD(stroke_cred_t
, load_ca
, certificate_t
*,
86 private_stroke_cred_t
*this, char *filename
)
93 snprintf(path
, sizeof(path
), "%s", filename
);
97 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
100 if (this->force_ca_cert
)
101 { /* we treat this certificate as a CA certificate even if it has no
102 * CA basic constraint */
103 cert
= lib
->creds
->create(lib
->creds
,
104 CRED_CERTIFICATE
, CERT_X509
,
105 BUILD_FROM_FILE
, path
, BUILD_X509_FLAG
, X509_CA
,
110 cert
= lib
->creds
->create(lib
->creds
,
111 CRED_CERTIFICATE
, CERT_X509
,
112 BUILD_FROM_FILE
, path
,
117 x509_t
*x509
= (x509_t
*)cert
;
119 if (!(x509
->get_flags(x509
) & X509_CA
))
121 DBG1(DBG_CFG
, " ca certificate \"%Y\" misses ca basic constraint, "
122 "discarded", cert
->get_subject(cert
));
126 return this->creds
->add_cert_ref(this->creds
, TRUE
, cert
);
131 METHOD(stroke_cred_t
, load_peer
, certificate_t
*,
132 private_stroke_cred_t
*this, char *filename
)
138 if (strneq(filename
, "%smartcard:", strlen("%smartcard:")))
140 keyid
= chunk_create(filename
, strlen(filename
));
141 keyid
= chunk_from_hex(chunk_skip(keyid
, strlen("%smartcard:")), NULL
);
142 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
143 BUILD_PKCS11_KEYID
, keyid
, BUILD_END
);
148 if (*filename
== '/')
150 snprintf(path
, sizeof(path
), "%s", filename
);
154 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
157 cert
= lib
->creds
->create(lib
->creds
,
158 CRED_CERTIFICATE
, CERT_ANY
,
159 BUILD_FROM_FILE
, path
,
164 cert
= this->creds
->add_cert_ref(this->creds
, TRUE
, cert
);
165 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
166 cert
->get_subject(cert
), filename
);
169 DBG1(DBG_CFG
, " loading certificate from '%s' failed", filename
);
173 METHOD(stroke_cred_t
, load_pubkey
, certificate_t
*,
174 private_stroke_cred_t
*this, key_type_t type
, char *filename
,
175 identification_t
*identity
)
180 if (streq(filename
, "%dns"))
184 else if (strncaseeq(filename
, "0x", 2) || strncaseeq(filename
, "0s", 2))
186 chunk_t printable_key
, rfc3110_key
;
189 printable_key
= chunk_create(filename
+ 2, strlen(filename
) - 2);
190 rfc3110_key
= strncaseeq(filename
, "0x", 2) ?
191 chunk_from_hex(printable_key
, NULL
) :
192 chunk_from_base64(printable_key
, NULL
);
193 key
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_RSA
,
194 BUILD_BLOB_DNSKEY
, rfc3110_key
,
196 free(rfc3110_key
.ptr
);
199 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,
201 BUILD_PUBLIC_KEY
, key
,
202 BUILD_SUBJECT
, identity
,
207 cert
= this->creds
->add_cert_ref(this->creds
, TRUE
, cert
);
208 DBG1(DBG_CFG
, " loaded %N public key for \"%Y\"",
209 key_type_names
, type
, identity
);
213 DBG1(DBG_CFG
, " loading %N public key for \"%Y\" failed",
214 key_type_names
, type
, identity
);
218 if (*filename
== '/')
220 snprintf(path
, sizeof(path
), "%s", filename
);
224 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
227 cert
= lib
->creds
->create(lib
->creds
,
228 CRED_CERTIFICATE
, CERT_TRUSTED_PUBKEY
,
229 BUILD_FROM_FILE
, path
,
230 BUILD_SUBJECT
, identity
,
234 cert
= this->creds
->add_cert_ref(this->creds
, TRUE
, cert
);
235 DBG1(DBG_CFG
, " loaded %N public key for \"%Y\" from '%s'",
236 key_type_names
, type
, identity
, filename
);
239 DBG1(DBG_CFG
, " loading %N public key for \"%Y\" from '%s' failed",
240 key_type_names
, type
, identity
, filename
);
246 * load trusted certificates from a directory
248 static void load_certdir(private_stroke_cred_t
*this, char *path
,
249 certificate_type_t type
, x509_flag_t flag
)
254 enumerator_t
*enumerator
= enumerator_create_directory(path
);
258 DBG1(DBG_CFG
, " reading directory failed");
262 while (enumerator
->enumerate(enumerator
, NULL
, &file
, &st
))
266 if (!S_ISREG(st
.st_mode
))
268 /* skip special file */
276 if (this->force_ca_cert
)
277 { /* treat this certificate as CA cert even it has no
278 * CA basic constraint */
279 cert
= lib
->creds
->create(lib
->creds
,
280 CRED_CERTIFICATE
, CERT_X509
,
281 BUILD_FROM_FILE
, file
, BUILD_X509_FLAG
,
286 cert
= lib
->creds
->create(lib
->creds
,
287 CRED_CERTIFICATE
, CERT_X509
,
288 BUILD_FROM_FILE
, file
, BUILD_END
);
292 x509_t
*x509
= (x509_t
*)cert
;
294 if (!(x509
->get_flags(x509
) & X509_CA
))
296 DBG1(DBG_CFG
, " ca certificate \"%Y\" lacks "
297 "ca basic constraint, discarded",
298 cert
->get_subject(cert
));
304 DBG1(DBG_CFG
, " loaded ca certificate \"%Y\" "
305 "from '%s'", cert
->get_subject(cert
), file
);
310 DBG1(DBG_CFG
, " loading ca certificate from '%s' "
315 { /* for all other flags, we add them to the certificate. */
316 cert
= lib
->creds
->create(lib
->creds
,
317 CRED_CERTIFICATE
, CERT_X509
,
318 BUILD_FROM_FILE
, file
,
319 BUILD_X509_FLAG
, flag
, BUILD_END
);
322 DBG1(DBG_CFG
, " loaded certificate \"%Y\" from '%s'",
323 cert
->get_subject(cert
), file
);
327 DBG1(DBG_CFG
, " loading certificate from '%s' "
333 this->creds
->add_cert(this->creds
, TRUE
, cert
);
337 cert
= lib
->creds
->create(lib
->creds
,
338 CRED_CERTIFICATE
, CERT_X509_CRL
,
339 BUILD_FROM_FILE
, file
,
343 this->creds
->add_crl(this->creds
, (crl_t
*)cert
);
344 DBG1(DBG_CFG
, " loaded crl from '%s'", file
);
348 DBG1(DBG_CFG
, " loading crl from '%s' failed", file
);
352 cert
= lib
->creds
->create(lib
->creds
,
353 CRED_CERTIFICATE
, CERT_X509_AC
,
354 BUILD_FROM_FILE
, file
,
358 this->creds
->add_cert(this->creds
, FALSE
, cert
);
359 DBG1(DBG_CFG
, " loaded attribute certificate from '%s'",
364 DBG1(DBG_CFG
, " loading attribute certificate from '%s' "
372 enumerator
->destroy(enumerator
);
375 METHOD(stroke_cred_t
, cache_cert
, void,
376 private_stroke_cred_t
*this, certificate_t
*cert
)
378 if (cert
->get_type(cert
) == CERT_X509_CRL
&& this->cachecrl
)
380 /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */
381 crl_t
*crl
= (crl_t
*)cert
;
384 if (this->creds
->add_crl(this->creds
, crl
))
389 chunk
= crl
->get_authKeyIdentifier(crl
);
390 hex
= chunk_to_hex(chunk
, NULL
, FALSE
);
391 snprintf(buf
, sizeof(buf
), "%s/%s.crl", CRL_DIR
, hex
.ptr
);
394 if (cert
->get_encoding(cert
, CERT_ASN1_DER
, &chunk
))
396 chunk_write(chunk
, buf
, "crl", 022, TRUE
);
403 METHOD(stroke_cred_t
, cachecrl
, void,
404 private_stroke_cred_t
*this, bool enabled
)
406 DBG1(DBG_CFG
, "crl caching to %s %s",
407 CRL_DIR
, enabled ?
"enabled" : "disabled");
408 this->cachecrl
= enabled
;
413 * Convert a string of characters into a binary secret
414 * A string between single or double quotes is treated as ASCII characters
415 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
417 static err_t
extract_secret(chunk_t
*secret
, chunk_t
*line
)
420 char delimiter
= ' ';
423 if (!eat_whitespace(line
))
425 return "missing secret";
428 if (*line
->ptr
== '\'' || *line
->ptr
== '"')
431 delimiter
= *line
->ptr
;
432 line
->ptr
++; line
->len
--;
435 if (!extract_token(&raw_secret
, delimiter
, line
))
437 if (delimiter
== ' ')
443 return "missing second delimiter";
449 /* treat as an ASCII string */
450 *secret
= chunk_clone(raw_secret
);
453 /* treat 0x as hex, 0s as base64 */
454 if (raw_secret
.len
> 2)
456 if (strncasecmp("0x", raw_secret
.ptr
, 2) == 0)
458 *secret
= chunk_from_hex(chunk_skip(raw_secret
, 2), NULL
);
461 if (strncasecmp("0s", raw_secret
.ptr
, 2) == 0)
463 *secret
= chunk_from_base64(chunk_skip(raw_secret
, 2), NULL
);
467 *secret
= chunk_clone(raw_secret
);
472 * Data for passphrase callback
475 /** socket we use for prompting */
477 /** private key file */
479 /** number of tries */
481 } passphrase_cb_data_t
;
484 * Callback function to receive Passphrases
486 static shared_key_t
* passphrase_cb(passphrase_cb_data_t
*data
,
487 shared_key_type_t type
,
488 identification_t
*me
, identification_t
*other
,
489 id_match_t
*match_me
, id_match_t
*match_other
)
494 if (type
!= SHARED_ANY
&& type
!= SHARED_PRIVATE_KEY_PASS
)
503 fprintf(data
->prompt
, "PIN invalid, giving up.\n");
506 fprintf(data
->prompt
, "PIN invalid!\n");
509 fprintf(data
->prompt
, "Private key '%s' is encrypted.\n", data
->path
);
510 fprintf(data
->prompt
, "Passphrase:\n");
511 if (fgets(buf
, sizeof(buf
), data
->prompt
))
513 secret
= chunk_create(buf
, strlen(buf
));
515 { /* trim appended \n */
519 *match_me
= ID_MATCH_PERFECT
;
523 *match_other
= ID_MATCH_NONE
;
525 return shared_key_create(SHARED_PRIVATE_KEY_PASS
, chunk_clone(secret
));
532 * Data for PIN callback
535 /** socket we use for prompting */
541 /** number of tries */
546 * Callback function to receive PINs
548 static shared_key_t
* pin_cb(pin_cb_data_t
*data
, shared_key_type_t type
,
549 identification_t
*me
, identification_t
*other
,
550 id_match_t
*match_me
, id_match_t
*match_other
)
555 if (type
!= SHARED_ANY
&& type
!= SHARED_PIN
)
560 if (!me
|| !chunk_equals(me
->get_encoding(me
), data
->keyid
))
567 fprintf(data
->prompt
, "PIN invalid, aborting.\n");
571 fprintf(data
->prompt
, "Login to '%s' required\n", data
->card
);
572 fprintf(data
->prompt
, "PIN:\n");
573 if (fgets(buf
, sizeof(buf
), data
->prompt
))
575 secret
= chunk_create(buf
, strlen(buf
));
577 { /* trim appended \n */
581 *match_me
= ID_MATCH_PERFECT
;
585 *match_other
= ID_MATCH_NONE
;
587 return shared_key_create(SHARED_PIN
, chunk_clone(secret
));
594 * Load a smartcard with a PIN
596 static bool load_pin(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
599 chunk_t sc
= chunk_empty
, secret
= chunk_empty
;
600 char smartcard
[64], keyid
[64], module
[64], *pos
;
601 private_key_t
*key
= NULL
;
604 shared_key_t
*shared
;
605 identification_t
*id
;
606 mem_cred_t
*mem
= NULL
;
607 callback_cred_t
*cb
= NULL
;
608 pin_cb_data_t pin_data
;
610 SC_FORMAT_SLOT_MODULE_KEYID
,
611 SC_FORMAT_SLOT_KEYID
,
615 err_t ugh
= extract_value(&sc
, &line
);
619 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
624 DBG1(DBG_CFG
, "line %d: expected %%smartcard specifier", line_nr
);
627 snprintf(smartcard
, sizeof(smartcard
), "%.*s", (int)sc
.len
, sc
.ptr
);
628 smartcard
[sizeof(smartcard
) - 1] = '\0';
630 /* parse slot and key id. Three formats are supported:
631 * - %smartcard<slot>@<module>:<keyid>
632 * - %smartcard<slot>:<keyid>
633 * - %smartcard:<keyid>
635 if (sscanf(smartcard
, "%%smartcard%u@%s", &slot
, module
) == 2)
637 pos
= strchr(module
, ':');
640 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is "
645 strncpy(keyid
, pos
+ 1, sizeof(keyid
));
646 format
= SC_FORMAT_SLOT_MODULE_KEYID
;
648 else if (sscanf(smartcard
, "%%smartcard%u:%s", &slot
, keyid
) == 2)
650 format
= SC_FORMAT_SLOT_KEYID
;
652 else if (sscanf(smartcard
, "%%smartcard:%s", keyid
) == 1)
654 format
= SC_FORMAT_KEYID
;
658 DBG1(DBG_CFG
, "line %d: the given %%smartcard specifier is not"
659 " supported or invalid", line_nr
);
663 if (!eat_whitespace(&line
))
665 DBG1(DBG_CFG
, "line %d: expected PIN", line_nr
);
668 ugh
= extract_secret(&secret
, &line
);
671 DBG1(DBG_CFG
, "line %d: malformed PIN: %s", line_nr
, ugh
);
675 chunk
= chunk_from_hex(chunk_create(keyid
, strlen(keyid
)), NULL
);
676 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
680 { /* no IO channel to prompt, skip */
684 /* use callback credential set to prompt for the pin */
685 pin_data
.prompt
= prompt
;
686 pin_data
.card
= smartcard
;
687 pin_data
.keyid
= chunk
;
689 cb
= callback_cred_create_shared((void*)pin_cb
, &pin_data
);
690 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
, FALSE
);
694 /* provide our pin in a temporary credential set */
695 shared
= shared_key_create(SHARED_PIN
, secret
);
696 id
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
697 mem
= mem_cred_create();
698 mem
->add_shared(mem
, shared
, id
, NULL
);
699 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
, FALSE
);
702 /* unlock: smartcard needs the pin and potentially calls public set */
705 case SC_FORMAT_SLOT_MODULE_KEYID
:
706 key
= lib
->creds
->create(lib
->creds
,
707 CRED_PRIVATE_KEY
, KEY_ANY
,
708 BUILD_PKCS11_SLOT
, slot
,
709 BUILD_PKCS11_MODULE
, module
,
710 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
712 case SC_FORMAT_SLOT_KEYID
:
713 key
= lib
->creds
->create(lib
->creds
,
714 CRED_PRIVATE_KEY
, KEY_ANY
,
715 BUILD_PKCS11_SLOT
, slot
,
716 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
718 case SC_FORMAT_KEYID
:
719 key
= lib
->creds
->create(lib
->creds
,
720 CRED_PRIVATE_KEY
, KEY_ANY
,
721 BUILD_PKCS11_KEYID
, chunk
, BUILD_END
);
726 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
731 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
738 DBG1(DBG_CFG
, " loaded private key from %.*s", (int)sc
.len
, sc
.ptr
);
739 this->creds
->add_key(this->creds
, key
);
747 static bool load_private(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
748 FILE *prompt
, key_type_t key_type
)
752 chunk_t secret
= chunk_empty
;
755 err_t ugh
= extract_value(&filename
, &line
);
759 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
762 if (filename
.len
== 0)
764 DBG1(DBG_CFG
, "line %d: empty filename", line_nr
);
767 if (*filename
.ptr
== '/')
769 /* absolute path name */
770 snprintf(path
, sizeof(path
), "%.*s", (int)filename
.len
, filename
.ptr
);
774 /* relative path name */
775 snprintf(path
, sizeof(path
), "%s/%.*s", PRIVATE_KEY_DIR
,
776 (int)filename
.len
, filename
.ptr
);
779 /* check for optional passphrase */
780 if (eat_whitespace(&line
))
782 ugh
= extract_secret(&secret
, &line
);
785 DBG1(DBG_CFG
, "line %d: malformed passphrase: %s", line_nr
, ugh
);
789 if (secret
.len
== 7 && strneq(secret
.ptr
, "%prompt", 7))
791 callback_cred_t
*cb
= NULL
;
792 passphrase_cb_data_t pp_data
= {
803 /* use callback credential set to prompt for the passphrase */
804 pp_data
.prompt
= prompt
;
807 cb
= callback_cred_create_shared((void*)passphrase_cb
, &pp_data
);
808 lib
->credmgr
->add_local_set(lib
->credmgr
, &cb
->set
, FALSE
);
810 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
811 BUILD_FROM_FILE
, path
, BUILD_END
);
813 lib
->credmgr
->remove_local_set(lib
->credmgr
, &cb
->set
);
818 mem_cred_t
*mem
= NULL
;
819 shared_key_t
*shared
;
821 /* provide our pin in a temporary credential set */
822 shared
= shared_key_create(SHARED_PRIVATE_KEY_PASS
, secret
);
823 mem
= mem_cred_create();
824 mem
->add_shared(mem
, shared
, NULL
);
825 lib
->credmgr
->add_local_set(lib
->credmgr
, &mem
->set
, FALSE
);
827 key
= lib
->creds
->create(lib
->creds
, CRED_PRIVATE_KEY
, key_type
,
828 BUILD_FROM_FILE
, path
, BUILD_END
);
830 lib
->credmgr
->remove_local_set(lib
->credmgr
, &mem
->set
);
835 DBG1(DBG_CFG
, " loaded %N private key from '%s'",
836 key_type_names
, key
->get_type(key
), path
);
837 this->creds
->add_key(this->creds
, key
);
841 DBG1(DBG_CFG
, " loading private key from '%s' failed", path
);
849 static bool load_shared(private_stroke_cred_t
*this, chunk_t line
, int line_nr
,
850 shared_key_type_t type
, chunk_t ids
)
852 shared_key_t
*shared_key
;
853 linked_list_t
*owners
;
854 chunk_t secret
= chunk_empty
;
857 err_t ugh
= extract_secret(&secret
, &line
);
860 DBG1(DBG_CFG
, "line %d: malformed secret: %s", line_nr
, ugh
);
863 shared_key
= shared_key_create(type
, secret
);
864 DBG1(DBG_CFG
, " loaded %N secret for %s", shared_key_type_names
, type
,
865 ids
.len
> 0 ?
(char*)ids
.ptr
: "%any");
866 DBG4(DBG_CFG
, " secret: %#B", &secret
);
868 owners
= linked_list_create();
872 identification_t
*peer_id
;
874 ugh
= extract_value(&id
, &ids
);
877 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
878 shared_key
->destroy(shared_key
);
879 owners
->destroy_offset(owners
, offsetof(identification_t
, destroy
));
887 /* NULL terminate the ID string */
888 *(id
.ptr
+ id
.len
) = '\0';
889 peer_id
= identification_create_from_string(id
.ptr
);
890 if (peer_id
->get_type(peer_id
) == ID_ANY
)
892 peer_id
->destroy(peer_id
);
896 owners
->insert_last(owners
, peer_id
);
901 owners
->insert_last(owners
,
902 identification_create_from_encoding(ID_ANY
, chunk_empty
));
904 this->creds
->add_shared_list(this->creds
, shared_key
, owners
);
909 * reload ipsec.secrets
911 static void load_secrets(private_stroke_cred_t
*this, char *file
, int level
,
919 DBG1(DBG_CFG
, "loading secrets from '%s'", file
);
920 fd
= open(file
, O_RDONLY
);
923 DBG1(DBG_CFG
, "opening secrets file '%s' failed: %s", file
,
927 if (fstat(fd
, &sb
) == -1)
929 DBG1(DBG_LIB
, "getting file size of '%s' failed: %s", file
,
934 addr
= mmap(NULL
, sb
.st_size
, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0);
935 if (addr
== MAP_FAILED
)
937 DBG1(DBG_LIB
, "mapping '%s' failed: %s", file
, strerror(errno
));
941 src
= chunk_create(addr
, sb
.st_size
);
944 { /* flush secrets on non-recursive invocation */
945 this->creds
->clear_secrets(this->creds
);
948 while (fetchline(&src
, &line
))
951 shared_key_type_t type
;
955 if (!eat_whitespace(&line
))
959 if (line
.len
> strlen("include ") &&
960 strneq(line
.ptr
, "include ", strlen("include ")))
962 char **expanded
, *dir
, pattern
[PATH_MAX
];
965 if (level
> MAX_SECRETS_RECURSION
)
967 DBG1(DBG_CFG
, "maximum level of %d includes reached, ignored",
968 MAX_SECRETS_RECURSION
);
971 /* terminate filename by space */
972 line
= chunk_skip(line
, strlen("include "));
973 pos
= memchr(line
.ptr
, ' ', line
.len
);
976 line
.len
= pos
- line
.ptr
;
978 if (line
.len
&& line
.ptr
[0] == '/')
980 if (line
.len
+ 1 > sizeof(pattern
))
982 DBG1(DBG_CFG
, "include pattern too long, ignored");
985 snprintf(pattern
, sizeof(pattern
), "%.*s",
986 (int)line
.len
, line
.ptr
);
989 { /* use directory of current file if relative */
993 if (line
.len
+ 1 + strlen(dir
) + 1 > sizeof(pattern
))
995 DBG1(DBG_CFG
, "include pattern too long, ignored");
999 snprintf(pattern
, sizeof(pattern
), "%s/%.*s",
1000 dir
, (int)line
.len
, line
.ptr
);
1006 if (glob(pattern
, GLOB_ERR
, NULL
, &buf
) != 0)
1008 DBG1(DBG_CFG
, "expanding file expression '%s' failed",
1013 for (expanded
= buf
.gl_pathv
; *expanded
!= NULL
; expanded
++)
1015 load_secrets(this, *expanded
, level
+ 1, prompt
);
1020 #else /* HAVE_GLOB_H */
1021 /* if glob(3) is not available, try to load pattern directly */
1022 load_secrets(this, pattern
, level
+ 1, prompt
);
1023 #endif /* HAVE_GLOB_H */
1027 if (line
.len
> 2 && strneq(": ", line
.ptr
, 2))
1029 /* no ids, skip the ':' */
1034 else if (extract_token_str(&ids
, " : ", &line
))
1036 /* NULL terminate the extracted id string */
1037 *(ids
.ptr
+ ids
.len
) = '\0';
1041 DBG1(DBG_CFG
, "line %d: missing ' : ' separator", line_nr
);
1045 if (!eat_whitespace(&line
) || !extract_token(&token
, ' ', &line
))
1047 DBG1(DBG_CFG
, "line %d: missing token", line_nr
);
1050 if (match("RSA", &token
) || match("ECDSA", &token
))
1052 if (!load_private(this, line
, line_nr
, prompt
,
1053 match("RSA", &token
) ? KEY_RSA
: KEY_ECDSA
))
1058 else if (match("PIN", &token
))
1060 if (!load_pin(this, line
, line_nr
, prompt
))
1065 else if ((match("PSK", &token
) && (type
= SHARED_IKE
)) ||
1066 (match("EAP", &token
) && (type
= SHARED_EAP
)) ||
1067 (match("NTLM", &token
) && (type
= SHARED_NT_HASH
)) ||
1068 (match("XAUTH", &token
) && (type
= SHARED_EAP
)))
1070 if (!load_shared(this, line
, line_nr
, type
, ids
))
1077 DBG1(DBG_CFG
, "line %d: token must be either "
1078 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr
);
1082 munmap(addr
, sb
.st_size
);
1087 * load all certificates from ipsec.d
1089 static void load_certs(private_stroke_cred_t
*this)
1091 DBG1(DBG_CFG
, "loading ca certificates from '%s'",
1092 CA_CERTIFICATE_DIR
);
1093 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1095 DBG1(DBG_CFG
, "loading aa certificates from '%s'",
1096 AA_CERTIFICATE_DIR
);
1097 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1099 DBG1(DBG_CFG
, "loading ocsp signer certificates from '%s'",
1100 OCSP_CERTIFICATE_DIR
);
1101 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
, X509_OCSP_SIGNER
);
1103 DBG1(DBG_CFG
, "loading attribute certificates from '%s'",
1104 ATTR_CERTIFICATE_DIR
);
1105 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1107 DBG1(DBG_CFG
, "loading crls from '%s'",
1109 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1112 METHOD(stroke_cred_t
, reread
, void,
1113 private_stroke_cred_t
*this, stroke_msg_t
*msg
, FILE *prompt
)
1115 if (msg
->reread
.flags
& REREAD_SECRETS
)
1117 DBG1(DBG_CFG
, "rereading secrets");
1118 load_secrets(this, SECRETS_FILE
, 0, prompt
);
1120 if (msg
->reread
.flags
& REREAD_CACERTS
)
1122 DBG1(DBG_CFG
, "rereading ca certificates from '%s'",
1123 CA_CERTIFICATE_DIR
);
1124 load_certdir(this, CA_CERTIFICATE_DIR
, CERT_X509
, X509_CA
);
1126 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1128 DBG1(DBG_CFG
, "rereading ocsp signer certificates from '%s'",
1129 OCSP_CERTIFICATE_DIR
);
1130 load_certdir(this, OCSP_CERTIFICATE_DIR
, CERT_X509
,
1133 if (msg
->reread
.flags
& REREAD_AACERTS
)
1135 DBG1(DBG_CFG
, "rereading aa certificates from '%s'",
1136 AA_CERTIFICATE_DIR
);
1137 load_certdir(this, AA_CERTIFICATE_DIR
, CERT_X509
, X509_AA
);
1139 if (msg
->reread
.flags
& REREAD_ACERTS
)
1141 DBG1(DBG_CFG
, "rereading attribute certificates from '%s'",
1142 ATTR_CERTIFICATE_DIR
);
1143 load_certdir(this, ATTR_CERTIFICATE_DIR
, CERT_X509_AC
, 0);
1145 if (msg
->reread
.flags
& REREAD_CRLS
)
1147 DBG1(DBG_CFG
, "rereading crls from '%s'",
1149 load_certdir(this, CRL_DIR
, CERT_X509_CRL
, 0);
1153 METHOD(stroke_cred_t
, add_shared
, void,
1154 private_stroke_cred_t
*this, shared_key_t
*shared
, linked_list_t
*owners
)
1156 this->creds
->add_shared_list(this->creds
, shared
, owners
);
1159 METHOD(stroke_cred_t
, destroy
, void,
1160 private_stroke_cred_t
*this)
1162 lib
->credmgr
->remove_set(lib
->credmgr
, &this->creds
->set
);
1163 this->creds
->destroy(this->creds
);
1170 stroke_cred_t
*stroke_cred_create()
1172 private_stroke_cred_t
*this;
1177 .create_private_enumerator
= (void*)return_null
,
1178 .create_cert_enumerator
= (void*)return_null
,
1179 .create_shared_enumerator
= (void*)return_null
,
1180 .create_cdp_enumerator
= (void*)return_null
,
1181 .cache_cert
= (void*)_cache_cert
,
1184 .load_ca
= _load_ca
,
1185 .load_peer
= _load_peer
,
1186 .load_pubkey
= _load_pubkey
,
1187 .add_shared
= _add_shared
,
1188 .cachecrl
= _cachecrl
,
1189 .destroy
= _destroy
,
1191 .creds
= mem_cred_create(),
1194 lib
->credmgr
->add_set(lib
->credmgr
, &this->creds
->set
);
1196 this->force_ca_cert
= lib
->settings
->get_bool(lib
->settings
,
1197 "%s.plugins.stroke.ignore_missing_ca_basic_constraint",
1198 FALSE
, charon
->name
);
1201 load_secrets(this, SECRETS_FILE
, 0, NULL
);
1203 return &this->public;