added support for ipsec.secrets "include" directive
[strongswan.git] / src / charon / plugins / stroke / stroke_cred.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 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
17 #include <sys/stat.h>
18 #include <limits.h>
19 #include <glob.h>
20 #include <libgen.h>
21
22 #include "stroke_cred.h"
23 #include "stroke_shared_key.h"
24
25 #include <credentials/certificates/x509.h>
26 #include <credentials/certificates/crl.h>
27 #include <credentials/certificates/ac.h>
28 #include <utils/linked_list.h>
29 #include <utils/lexparser.h>
30 #include <utils/mutex.h>
31 #include <asn1/pem.h>
32 #include <daemon.h>
33
34 /* configuration directories and files */
35 #define CONFIG_DIR IPSEC_CONFDIR
36 #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d"
37 #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private"
38 #define CERTIFICATE_DIR IPSEC_D_DIR "/certs"
39 #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts"
40 #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts"
41 #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts"
42 #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts"
43 #define CRL_DIR IPSEC_D_DIR "/crls"
44 #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets"
45
46 #define MAX_SECRETS_RECURSION 10
47
48 typedef struct private_stroke_cred_t private_stroke_cred_t;
49
50 /**
51 * private data of stroke_cred
52 */
53 struct private_stroke_cred_t {
54
55 /**
56 * public functions
57 */
58 stroke_cred_t public;
59
60 /**
61 * list of trusted peer/signer/CA certificates (certificate_t)
62 */
63 linked_list_t *certs;
64
65 /**
66 * list of shared secrets (private_shared_key_t)
67 */
68 linked_list_t *shared;
69
70 /**
71 * list of private keys (private_key_t)
72 */
73 linked_list_t *private;
74
75 /**
76 * read-write lock to lists
77 */
78 rwlock_t *lock;
79
80 /**
81 * cache CRLs to disk?
82 */
83 bool cachecrl;
84 };
85
86 /**
87 * data to pass to various filters
88 */
89 typedef struct {
90 private_stroke_cred_t *this;
91 identification_t *id;
92 } id_data_t;
93
94 /**
95 * destroy id enumerator data and unlock list
96 */
97 static void id_data_destroy(id_data_t *data)
98 {
99 data->this->lock->unlock(data->this->lock);
100 free(data);
101 }
102
103 /**
104 * filter function for private key enumerator
105 */
106 static bool private_filter(id_data_t *data,
107 private_key_t **in, private_key_t **out)
108 {
109 identification_t *candidate;
110 id_type_t type;
111
112 if (data->id == NULL)
113 {
114 *out = *in;
115 return TRUE;
116 }
117 type = data->id->get_type(data->id);
118 if (type == ID_KEY_ID)
119 { /* handle ID_KEY_ID as a ID_PUBKEY_SHA1 */
120 type = ID_PUBKEY_SHA1;
121 }
122 candidate = (*in)->get_id(*in, type);
123 if (candidate &&
124 chunk_equals(candidate->get_encoding(candidate),
125 data->id->get_encoding(data->id)))
126 {
127 *out = *in;
128 return TRUE;
129 }
130 return FALSE;
131 }
132
133 /**
134 * Implements credential_set_t.create_private_enumerator
135 */
136 static enumerator_t* create_private_enumerator(private_stroke_cred_t *this,
137 key_type_t type, identification_t *id)
138 {
139 id_data_t *data;
140
141 data = malloc_thing(id_data_t);
142 data->this = this;
143 data->id = id;
144
145 this->lock->read_lock(this->lock);
146 return enumerator_create_filter(this->private->create_enumerator(this->private),
147 (void*)private_filter, data,
148 (void*)id_data_destroy);
149 }
150
151 /**
152 * filter function for certs enumerator
153 */
154 static bool certs_filter(id_data_t *data, certificate_t **in, certificate_t **out)
155 {
156 public_key_t *public;
157 identification_t *candidate;
158 certificate_t *cert = *in;
159 certificate_type_t type = cert->get_type(cert);
160
161 if (type == CERT_X509_CRL || type == CERT_X509_AC)
162 {
163 return FALSE;
164 }
165
166 if (data->id == NULL || cert->has_subject(cert, data->id))
167 {
168 *out = *in;
169 return TRUE;
170 }
171
172 public = (cert)->get_public_key(cert);
173 if (public)
174 {
175 candidate = public->get_id(public, data->id->get_type(data->id));
176 if (candidate && data->id->equals(data->id, candidate))
177 {
178 public->destroy(public);
179 *out = *in;
180 return TRUE;
181 }
182 public->destroy(public);
183 }
184 return FALSE;
185 }
186
187 /**
188 * filter function for crl enumerator
189 */
190 static bool crl_filter(id_data_t *data, certificate_t **in, certificate_t **out)
191 {
192 certificate_t *cert = *in;
193
194 if (cert->get_type(cert) != CERT_X509_CRL)
195 {
196 return FALSE;
197 }
198
199 if (data->id == NULL || cert->has_issuer(cert, data->id))
200 {
201 *out = *in;
202 return TRUE;
203 }
204 return FALSE;
205 }
206
207 /**
208 * filter function for attribute certificate enumerator
209 */
210 static bool ac_filter(id_data_t *data, certificate_t **in, certificate_t **out)
211 {
212 certificate_t *cert = *in;
213
214 if (cert->get_type(cert) != CERT_X509_AC)
215 {
216 return FALSE;
217 }
218
219 if (data->id == NULL || cert->has_subject(cert, data->id))
220 {
221 *out = *in;
222 return TRUE;
223 }
224 return FALSE;
225 }
226
227 /**
228 * Implements credential_set_t.create_cert_enumerator
229 */
230 static enumerator_t* create_cert_enumerator(private_stroke_cred_t *this,
231 certificate_type_t cert, key_type_t key,
232 identification_t *id, bool trusted)
233 {
234 id_data_t *data;
235
236 if (cert == CERT_X509_CRL || cert == CERT_X509_AC)
237 {
238 if (trusted)
239 {
240 return NULL;
241 }
242 data = malloc_thing(id_data_t);
243 data->this = this;
244 data->id = id;
245
246 this->lock->read_lock(this->lock);
247 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
248 (cert == CERT_X509_CRL)? (void*)crl_filter : (void*)ac_filter,
249 data, (void*)id_data_destroy);
250 }
251 if (cert != CERT_X509 && cert != CERT_ANY)
252 { /* we only have X509 certificates. TODO: ACs? */
253 return NULL;
254 }
255 data = malloc_thing(id_data_t);
256 data->this = this;
257 data->id = id;
258
259 this->lock->read_lock(this->lock);
260 return enumerator_create_filter(this->certs->create_enumerator(this->certs),
261 (void*)certs_filter, data,
262 (void*)id_data_destroy);
263 }
264
265 typedef struct {
266 private_stroke_cred_t *this;
267 identification_t *me;
268 identification_t *other;
269 shared_key_type_t type;
270 } shared_data_t;
271
272 /**
273 * free shared key enumerator data and unlock list
274 */
275 static void shared_data_destroy(shared_data_t *data)
276 {
277 data->this->lock->unlock(data->this->lock);
278 free(data);
279 }
280
281 /**
282 * filter function for certs enumerator
283 */
284 static bool shared_filter(shared_data_t *data,
285 stroke_shared_key_t **in, shared_key_t **out,
286 void **unused1, id_match_t *me,
287 void **unused2, id_match_t *other)
288 {
289 id_match_t my_match, other_match;
290 stroke_shared_key_t *stroke = *in;
291 shared_key_t *shared = &stroke->shared;
292
293 if (data->type != SHARED_ANY && shared->get_type(shared) != data->type)
294 {
295 return FALSE;
296 }
297
298 my_match = stroke->has_owner(stroke, data->me);
299 other_match = stroke->has_owner(stroke, data->other);
300 if (!my_match && !other_match)
301 {
302 return FALSE;
303 }
304 *out = shared;
305 if (me)
306 {
307 *me = my_match;
308 }
309 if (other)
310 {
311 *other = other_match;
312 }
313 return TRUE;
314 }
315
316 /**
317 * Implements credential_set_t.create_shared_enumerator
318 */
319 static enumerator_t* create_shared_enumerator(private_stroke_cred_t *this,
320 shared_key_type_t type, identification_t *me,
321 identification_t *other)
322 {
323 shared_data_t *data = malloc_thing(shared_data_t);
324
325 data->this = this;
326 data->me = me;
327 data->other = other;
328 data->type = type;
329 this->lock->read_lock(this->lock);
330 return enumerator_create_filter(this->shared->create_enumerator(this->shared),
331 (void*)shared_filter, data,
332 (void*)shared_data_destroy);
333 }
334
335 /**
336 * Add a certificate to chain
337 */
338 static certificate_t* add_cert(private_stroke_cred_t *this, certificate_t *cert)
339 {
340 certificate_t *current;
341 enumerator_t *enumerator;
342 bool new = TRUE;
343
344 this->lock->read_lock(this->lock);
345 enumerator = this->certs->create_enumerator(this->certs);
346 while (enumerator->enumerate(enumerator, (void**)&current))
347 {
348 if (current->equals(current, cert))
349 {
350 /* cert already in queue */
351 cert->destroy(cert);
352 cert = current;
353 new = FALSE;
354 break;
355 }
356 }
357 enumerator->destroy(enumerator);
358
359 if (new)
360 {
361 this->certs->insert_last(this->certs, cert);
362 }
363 this->lock->unlock(this->lock);
364 return cert;
365 }
366
367 /**
368 * Implementation of stroke_cred_t.load_ca.
369 */
370 static certificate_t* load_ca(private_stroke_cred_t *this, char *filename)
371 {
372 certificate_t *cert;
373 char path[PATH_MAX];
374
375 if (*filename == '/')
376 {
377 snprintf(path, sizeof(path), "%s", filename);
378 }
379 else
380 {
381 snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
382 }
383
384 cert = lib->creds->create(lib->creds,
385 CRED_CERTIFICATE, CERT_X509,
386 BUILD_FROM_FILE, path,
387 BUILD_END);
388 if (cert)
389 {
390 x509_t *x509 = (x509_t*)cert;
391
392 if (!(x509->get_flags(x509) & X509_CA))
393 {
394 cert->destroy(cert);
395 DBG1(DBG_CFG, " ca certificate must have ca basic constraint set, "
396 "discarded");
397 return NULL;
398 }
399 return (certificate_t*)add_cert(this, cert);
400 }
401 return NULL;
402 }
403
404 /**
405 * Add X.509 CRL to chain
406 */
407 static bool add_crl(private_stroke_cred_t *this, crl_t* crl)
408 {
409 certificate_t *current, *cert = &crl->certificate;
410 enumerator_t *enumerator;
411 bool new = TRUE, found = FALSE;
412
413 this->lock->write_lock(this->lock);
414 enumerator = this->certs->create_enumerator(this->certs);
415 while (enumerator->enumerate(enumerator, (void**)&current))
416 {
417 if (current->get_type(current) == CERT_X509_CRL)
418 {
419 crl_t *crl_c = (crl_t*)current;
420 identification_t *authkey = crl->get_authKeyIdentifier(crl);
421 identification_t *authkey_c = crl_c->get_authKeyIdentifier(crl_c);
422
423 /* if compare authorityKeyIdentifiers if available */
424 if (authkey != NULL && authkey_c != NULL &&
425 authkey->equals(authkey, authkey_c))
426 {
427 found = TRUE;
428 }
429 else
430 {
431 identification_t *issuer = cert->get_issuer(cert);
432 identification_t *issuer_c = current->get_issuer(current);
433
434 /* otherwise compare issuer distinguished names */
435 if (issuer->equals(issuer, issuer_c))
436 {
437 found = TRUE;
438 }
439 }
440 if (found)
441 {
442 new = cert->is_newer(cert, current);
443 if (new)
444 {
445 this->certs->remove_at(this->certs, enumerator);
446 }
447 else
448 {
449 cert->destroy(cert);
450 }
451 break;
452 }
453 }
454 }
455 enumerator->destroy(enumerator);
456
457 if (new)
458 {
459 this->certs->insert_last(this->certs, cert);
460 }
461 this->lock->unlock(this->lock);
462 return new;
463 }
464
465 /**
466 * Add X.509 attribute certificate to chain
467 */
468 static bool add_ac(private_stroke_cred_t *this, ac_t* ac)
469 {
470 certificate_t *cert = &ac->certificate;
471
472 this->lock->write_lock(this->lock);
473 this->certs->insert_last(this->certs, cert);
474 this->lock->unlock(this->lock);
475 return TRUE;
476 }
477
478 /**
479 * Implementation of stroke_cred_t.load_peer.
480 */
481 static certificate_t* load_peer(private_stroke_cred_t *this, char *filename)
482 {
483 certificate_t *cert;
484 char path[PATH_MAX];
485
486 if (*filename == '/')
487 {
488 snprintf(path, sizeof(path), "%s", filename);
489 }
490 else
491 {
492 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
493 }
494
495 cert = lib->creds->create(lib->creds,
496 CRED_CERTIFICATE, CERT_X509,
497 BUILD_FROM_FILE, path,
498 BUILD_X509_FLAG, 0,
499 BUILD_END);
500 if (cert)
501 {
502 cert = add_cert(this, cert);
503 return cert->get_ref(cert);
504 }
505 return NULL;
506 }
507
508 /**
509 * load trusted certificates from a directory
510 */
511 static void load_certdir(private_stroke_cred_t *this, char *path,
512 certificate_type_t type, x509_flag_t flag)
513 {
514 struct stat st;
515 char *file;
516
517 enumerator_t *enumerator = enumerator_create_directory(path);
518
519 if (!enumerator)
520 {
521 DBG1(DBG_CFG, " reading directory failed");
522 return;
523 }
524
525 while (enumerator->enumerate(enumerator, NULL, &file, &st))
526 {
527 certificate_t *cert;
528
529 if (!S_ISREG(st.st_mode))
530 {
531 /* skip special file */
532 continue;
533 }
534 switch (type)
535 {
536 case CERT_X509:
537 if (flag & X509_CA)
538 { /* for CA certificates, we strictly require CA
539 * basicconstraints to be set */
540 cert = lib->creds->create(lib->creds,
541 CRED_CERTIFICATE, CERT_X509,
542 BUILD_FROM_FILE, file, BUILD_END);
543 if (cert)
544 {
545 x509_t *x509 = (x509_t*)cert;
546
547 if (!(x509->get_flags(x509) & X509_CA))
548 {
549 DBG1(DBG_CFG, " ca certificate must have ca "
550 "basic constraint set, discarded");
551 cert->destroy(cert);
552 cert = NULL;
553 }
554 }
555 }
556 else
557 { /* for all other flags, we add them to the certificate. */
558 cert = lib->creds->create(lib->creds,
559 CRED_CERTIFICATE, CERT_X509,
560 BUILD_FROM_FILE, file,
561 BUILD_X509_FLAG, flag, BUILD_END);
562 }
563 if (cert)
564 {
565 add_cert(this, cert);
566 }
567 break;
568 case CERT_X509_CRL:
569 cert = lib->creds->create(lib->creds,
570 CRED_CERTIFICATE, CERT_X509_CRL,
571 BUILD_FROM_FILE, file,
572 BUILD_END);
573 if (cert)
574 {
575 add_crl(this, (crl_t*)cert);
576 }
577 break;
578 case CERT_X509_AC:
579 cert = lib->creds->create(lib->creds,
580 CRED_CERTIFICATE, CERT_X509_AC,
581 BUILD_FROM_FILE, file,
582 BUILD_END);
583 if (cert)
584 {
585 add_ac(this, (ac_t*)cert);
586 }
587 break;
588 default:
589 break;
590 }
591 }
592 enumerator->destroy(enumerator);
593 }
594
595 /**
596 * Implementation of credential_set_t.cache_cert.
597 */
598 static void cache_cert(private_stroke_cred_t *this, certificate_t *cert)
599 {
600 if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl)
601 {
602 /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */
603 crl_t *crl = (crl_t*)cert;
604
605 cert->get_ref(cert);
606 if (add_crl(this, crl))
607 {
608 char buf[BUF_LEN];
609 chunk_t chunk, hex;
610 identification_t *id;
611
612 id = crl->get_authKeyIdentifier(crl);
613 chunk = id->get_encoding(id);
614 hex = chunk_to_hex(chunk, NULL, FALSE);
615 snprintf(buf, sizeof(buf), "%s/%s.crl", CRL_DIR, hex);
616 free(hex.ptr);
617
618 chunk = cert->get_encoding(cert);
619 chunk_write(chunk, buf, "crl", 022, TRUE);
620 free(chunk.ptr);
621 }
622 }
623 }
624
625 /**
626 * Implementation of stroke_cred_t.cachecrl.
627 */
628 static void cachecrl(private_stroke_cred_t *this, bool enabled)
629 {
630 DBG1(DBG_CFG, "crl caching to %s %s",
631 CRL_DIR, enabled ? "enabled" : "disabled");
632 this->cachecrl = enabled;
633 }
634
635
636 /**
637 * Convert a string of characters into a binary secret
638 * A string between single or double quotes is treated as ASCII characters
639 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
640 */
641 static err_t extract_secret(chunk_t *secret, chunk_t *line)
642 {
643 chunk_t raw_secret;
644 char delimiter = ' ';
645 bool quotes = FALSE;
646
647 if (!eat_whitespace(line))
648 {
649 return "missing secret";
650 }
651
652 if (*line->ptr == '\'' || *line->ptr == '"')
653 {
654 quotes = TRUE;
655 delimiter = *line->ptr;
656 line->ptr++; line->len--;
657 }
658
659 if (!extract_token(&raw_secret, delimiter, line))
660 {
661 if (delimiter == ' ')
662 {
663 raw_secret = *line;
664 }
665 else
666 {
667 return "missing second delimiter";
668 }
669 }
670
671 if (quotes)
672 {
673 /* treat as an ASCII string */
674 *secret = chunk_clone(raw_secret);
675 return NULL;
676 }
677 /* treat 0x as hex, 0s as base64 */
678 if (raw_secret.len > 2)
679 {
680 if (strncasecmp("0x", raw_secret.ptr, 2) == 0)
681 {
682 *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL);
683 return NULL;
684 }
685 if (strncasecmp("0s", raw_secret.ptr, 2) == 0)
686 {
687 *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL);
688 return NULL;
689 }
690 }
691 *secret = chunk_clone(raw_secret);
692 return NULL;
693 }
694
695 /**
696 * reload ipsec.secrets
697 */
698 static void load_secrets(private_stroke_cred_t *this, char *file, int level)
699 {
700 size_t bytes;
701 int line_nr = 0;
702 chunk_t chunk, src, line;
703 FILE *fd;
704 private_key_t *private;
705 shared_key_t *shared;
706
707 DBG1(DBG_CFG, "loading secrets from '%s'", file);
708
709 fd = fopen(file, "r");
710 if (fd == NULL)
711 {
712 DBG1(DBG_CFG, "opening secrets file '%s' failed");
713 return;
714 }
715
716 /* TODO: do error checks */
717 fseek(fd, 0, SEEK_END);
718 chunk.len = ftell(fd);
719 rewind(fd);
720 chunk.ptr = malloc(chunk.len);
721 bytes = fread(chunk.ptr, 1, chunk.len, fd);
722 fclose(fd);
723 src = chunk;
724
725 this->lock->write_lock(this->lock);
726 if (level == 0)
727 {
728 /* flush secrets on non-recursive invocation */
729 while (this->shared->remove_last(this->shared,
730 (void**)&shared) == SUCCESS)
731 {
732 shared->destroy(shared);
733 }
734 while (this->private->remove_last(this->private,
735 (void**)&private) == SUCCESS)
736 {
737 private->destroy(private);
738 }
739 }
740
741 while (fetchline(&src, &line))
742 {
743 chunk_t ids, token;
744 shared_key_type_t type;
745
746 line_nr++;
747
748 if (!eat_whitespace(&line))
749 {
750 continue;
751 }
752 if (line.len > strlen("include ") &&
753 strneq(line.ptr, "include ", strlen("include ")))
754 {
755 glob_t buf;
756 char **expanded, *dir, pattern[PATH_MAX];
757 u_char *pos;
758
759 if (level > MAX_SECRETS_RECURSION)
760 {
761 DBG1(DBG_CFG, "maximum level of %d includes reached, ignored",
762 MAX_SECRETS_RECURSION);
763 continue;
764 }
765 /* terminate filename by space */
766 line = chunk_skip(line, strlen("include "));
767 pos = memchr(line.ptr, ' ', line.len);
768 if (pos)
769 {
770 line.len = pos - line.ptr;
771 }
772 if (line.len && line.ptr[0] == '/')
773 {
774 if (line.len + 1 > sizeof(pattern))
775 {
776 DBG1(DBG_CFG, "include pattern too long, ignored");
777 continue;
778 }
779 snprintf(pattern, sizeof(pattern), "%.*s", line.len, line.ptr);
780 }
781 else
782 { /* use directory of current file if relative */
783 dir = strdup(file);
784 dir = dirname(dir);
785
786 if (line.len + 1 + strlen(dir) + 1 > sizeof(pattern))
787 {
788 DBG1(DBG_CFG, "include pattern too long, ignored");
789 free(dir);
790 continue;
791 }
792 snprintf(pattern, sizeof(pattern), "%s/%.*s",
793 dir, line.len, line.ptr);
794 free(dir);
795 }
796 if (glob(pattern, GLOB_ERR, NULL, &buf) != 0)
797 {
798 DBG1(DBG_CFG, "expanding file expression '%s' failed", pattern);
799 globfree(&buf);
800 }
801 else
802 {
803 for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
804 {
805 load_secrets(this, *expanded, level + 1);
806 }
807 }
808 globfree(&buf);
809 continue;
810 }
811
812 if (line.len > 2 && strneq(": ", line.ptr, 2))
813 {
814 /* no ids, skip the ':' */
815 ids = chunk_empty;
816 line.ptr++;
817 line.len--;
818 }
819 else if (extract_token_str(&ids, " : ", &line))
820 {
821 /* NULL terminate the extracted id string */
822 *(ids.ptr + ids.len) = '\0';
823 }
824 else
825 {
826 DBG1(DBG_CFG, "line %d: missing ' : ' separator", line_nr);
827 goto error;
828 }
829
830 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
831 {
832 DBG1(DBG_CFG, "line %d: missing token", line_nr);
833 goto error;
834 }
835 if (match("RSA", &token) || match("ECDSA", &token))
836 {
837 char path[PATH_MAX];
838 chunk_t filename;
839 chunk_t secret = chunk_empty;
840 private_key_t *key;
841 bool pgp = FALSE;
842 chunk_t chunk = chunk_empty;
843 key_type_t key_type = match("RSA", &token) ? KEY_RSA : KEY_ECDSA;
844
845 err_t ugh = extract_value(&filename, &line);
846
847 if (ugh != NULL)
848 {
849 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
850 goto error;
851 }
852 if (filename.len == 0)
853 {
854 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
855 goto error;
856 }
857 if (*filename.ptr == '/')
858 {
859 /* absolute path name */
860 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
861 }
862 else
863 {
864 /* relative path name */
865 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
866 filename.len, filename.ptr);
867 }
868
869 /* check for optional passphrase */
870 if (eat_whitespace(&line))
871 {
872 ugh = extract_secret(&secret, &line);
873 if (ugh != NULL)
874 {
875 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
876 goto error;
877 }
878 }
879
880 if (pem_asn1_load_file(path, &secret, &chunk, &pgp))
881 {
882 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
883 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
884 free(chunk.ptr);
885 if (key)
886 {
887 DBG1(DBG_CFG, " loaded private key file '%s'", path);
888 this->private->insert_last(this->private, key);
889 }
890 }
891 chunk_clear(&secret);
892 }
893 else if (match("PIN", &token))
894 {
895 chunk_t sc = chunk_empty, secret = chunk_empty;
896 char smartcard[32], keyid[22], pin[32];
897 private_key_t *key;
898 u_int slot;
899
900 err_t ugh = extract_value(&sc, &line);
901
902 if (ugh != NULL)
903 {
904 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
905 goto error;
906 }
907 if (sc.len == 0)
908 {
909 DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr);
910 goto error;
911 }
912 snprintf(smartcard, sizeof(smartcard), "%.*s", sc.len, sc.ptr);
913 smartcard[sizeof(smartcard) - 1] = '\0';
914
915 /* parse slot and key id. only two formats are supported.
916 * first try %smartcard<slot>:<keyid> */
917 if (sscanf(smartcard, "%%smartcard%u:%s", &slot, keyid) == 2)
918 {
919 snprintf(smartcard, sizeof(smartcard), "%u:%s", slot, keyid);
920 }
921 /* then try %smartcard:<keyid> */
922 else if (sscanf(smartcard, "%%smartcard:%s", keyid) == 1)
923 {
924 snprintf(smartcard, sizeof(smartcard), "%s", keyid);
925 }
926 else
927 {
928 DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not"
929 " supported or invalid", line_nr);
930 goto error;
931 }
932
933 if (!eat_whitespace(&line))
934 {
935 DBG1(DBG_CFG, "line %d: expected PIN", line_nr);
936 goto error;
937 }
938 ugh = extract_secret(&secret, &line);
939 if (ugh != NULL)
940 {
941 DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh);
942 goto error;
943 }
944 snprintf(pin, sizeof(pin), "%.*s", secret.len, secret.ptr);
945 pin[sizeof(pin) - 1] = '\0';
946
947 /* we assume an RSA key */
948 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
949 BUILD_SMARTCARD_KEYID, smartcard,
950 BUILD_SMARTCARD_PIN, pin, BUILD_END);
951
952 if (key)
953 {
954 DBG1(DBG_CFG, " loaded private key from %.*s", sc.len, sc.ptr);
955 this->private->insert_last(this->private, key);
956 }
957 memset(pin, 0, sizeof(pin));
958 chunk_clear(&secret);
959 }
960 else if ((match("PSK", &token) && (type = SHARED_IKE)) ||
961 (match("EAP", &token) && (type = SHARED_EAP)) ||
962 (match("XAUTH", &token) && (type = SHARED_EAP)))
963 {
964 stroke_shared_key_t *shared_key;
965 chunk_t secret = chunk_empty;
966 bool any = TRUE;
967
968 err_t ugh = extract_secret(&secret, &line);
969 if (ugh != NULL)
970 {
971 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
972 goto error;
973 }
974 shared_key = stroke_shared_key_create(type, secret);
975 DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type,
976 ids.len > 0 ? (char*)ids.ptr : "%any");
977 DBG4(DBG_CFG, " secret: %#B", &secret);
978
979 this->shared->insert_last(this->shared, shared_key);
980 while (ids.len > 0)
981 {
982 chunk_t id;
983 identification_t *peer_id;
984
985 ugh = extract_value(&id, &ids);
986 if (ugh != NULL)
987 {
988 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
989 goto error;
990 }
991 if (id.len == 0)
992 {
993 continue;
994 }
995
996 /* NULL terminate the ID string */
997 *(id.ptr + id.len) = '\0';
998 peer_id = identification_create_from_string(id.ptr);
999 if (peer_id->get_type(peer_id) == ID_ANY)
1000 {
1001 peer_id->destroy(peer_id);
1002 continue;
1003 }
1004
1005 shared_key->add_owner(shared_key, peer_id);
1006 any = FALSE;
1007 }
1008 if (any)
1009 {
1010 shared_key->add_owner(shared_key,
1011 identification_create_from_encoding(ID_ANY, chunk_empty));
1012 }
1013 }
1014 else
1015 {
1016 DBG1(DBG_CFG, "line %d: token must be either "
1017 "RSA, ECDSA, PSK, EAP, XAUTH or PIN", line_nr);
1018 goto error;
1019 }
1020 }
1021 error:
1022 this->lock->unlock(this->lock);
1023 chunk_clear(&chunk);
1024 }
1025
1026 /**
1027 * load all certificates from ipsec.d
1028 */
1029 static void load_certs(private_stroke_cred_t *this)
1030 {
1031 DBG1(DBG_CFG, "loading ca certificates from '%s'",
1032 CA_CERTIFICATE_DIR);
1033 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
1034
1035 DBG1(DBG_CFG, "loading aa certificates from '%s'",
1036 AA_CERTIFICATE_DIR);
1037 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
1038
1039 DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
1040 OCSP_CERTIFICATE_DIR);
1041 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
1042
1043 DBG1(DBG_CFG, "loading attribute certificates from '%s'",
1044 ATTR_CERTIFICATE_DIR);
1045 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
1046
1047 DBG1(DBG_CFG, "loading crls from '%s'",
1048 CRL_DIR);
1049 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
1050 }
1051
1052 /**
1053 * Implementation of stroke_cred_t.reread.
1054 */
1055 static void reread(private_stroke_cred_t *this, stroke_msg_t *msg)
1056 {
1057 if (msg->reread.flags & REREAD_SECRETS)
1058 {
1059 DBG1(DBG_CFG, "rereading secrets");
1060 load_secrets(this, SECRETS_FILE, 0);
1061 }
1062 if (msg->reread.flags & REREAD_CACERTS)
1063 {
1064 DBG1(DBG_CFG, "rereading ca certificates from '%s'",
1065 CA_CERTIFICATE_DIR);
1066 load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
1067 }
1068 if (msg->reread.flags & REREAD_OCSPCERTS)
1069 {
1070 DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
1071 OCSP_CERTIFICATE_DIR);
1072 load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
1073 X509_OCSP_SIGNER);
1074 }
1075 if (msg->reread.flags & REREAD_AACERTS)
1076 {
1077 DBG1(DBG_CFG, "rereading aa certificates from '%s'",
1078 AA_CERTIFICATE_DIR);
1079 load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
1080 }
1081 if (msg->reread.flags & REREAD_ACERTS)
1082 {
1083 DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
1084 ATTR_CERTIFICATE_DIR);
1085 load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
1086 }
1087 if (msg->reread.flags & REREAD_CRLS)
1088 {
1089 DBG1(DBG_CFG, "rereading crls from '%s'",
1090 CRL_DIR);
1091 load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
1092 }
1093 }
1094
1095 /**
1096 * Implementation of stroke_cred_t.destroy
1097 */
1098 static void destroy(private_stroke_cred_t *this)
1099 {
1100 this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
1101 this->shared->destroy_offset(this->shared, offsetof(shared_key_t, destroy));
1102 this->private->destroy_offset(this->private, offsetof(private_key_t, destroy));
1103 this->lock->destroy(this->lock);
1104 free(this);
1105 }
1106
1107 /*
1108 * see header file
1109 */
1110 stroke_cred_t *stroke_cred_create()
1111 {
1112 private_stroke_cred_t *this = malloc_thing(private_stroke_cred_t);
1113
1114 this->public.set.create_private_enumerator = (void*)create_private_enumerator;
1115 this->public.set.create_cert_enumerator = (void*)create_cert_enumerator;
1116 this->public.set.create_shared_enumerator = (void*)create_shared_enumerator;
1117 this->public.set.create_cdp_enumerator = (void*)return_null;
1118 this->public.set.cache_cert = (void*)cache_cert;
1119 this->public.reread = (void(*)(stroke_cred_t*, stroke_msg_t *msg))reread;
1120 this->public.load_ca = (certificate_t*(*)(stroke_cred_t*, char *filename))load_ca;
1121 this->public.load_peer = (certificate_t*(*)(stroke_cred_t*, char *filename))load_peer;
1122 this->public.cachecrl = (void(*)(stroke_cred_t*, bool enabled))cachecrl;
1123 this->public.destroy = (void(*)(stroke_cred_t*))destroy;
1124
1125 this->certs = linked_list_create();
1126 this->shared = linked_list_create();
1127 this->private = linked_list_create();
1128 this->lock = rwlock_create(RWLOCK_DEFAULT);
1129
1130 load_certs(this);
1131 load_secrets(this, SECRETS_FILE, 0);
1132
1133 this->cachecrl = FALSE;
1134
1135 return &this->public;
1136 }
1137