Return to stroke_cred.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / stroke |
1.1 misho 1: /* 2: * Copyright (C) 2008-2017 Tobias Brunner 3: * Copyright (C) 2008 Martin Willi 4: * HSR 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/types.h> 18: #include <sys/stat.h> 19: #include <limits.h> 20: #include <fcntl.h> 21: #include <errno.h> 22: #include <unistd.h> 23: 24: #ifdef HAVE_GLOB_H 25: #include <glob.h> 26: #endif 27: 28: #include "stroke_cred.h" 29: 30: #include <credentials/certificates/x509.h> 31: #include <credentials/certificates/crl.h> 32: #include <credentials/certificates/ac.h> 33: #include <credentials/containers/pkcs12.h> 34: #include <credentials/sets/mem_cred.h> 35: #include <credentials/sets/callback_cred.h> 36: #include <collections/linked_list.h> 37: #include <utils/lexparser.h> 38: #include <threading/rwlock.h> 39: #include <daemon.h> 40: 41: /* configuration directories and files */ 42: #define CONFIG_DIR IPSEC_CONFDIR 43: #define IPSEC_D_DIR CONFIG_DIR "/ipsec.d" 44: #define PRIVATE_KEY_DIR IPSEC_D_DIR "/private" 45: #define CERTIFICATE_DIR IPSEC_D_DIR "/certs" 46: #define CA_CERTIFICATE_DIR IPSEC_D_DIR "/cacerts" 47: #define AA_CERTIFICATE_DIR IPSEC_D_DIR "/aacerts" 48: #define ATTR_CERTIFICATE_DIR IPSEC_D_DIR "/acerts" 49: #define OCSP_CERTIFICATE_DIR IPSEC_D_DIR "/ocspcerts" 50: #define CRL_DIR IPSEC_D_DIR "/crls" 51: #define SECRETS_FILE CONFIG_DIR "/ipsec.secrets" 52: 53: #define MAX_SECRETS_RECURSION 10 54: 55: typedef struct private_stroke_cred_t private_stroke_cred_t; 56: 57: /** 58: * private data of stroke_cred 59: */ 60: struct private_stroke_cred_t { 61: 62: /** 63: * public functions 64: */ 65: stroke_cred_t public; 66: 67: /** 68: * secrets file with credential information 69: */ 70: char *secrets_file; 71: 72: /** 73: * credentials: end entity certs, attribute certs, CRLs, etc. 74: */ 75: mem_cred_t *creds; 76: 77: /** 78: * Attribute Authority certificates 79: */ 80: mem_cred_t *aacerts; 81: 82: /** 83: * ignore missing CA basic constraint (i.e. treat all certificates in 84: * ipsec.conf ca sections and ipsec.d/cacerts as CA certificates) 85: */ 86: bool force_ca_cert; 87: 88: /** 89: * cache CRLs to disk? 90: */ 91: bool cachecrl; 92: 93: /** 94: * CA certificate store 95: */ 96: stroke_ca_t *ca; 97: }; 98: 99: /** Length of smartcard specifier parts (module, keyid) */ 100: #define SC_PART_LEN 128 101: 102: /** 103: * Kind of smartcard specifier token 104: */ 105: typedef enum { 106: SC_FORMAT_SLOT_MODULE_KEYID, 107: SC_FORMAT_SLOT_KEYID, 108: SC_FORMAT_KEYID, 109: SC_FORMAT_INVALID, 110: } smartcard_format_t; 111: 112: /** 113: * Parse a smartcard specifier token 114: */ 115: static smartcard_format_t parse_smartcard(char *smartcard, u_int *slot, 116: char *module, char *keyid) 117: { 118: /* The token has one of the following three formats: 119: * - %smartcard<slot>@<module>:<keyid> 120: * - %smartcard<slot>:<keyid> 121: * - %smartcard:<keyid> 122: */ 123: char buf[2 * SC_PART_LEN], *pos; 124: 125: if (sscanf(smartcard, "%%smartcard%u@%255s", slot, buf) == 2) 126: { 127: pos = strchr(buf, ':'); 128: if (!pos) 129: { 130: return SC_FORMAT_INVALID; 131: } 132: *pos++ = '\0'; 133: snprintf(module, SC_PART_LEN, "%s", buf); 134: snprintf(keyid, SC_PART_LEN, "%s", pos); 135: return SC_FORMAT_SLOT_MODULE_KEYID; 136: } 137: if (sscanf(smartcard, "%%smartcard%u:%127s", slot, keyid) == 2) 138: { 139: return SC_FORMAT_SLOT_KEYID; 140: } 141: if (sscanf(smartcard, "%%smartcard:%127s", keyid) == 1) 142: { 143: return SC_FORMAT_KEYID; 144: } 145: return SC_FORMAT_INVALID; 146: } 147: 148: /** 149: * Load a credential from a smartcard 150: */ 151: static certificate_t *load_from_smartcard(smartcard_format_t format, 152: u_int slot, char *module, char *keyid, 153: credential_type_t type, int subtype) 154: { 155: chunk_t chunk; 156: void *cred; 157: 158: chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); 159: switch (format) 160: { 161: case SC_FORMAT_SLOT_MODULE_KEYID: 162: cred = lib->creds->create(lib->creds, type, subtype, 163: BUILD_PKCS11_SLOT, slot, 164: BUILD_PKCS11_MODULE, module, 165: BUILD_PKCS11_KEYID, chunk, BUILD_END); 166: break; 167: case SC_FORMAT_SLOT_KEYID: 168: cred = lib->creds->create(lib->creds, type, subtype, 169: BUILD_PKCS11_SLOT, slot, 170: BUILD_PKCS11_KEYID, chunk, BUILD_END); 171: break; 172: case SC_FORMAT_KEYID: 173: cred = lib->creds->create(lib->creds, type, subtype, 174: BUILD_PKCS11_KEYID, chunk, BUILD_END); 175: break; 176: default: 177: cred = NULL; 178: break; 179: } 180: free(chunk.ptr); 181: 182: return cred; 183: } 184: 185: METHOD(stroke_cred_t, load_peer, certificate_t*, 186: private_stroke_cred_t *this, char *filename) 187: { 188: certificate_t *cert = NULL; 189: char path[PATH_MAX]; 190: 191: if (strpfx(filename, "%smartcard")) 192: { 193: smartcard_format_t format; 194: char module[SC_PART_LEN], keyid[SC_PART_LEN]; 195: u_int slot; 196: 197: format = parse_smartcard(filename, &slot, module, keyid); 198: if (format != SC_FORMAT_INVALID) 199: { 200: cert = (certificate_t*)load_from_smartcard(format, 201: slot, module, keyid, CRED_CERTIFICATE, CERT_X509); 202: } 203: } 204: else 205: { 206: if (*filename == '/') 207: { 208: snprintf(path, sizeof(path), "%s", filename); 209: } 210: else 211: { 212: snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); 213: } 214: 215: cert = lib->creds->create(lib->creds, 216: CRED_CERTIFICATE, CERT_ANY, 217: BUILD_FROM_FILE, path, 218: BUILD_END); 219: } 220: if (cert) 221: { 222: cert = this->creds->add_cert_ref(this->creds, TRUE, cert); 223: DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", 224: cert->get_subject(cert), filename); 225: return cert; 226: } 227: DBG1(DBG_CFG, " loading certificate from '%s' failed", filename); 228: return NULL; 229: } 230: 231: METHOD(stroke_cred_t, load_pubkey, certificate_t*, 232: private_stroke_cred_t *this, char *filename, identification_t *identity) 233: { 234: certificate_t *cert; 235: public_key_t *key; 236: char path[PATH_MAX]; 237: builder_part_t build_part; 238: key_type_t type = KEY_ANY; 239: 240: if (streq(filename, "%dns")) 241: { 242: return NULL; 243: } 244: if (strncaseeq(filename, "dns:", 4)) 245: { /* RFC 3110 format */ 246: build_part = BUILD_BLOB_DNSKEY; 247: /* not a complete RR, only RSA supported */ 248: type = KEY_RSA; 249: filename += 4; 250: } 251: else if (strncaseeq(filename, "ssh:", 4)) 252: { /* SSH key */ 253: build_part = BUILD_BLOB_SSHKEY; 254: filename += 4; 255: } 256: else 257: { /* try PKCS#1 by default */ 258: build_part = BUILD_BLOB_ASN1_DER; 259: } 260: if (strncaseeq(filename, "0x", 2) || strncaseeq(filename, "0s", 2)) 261: { 262: chunk_t printable_key, raw_key; 263: 264: printable_key = chunk_create(filename + 2, strlen(filename) - 2); 265: raw_key = strncaseeq(filename, "0x", 2) ? 266: chunk_from_hex(printable_key, NULL) : 267: chunk_from_base64(printable_key, NULL); 268: key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type, 269: build_part, raw_key, BUILD_END); 270: chunk_free(&raw_key); 271: if (key) 272: { 273: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, 274: CERT_TRUSTED_PUBKEY, 275: BUILD_PUBLIC_KEY, key, 276: BUILD_SUBJECT, identity, 277: BUILD_END); 278: type = key->get_type(key); 279: key->destroy(key); 280: if (cert) 281: { 282: cert = this->creds->add_cert_ref(this->creds, TRUE, cert); 283: DBG1(DBG_CFG, " loaded %N public key for \"%Y\"", 284: key_type_names, type, identity); 285: return cert; 286: } 287: } 288: DBG1(DBG_CFG, " loading public key for \"%Y\" failed", identity); 289: } 290: else 291: { 292: if (*filename == '/') 293: { 294: snprintf(path, sizeof(path), "%s", filename); 295: } 296: else 297: { 298: snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename); 299: } 300: 301: cert = lib->creds->create(lib->creds, 302: CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, 303: BUILD_FROM_FILE, path, 304: BUILD_SUBJECT, identity, 305: BUILD_END); 306: if (cert) 307: { 308: cert = this->creds->add_cert_ref(this->creds, TRUE, cert); 309: key = cert->get_public_key(cert); 310: type = key->get_type(key); 311: key->destroy(key); 312: DBG1(DBG_CFG, " loaded %N public key for \"%Y\" from '%s'", 313: key_type_names, type, identity, filename); 314: return cert; 315: } 316: DBG1(DBG_CFG, " loading public key for \"%Y\" from '%s' failed", 317: identity, filename); 318: } 319: return NULL; 320: } 321: 322: /** 323: * Load a CA certificate, optionally force it to be one 324: */ 325: static certificate_t *load_ca_cert(char *filename, bool force_ca_cert) 326: { 327: certificate_t *cert = NULL; 328: char path[PATH_MAX]; 329: 330: if (strpfx(filename, "%smartcard")) 331: { 332: smartcard_format_t format; 333: char module[SC_PART_LEN], keyid[SC_PART_LEN]; 334: u_int slot; 335: 336: format = parse_smartcard(filename, &slot, module, keyid); 337: if (format != SC_FORMAT_INVALID) 338: { 339: cert = (certificate_t*)load_from_smartcard(format, 340: slot, module, keyid, CRED_CERTIFICATE, CERT_X509); 341: } 342: } 343: else 344: { 345: if (*filename == '/') 346: { 347: snprintf(path, sizeof(path), "%s", filename); 348: } 349: else 350: { 351: snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename); 352: } 353: 354: if (force_ca_cert) 355: { /* we treat this certificate as a CA certificate even if it has no 356: * CA basic constraint */ 357: cert = lib->creds->create(lib->creds, 358: CRED_CERTIFICATE, CERT_X509, 359: BUILD_FROM_FILE, path, BUILD_X509_FLAG, X509_CA, 360: BUILD_END); 361: } 362: else 363: { 364: cert = lib->creds->create(lib->creds, 365: CRED_CERTIFICATE, CERT_X509, 366: BUILD_FROM_FILE, path, 367: BUILD_END); 368: } 369: } 370: if (cert) 371: { 372: x509_t *x509 = (x509_t*)cert; 373: 374: if (!(x509->get_flags(x509) & X509_CA)) 375: { 376: DBG1(DBG_CFG, " ca certificate \"%Y\" lacks ca basic constraint, " 377: "discarded", cert->get_subject(cert)); 378: cert->destroy(cert); 379: return NULL; 380: } 381: DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", 382: cert->get_subject(cert), filename); 383: return cert; 384: } 385: return NULL; 386: } 387: 388: /** 389: * Used by stroke_ca.c 390: */ 391: certificate_t *stroke_load_ca_cert(char *filename) 392: { 393: bool force_ca_cert; 394: 395: force_ca_cert = lib->settings->get_bool(lib->settings, 396: "%s.plugins.stroke.ignore_missing_ca_basic_constraint", 397: FALSE, lib->ns); 398: return load_ca_cert(filename, force_ca_cert); 399: } 400: 401: /** 402: * Load a CA certificate from disk 403: */ 404: static void load_x509_ca(private_stroke_cred_t *this, char *file, 405: mem_cred_t *creds) 406: { 407: certificate_t *cert; 408: 409: cert = load_ca_cert(file, this->force_ca_cert); 410: if (cert) 411: { 412: cert = this->ca->get_cert_ref(this->ca, cert); 413: creds->add_cert(creds, TRUE, cert); 414: } 415: else 416: { 417: DBG1(DBG_CFG, " loading ca certificate from '%s' failed", file); 418: } 419: } 420: 421: /** 422: * Load AA certificate with flags from disk 423: */ 424: static void load_x509_aa(private_stroke_cred_t *this,char *file, 425: mem_cred_t *creds) 426: { 427: certificate_t *cert; 428: 429: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, 430: BUILD_FROM_FILE, file, 431: BUILD_X509_FLAG, X509_AA, BUILD_END); 432: if (cert) 433: { 434: DBG1(DBG_CFG, " loaded AA certificate \"%Y\" from '%s'", 435: cert->get_subject(cert), file); 436: creds->add_cert(creds, TRUE, cert); 437: } 438: else 439: { 440: DBG1(DBG_CFG, " loading AA certificate from '%s' failed", file); 441: } 442: } 443: 444: /** 445: * Load a certificate with flags from disk 446: */ 447: static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag, 448: mem_cred_t *creds) 449: { 450: certificate_t *cert; 451: 452: /* for all other flags, we add them to the certificate. */ 453: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, 454: BUILD_FROM_FILE, file, 455: BUILD_X509_FLAG, flag, BUILD_END); 456: if (cert) 457: { 458: DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", 459: cert->get_subject(cert), file); 460: creds->add_cert(creds, TRUE, cert); 461: } 462: else 463: { 464: DBG1(DBG_CFG, " loading certificate from '%s' failed", file); 465: } 466: } 467: 468: /** 469: * Load a CRL from a file 470: */ 471: static void load_x509_crl(private_stroke_cred_t *this, char *file, 472: mem_cred_t *creds) 473: { 474: certificate_t *cert; 475: 476: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, 477: BUILD_FROM_FILE, file, BUILD_END); 478: if (cert) 479: { 480: DBG1(DBG_CFG, " loaded crl from '%s'", file); 481: creds->add_crl(creds, (crl_t*)cert); 482: } 483: else 484: { 485: DBG1(DBG_CFG, " loading crl from '%s' failed", file); 486: } 487: } 488: 489: /** 490: * Load an attribute certificate from a file 491: */ 492: static void load_x509_ac(private_stroke_cred_t *this, char *file, 493: mem_cred_t *creds) 494: { 495: certificate_t *cert; 496: 497: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, 498: BUILD_FROM_FILE, file, BUILD_END); 499: if (cert) 500: { 501: DBG1(DBG_CFG, " loaded attribute certificate from '%s'", file); 502: creds->add_cert(creds, FALSE, cert); 503: } 504: else 505: { 506: DBG1(DBG_CFG, " loading attribute certificate from '%s' failed", file); 507: } 508: } 509: 510: /** 511: * load trusted certificates from a directory 512: */ 513: static void load_certdir(private_stroke_cred_t *this, char *path, 514: certificate_type_t type, x509_flag_t flag, 515: mem_cred_t *creds) 516: { 517: enumerator_t *enumerator; 518: struct stat st; 519: char *file; 520: 521: enumerator = enumerator_create_directory(path); 522: if (enumerator) 523: { 524: while (enumerator->enumerate(enumerator, NULL, &file, &st)) 525: { 526: if (!S_ISREG(st.st_mode)) 527: { 528: /* skip special file */ 529: continue; 530: } 531: switch (type) 532: { 533: case CERT_X509: 534: if (flag & X509_CA) 535: { 536: load_x509_ca(this, file, creds); 537: } 538: else if (flag & X509_AA) 539: { 540: load_x509_aa(this, file, creds); 541: } 542: else 543: { 544: load_x509(this, file, flag, creds); 545: } 546: break; 547: case CERT_X509_CRL: 548: load_x509_crl(this, file, creds); 549: break; 550: case CERT_X509_AC: 551: load_x509_ac(this, file, creds); 552: break; 553: default: 554: break; 555: } 556: } 557: enumerator->destroy(enumerator); 558: } 559: else 560: { 561: DBG1(DBG_CFG, " reading directory failed"); 562: } 563: } 564: 565: METHOD(credential_set_t, cache_cert, void, 566: private_stroke_cred_t *this, certificate_t *cert) 567: { 568: if (cert->get_type(cert) == CERT_X509_CRL && this->cachecrl) 569: { 570: /* CRLs get written to /etc/ipsec.d/crls/<authkeyId>.crl */ 571: crl_t *crl = (crl_t*)cert; 572: 573: cert->get_ref(cert); 574: if (this->creds->add_crl(this->creds, crl)) 575: { 576: char buf[BUF_LEN]; 577: chunk_t chunk, hex; 578: bool is_delta_crl; 579: 580: is_delta_crl = crl->is_delta_crl(crl, NULL); 581: 582: chunk = crl->get_authKeyIdentifier(crl); 583: hex = chunk_to_hex(chunk, NULL, FALSE); 584: snprintf(buf, sizeof(buf), "%s/%s%s.crl", CRL_DIR, hex.ptr, 585: is_delta_crl ? "_delta" : ""); 586: free(hex.ptr); 587: 588: if (cert->get_encoding(cert, CERT_ASN1_DER, &chunk)) 589: { 590: if (chunk_write(chunk, buf, 022, TRUE)) 591: { 592: DBG1(DBG_CFG, " written crl file '%s' (%d bytes)", 593: buf, chunk.len); 594: } 595: else 596: { 597: DBG1(DBG_CFG, " writing crl file '%s' failed: %s", 598: buf, strerror(errno)); 599: } 600: free(chunk.ptr); 601: } 602: } 603: } 604: } 605: 606: METHOD(stroke_cred_t, cachecrl, void, 607: private_stroke_cred_t *this, bool enabled) 608: { 609: DBG1(DBG_CFG, "crl caching to %s %s", 610: CRL_DIR, enabled ? "enabled" : "disabled"); 611: this->cachecrl = enabled; 612: } 613: 614: 615: /** 616: * Convert a string of characters into a binary secret 617: * A string between single or double quotes is treated as ASCII characters 618: * A string prepended by 0x is treated as HEX and prepended by 0s as Base64 619: */ 620: static err_t extract_secret(chunk_t *secret, chunk_t *line) 621: { 622: chunk_t raw_secret; 623: char delimiter = ' '; 624: bool quotes = FALSE; 625: 626: if (!eat_whitespace(line)) 627: { 628: return "missing secret"; 629: } 630: 631: if (*line->ptr == '\'' || *line->ptr == '"') 632: { 633: quotes = TRUE; 634: delimiter = *line->ptr; 635: line->ptr++; line->len--; 636: } 637: 638: if (!extract_token(&raw_secret, delimiter, line)) 639: { 640: if (delimiter == ' ') 641: { 642: raw_secret = *line; 643: } 644: else 645: { 646: return "missing second delimiter"; 647: } 648: } 649: 650: if (quotes) 651: { 652: /* treat as an ASCII string */ 653: *secret = chunk_clone(raw_secret); 654: return NULL; 655: } 656: /* treat 0x as hex, 0s as base64 */ 657: if (raw_secret.len > 2) 658: { 659: if (strncasecmp("0x", raw_secret.ptr, 2) == 0) 660: { 661: *secret = chunk_from_hex(chunk_skip(raw_secret, 2), NULL); 662: return NULL; 663: } 664: if (strncasecmp("0s", raw_secret.ptr, 2) == 0) 665: { 666: *secret = chunk_from_base64(chunk_skip(raw_secret, 2), NULL); 667: return NULL; 668: } 669: } 670: *secret = chunk_clone(raw_secret); 671: return NULL; 672: } 673: 674: /** 675: * Data for passphrase callback 676: */ 677: typedef struct { 678: /** cached passphrases */ 679: mem_cred_t *cache; 680: /** socket we use for prompting */ 681: FILE *prompt; 682: /** type of secret to unlock */ 683: int type; 684: /** private key file */ 685: char *path; 686: /** number of tries */ 687: int try; 688: } passphrase_cb_data_t; 689: 690: /** 691: * Callback function to receive passphrases 692: */ 693: static shared_key_t* passphrase_cb(passphrase_cb_data_t *data, 694: shared_key_type_t type, identification_t *me, 695: identification_t *other, id_match_t *match_me, 696: id_match_t *match_other) 697: { 698: static const int max_tries = 3; 699: shared_key_t *shared; 700: chunk_t secret; 701: char buf[256]; 702: 703: if (type != SHARED_ANY && type != SHARED_PRIVATE_KEY_PASS) 704: { 705: return NULL; 706: } 707: 708: data->try++; 709: if (data->try > max_tries + 1) 710: { /* another builder might call this after we gave up, fail silently */ 711: return NULL; 712: } 713: if (data->try > max_tries) 714: { 715: fprintf(data->prompt, "Passphrase invalid, giving up.\n"); 716: return NULL; 717: } 718: if (data->try > 1) 719: { 720: fprintf(data->prompt, "Passphrase invalid!\n"); 721: } 722: fprintf(data->prompt, "%s '%s' is encrypted.\n", 723: data->type == CRED_PRIVATE_KEY ? "Private key" : "PKCS#12 file", 724: data->path); 725: fprintf(data->prompt, "Passphrase:\n"); 726: if (fgets(buf, sizeof(buf), data->prompt)) 727: { 728: secret = chunk_create(buf, strlen(buf)); 729: if (secret.len > 1) 730: { /* trim appended \n */ 731: secret.len--; 732: if (match_me) 733: { 734: *match_me = ID_MATCH_PERFECT; 735: } 736: if (match_other) 737: { 738: *match_other = ID_MATCH_NONE; 739: } 740: shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, 741: chunk_clone(secret)); 742: data->cache->add_shared(data->cache, shared->get_ref(shared), NULL); 743: return shared; 744: } 745: } 746: return NULL; 747: } 748: 749: /** 750: * Data for PIN callback 751: */ 752: typedef struct { 753: /** socket we use for prompting */ 754: FILE *prompt; 755: /** card label */ 756: char *card; 757: /** card keyid */ 758: chunk_t keyid; 759: /** number of tries */ 760: int try; 761: /** provided PIN */ 762: shared_key_t *shared; 763: } pin_cb_data_t; 764: 765: /** 766: * Callback function to receive PINs 767: */ 768: static shared_key_t* pin_cb(pin_cb_data_t *data, shared_key_type_t type, 769: identification_t *me, identification_t *other, 770: id_match_t *match_me, id_match_t *match_other) 771: { 772: chunk_t secret; 773: char buf[256]; 774: 775: if (type != SHARED_ANY && type != SHARED_PIN) 776: { 777: return NULL; 778: } 779: 780: if (!me || !chunk_equals(me->get_encoding(me), data->keyid)) 781: { 782: return NULL; 783: } 784: 785: data->try++; 786: if (data->try > 1) 787: { 788: fprintf(data->prompt, "PIN invalid, aborting.\n"); 789: return NULL; 790: } 791: fprintf(data->prompt, "Login to '%s' required\n", data->card); 792: fprintf(data->prompt, "PIN:\n"); 793: if (fgets(buf, sizeof(buf), data->prompt)) 794: { 795: secret = chunk_create(buf, strlen(buf)); 796: if (secret.len > 1) 797: { /* trim appended \n */ 798: secret.len--; 799: if (match_me) 800: { 801: *match_me = ID_MATCH_PERFECT; 802: } 803: if (match_other) 804: { 805: *match_other = ID_MATCH_NONE; 806: } 807: DESTROY_IF(data->shared); 808: data->shared = shared_key_create(SHARED_PIN, chunk_clone(secret)); 809: return data->shared->get_ref(data->shared); 810: } 811: } 812: return NULL; 813: } 814: 815: /** 816: * Load a smartcard with a PIN 817: */ 818: static bool load_pin(mem_cred_t *secrets, chunk_t line, int line_nr, 819: FILE *prompt) 820: { 821: chunk_t sc = chunk_empty, secret = chunk_empty; 822: char smartcard[BUF_LEN], keyid[SC_PART_LEN], module[SC_PART_LEN]; 823: private_key_t *key = NULL; 824: u_int slot; 825: chunk_t chunk; 826: shared_key_t *shared = NULL; 827: identification_t *id; 828: mem_cred_t *mem = NULL; 829: callback_cred_t *cb = NULL; 830: pin_cb_data_t pin_data; 831: smartcard_format_t format; 832: 833: err_t ugh = extract_value(&sc, &line); 834: 835: if (ugh != NULL) 836: { 837: DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); 838: return FALSE; 839: } 840: if (sc.len == 0) 841: { 842: DBG1(DBG_CFG, "line %d: expected %%smartcard specifier", line_nr); 843: return FALSE; 844: } 845: snprintf(smartcard, sizeof(smartcard), "%.*s", (int)sc.len, sc.ptr); 846: smartcard[sizeof(smartcard) - 1] = '\0'; 847: 848: format = parse_smartcard(smartcard, &slot, module, keyid); 849: if (format == SC_FORMAT_INVALID) 850: { 851: DBG1(DBG_CFG, "line %d: the given %%smartcard specifier is not" 852: " supported or invalid", line_nr); 853: return FALSE; 854: } 855: 856: if (!eat_whitespace(&line)) 857: { 858: DBG1(DBG_CFG, "line %d: expected PIN", line_nr); 859: return FALSE; 860: } 861: ugh = extract_secret(&secret, &line); 862: if (ugh != NULL) 863: { 864: DBG1(DBG_CFG, "line %d: malformed PIN: %s", line_nr, ugh); 865: return FALSE; 866: } 867: 868: chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); 869: if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) 870: { 871: free(secret.ptr); 872: if (!prompt) 873: { /* no IO channel to prompt, skip */ 874: chunk_clear(&chunk); 875: return TRUE; 876: } 877: /* use callback credential set to prompt for the pin */ 878: pin_data = (pin_cb_data_t){ 879: .prompt = prompt, 880: .card = smartcard, 881: .keyid = chunk, 882: }; 883: cb = callback_cred_create_shared((void*)pin_cb, &pin_data); 884: lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE); 885: } 886: else 887: { 888: /* provide our pin in a temporary credential set */ 889: shared = shared_key_create(SHARED_PIN, secret); 890: id = identification_create_from_encoding(ID_KEY_ID, chunk); 891: mem = mem_cred_create(); 892: mem->add_shared(mem, shared->get_ref(shared), id, NULL); 893: lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE); 894: } 895: 896: /* unlock: smartcard needs the pin and potentially calls public set */ 897: key = (private_key_t*)load_from_smartcard(format, slot, module, keyid, 898: CRED_PRIVATE_KEY, KEY_ANY); 899: 900: if (key) 901: { 902: DBG1(DBG_CFG, " loaded private key from %.*s", (int)sc.len, sc.ptr); 903: secrets->add_key(secrets, key); 904: } 905: if (mem) 906: { 907: if (!key) 908: { 909: shared->destroy(shared); 910: shared = NULL; 911: } 912: lib->credmgr->remove_local_set(lib->credmgr, &mem->set); 913: mem->destroy(mem); 914: } 915: if (cb) 916: { 917: if (key) 918: { 919: shared = pin_data.shared; 920: } 921: else 922: { 923: DESTROY_IF(pin_data.shared); 924: } 925: lib->credmgr->remove_local_set(lib->credmgr, &cb->set); 926: cb->destroy(cb); 927: } 928: if (shared) 929: { 930: id = identification_create_from_encoding(ID_KEY_ID, chunk); 931: secrets->add_shared(secrets, shared, id, NULL); 932: } 933: chunk_clear(&chunk); 934: return TRUE; 935: } 936: 937: /** 938: * Load a private key or PKCS#12 container from a file 939: */ 940: static bool load_from_file(chunk_t line, int line_nr, FILE *prompt, 941: char *path, int type, int subtype, 942: void **result) 943: { 944: chunk_t filename; 945: chunk_t secret = chunk_empty; 946: 947: err_t ugh = extract_value(&filename, &line); 948: 949: if (ugh != NULL) 950: { 951: DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); 952: return FALSE; 953: } 954: if (filename.len == 0) 955: { 956: DBG1(DBG_CFG, "line %d: empty filename", line_nr); 957: return FALSE; 958: } 959: if (*filename.ptr == '/') 960: { 961: /* absolute path name */ 962: snprintf(path, PATH_MAX, "%.*s", (int)filename.len, filename.ptr); 963: } 964: else 965: { 966: /* relative path name */ 967: snprintf(path, PATH_MAX, "%s/%.*s", PRIVATE_KEY_DIR, 968: (int)filename.len, filename.ptr); 969: } 970: 971: /* check for optional passphrase */ 972: if (eat_whitespace(&line)) 973: { 974: ugh = extract_secret(&secret, &line); 975: if (ugh != NULL) 976: { 977: DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); 978: return FALSE; 979: } 980: } 981: if (secret.len == 7 && strpfx(secret.ptr, "%prompt")) 982: { 983: callback_cred_t *cb; 984: passphrase_cb_data_t pp_data = { 985: .prompt = prompt, 986: .type = type, 987: .path = path, 988: .try = 0, 989: }; 990: 991: free(secret.ptr); 992: if (!prompt) 993: { 994: *result = NULL; 995: return TRUE; 996: } 997: /* add cache first so if valid passphrases are needed multiple times 998: * the callback is not called anymore */ 999: pp_data.cache = mem_cred_create(); 1000: lib->credmgr->add_local_set(lib->credmgr, &pp_data.cache->set, FALSE); 1001: /* use callback credential set to prompt for the passphrase */ 1002: cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data); 1003: lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE); 1004: 1005: *result = lib->creds->create(lib->creds, type, subtype, 1006: BUILD_FROM_FILE, path, BUILD_END); 1007: 1008: lib->credmgr->remove_local_set(lib->credmgr, &cb->set); 1009: cb->destroy(cb); 1010: lib->credmgr->remove_local_set(lib->credmgr, &pp_data.cache->set); 1011: pp_data.cache->destroy(pp_data.cache); 1012: } 1013: else 1014: { 1015: mem_cred_t *mem = NULL; 1016: shared_key_t *shared; 1017: 1018: /* provide our pin in a temporary credential set */ 1019: shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret); 1020: mem = mem_cred_create(); 1021: mem->add_shared(mem, shared, NULL); 1022: if (eat_whitespace(&line)) 1023: { /* if there is a second passphrase add that too, could be needed for 1024: * PKCS#12 files using different passwords for MAC and encryption */ 1025: ugh = extract_secret(&secret, &line); 1026: if (ugh != NULL) 1027: { 1028: DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh); 1029: mem->destroy(mem); 1030: return FALSE; 1031: } 1032: shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret); 1033: mem->add_shared(mem, shared, NULL); 1034: } 1035: lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE); 1036: 1037: *result = lib->creds->create(lib->creds, type, subtype, 1038: BUILD_FROM_FILE, path, BUILD_END); 1039: 1040: lib->credmgr->remove_local_set(lib->credmgr, &mem->set); 1041: mem->destroy(mem); 1042: } 1043: return TRUE; 1044: } 1045: 1046: /** 1047: * Load a private key 1048: */ 1049: static bool load_private(mem_cred_t *secrets, chunk_t line, int line_nr, 1050: FILE *prompt, key_type_t key_type) 1051: { 1052: char path[PATH_MAX]; 1053: private_key_t *key; 1054: 1055: if (!load_from_file(line, line_nr, prompt, path, CRED_PRIVATE_KEY, 1056: key_type, (void**)&key)) 1057: { 1058: return FALSE; 1059: } 1060: if (key) 1061: { 1062: DBG1(DBG_CFG, " loaded %N private key from '%s'", 1063: key_type_names, key->get_type(key), path); 1064: secrets->add_key(secrets, key); 1065: } 1066: else 1067: { 1068: DBG1(DBG_CFG, " loading private key from '%s' failed", path); 1069: } 1070: return TRUE; 1071: } 1072: 1073: /** 1074: * Load a PKCS#12 container 1075: */ 1076: static bool load_pkcs12(private_stroke_cred_t *this, mem_cred_t *secrets, 1077: chunk_t line, int line_nr, FILE *prompt) 1078: { 1079: enumerator_t *enumerator; 1080: char path[PATH_MAX]; 1081: certificate_t *cert; 1082: private_key_t *key; 1083: pkcs12_t *pkcs12; 1084: 1085: if (!load_from_file(line, line_nr, prompt, path, CRED_CONTAINER, 1086: CONTAINER_PKCS12, (void**)&pkcs12)) 1087: { 1088: return FALSE; 1089: } 1090: if (!pkcs12) 1091: { 1092: DBG1(DBG_CFG, " loading credentials from '%s' failed", path); 1093: return TRUE; 1094: } 1095: enumerator = pkcs12->create_cert_enumerator(pkcs12); 1096: while (enumerator->enumerate(enumerator, &cert)) 1097: { 1098: x509_t *x509 = (x509_t*)cert; 1099: 1100: if (x509->get_flags(x509) & X509_CA) 1101: { 1102: DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'", 1103: cert->get_subject(cert), path); 1104: } 1105: else 1106: { 1107: DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'", 1108: cert->get_subject(cert), path); 1109: } 1110: this->creds->add_cert(this->creds, TRUE, cert->get_ref(cert)); 1111: } 1112: enumerator->destroy(enumerator); 1113: enumerator = pkcs12->create_key_enumerator(pkcs12); 1114: while (enumerator->enumerate(enumerator, &key)) 1115: { 1116: DBG1(DBG_CFG, " loaded %N private key from '%s'", 1117: key_type_names, key->get_type(key), path); 1118: secrets->add_key(secrets, key->get_ref(key)); 1119: } 1120: enumerator->destroy(enumerator); 1121: pkcs12->container.destroy(&pkcs12->container); 1122: return TRUE; 1123: } 1124: 1125: /** 1126: * Load a shared key 1127: */ 1128: static bool load_shared(mem_cred_t *secrets, chunk_t line, int line_nr, 1129: shared_key_type_t type, chunk_t ids) 1130: { 1131: shared_key_t *shared_key; 1132: linked_list_t *owners; 1133: chunk_t secret = chunk_empty; 1134: 1135: err_t ugh = extract_secret(&secret, &line); 1136: if (ugh != NULL) 1137: { 1138: DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh); 1139: return FALSE; 1140: } 1141: shared_key = shared_key_create(type, secret); 1142: DBG1(DBG_CFG, " loaded %N secret for %s", shared_key_type_names, type, 1143: ids.len > 0 ? (char*)ids.ptr : "%any"); 1144: DBG4(DBG_CFG, " secret: %#B", &secret); 1145: 1146: owners = linked_list_create(); 1147: while (ids.len > 0) 1148: { 1149: chunk_t id; 1150: 1151: ugh = extract_value(&id, &ids); 1152: if (ugh != NULL) 1153: { 1154: DBG1(DBG_CFG, "line %d: %s", line_nr, ugh); 1155: shared_key->destroy(shared_key); 1156: owners->destroy_offset(owners, offsetof(identification_t, destroy)); 1157: return FALSE; 1158: } 1159: if (id.len == 0) 1160: { 1161: continue; 1162: } 1163: 1164: /* NULL terminate the ID string */ 1165: *(id.ptr + id.len) = '\0'; 1166: owners->insert_last(owners, identification_create_from_string(id.ptr)); 1167: } 1168: if (!owners->get_count(owners)) 1169: { 1170: owners->insert_last(owners, 1171: identification_create_from_encoding(ID_ANY, chunk_empty)); 1172: } 1173: secrets->add_shared_list(secrets, shared_key, owners); 1174: return TRUE; 1175: } 1176: 1177: /** 1178: * reload ipsec.secrets 1179: */ 1180: static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets, 1181: char *file, int level, FILE *prompt) 1182: { 1183: int line_nr = 0; 1184: chunk_t *src, line; 1185: 1186: DBG1(DBG_CFG, "loading secrets from '%s'", file); 1187: src = chunk_map(file, FALSE); 1188: if (!src) 1189: { 1190: DBG1(DBG_CFG, "opening secrets file '%s' failed: %s", file, 1191: strerror(errno)); 1192: return; 1193: } 1194: 1195: if (!secrets) 1196: { 1197: secrets = mem_cred_create(); 1198: } 1199: 1200: while (fetchline(src, &line)) 1201: { 1202: chunk_t ids, token; 1203: key_type_t key_type; 1204: shared_key_type_t type; 1205: 1206: line_nr++; 1207: 1208: if (!eat_whitespace(&line)) 1209: { 1210: continue; 1211: } 1212: if (line.len > strlen("include ") && strpfx(line.ptr, "include ")) 1213: { 1214: char **expanded, *dir, pattern[PATH_MAX]; 1215: u_char *pos; 1216: 1217: if (level > MAX_SECRETS_RECURSION) 1218: { 1219: DBG1(DBG_CFG, "maximum level of %d includes reached, ignored", 1220: MAX_SECRETS_RECURSION); 1221: continue; 1222: } 1223: /* terminate filename by space */ 1224: line = chunk_skip(line, strlen("include ")); 1225: pos = memchr(line.ptr, ' ', line.len); 1226: if (pos) 1227: { 1228: line.len = pos - line.ptr; 1229: } 1230: if (line.len && line.ptr[0] == '/') 1231: { 1232: if (line.len + 1 > sizeof(pattern)) 1233: { 1234: DBG1(DBG_CFG, "include pattern too long, ignored"); 1235: continue; 1236: } 1237: snprintf(pattern, sizeof(pattern), "%.*s", 1238: (int)line.len, line.ptr); 1239: } 1240: else 1241: { /* use directory of current file if relative */ 1242: dir = path_dirname(file); 1243: 1244: if (line.len + 1 + strlen(dir) + 1 > sizeof(pattern)) 1245: { 1246: DBG1(DBG_CFG, "include pattern too long, ignored"); 1247: free(dir); 1248: continue; 1249: } 1250: snprintf(pattern, sizeof(pattern), "%s/%.*s", 1251: dir, (int)line.len, line.ptr); 1252: free(dir); 1253: } 1254: #ifdef HAVE_GLOB_H 1255: { 1256: glob_t buf; 1257: if (glob(pattern, GLOB_ERR, NULL, &buf) != 0) 1258: { 1259: DBG1(DBG_CFG, "expanding file expression '%s' failed", 1260: pattern); 1261: } 1262: else 1263: { 1264: for (expanded = buf.gl_pathv; *expanded != NULL; expanded++) 1265: { 1266: load_secrets(this, secrets, *expanded, level + 1, 1267: prompt); 1268: } 1269: } 1270: globfree(&buf); 1271: } 1272: #else /* HAVE_GLOB_H */ 1273: /* if glob(3) is not available, try to load pattern directly */ 1274: load_secrets(this, secrets, pattern, level + 1, prompt); 1275: #endif /* HAVE_GLOB_H */ 1276: continue; 1277: } 1278: 1279: if (line.len > 2 && strpfx(line.ptr, ": ")) 1280: { 1281: /* no ids, skip the ':' */ 1282: ids = chunk_empty; 1283: line.ptr++; 1284: line.len--; 1285: } 1286: else if (extract_token_str(&ids, " : ", &line)) 1287: { 1288: /* NULL terminate the extracted id string */ 1289: *(ids.ptr + ids.len) = '\0'; 1290: } 1291: else 1292: { 1293: DBG1(DBG_CFG, "line %d: missing ' : ' separator", line_nr); 1294: break; 1295: } 1296: 1297: if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) 1298: { 1299: DBG1(DBG_CFG, "line %d: missing token", line_nr); 1300: break; 1301: } 1302: if (match("RSA", &token) || match("ECDSA", &token) || 1303: match("BLISS", &token) || match("PKCS8", &token)) 1304: { 1305: if (match("RSA", &token)) 1306: { 1307: key_type = KEY_RSA; 1308: } 1309: else if (match("ECDSA", &token)) 1310: { 1311: key_type = KEY_ECDSA; 1312: } 1313: else if (match("BLISS", &token)) 1314: { 1315: key_type = KEY_BLISS; 1316: } 1317: else 1318: { 1319: key_type = KEY_ANY; 1320: } 1321: if (!load_private(secrets, line, line_nr, prompt, key_type)) 1322: { 1323: break; 1324: } 1325: } 1326: else if (match("P12", &token)) 1327: { 1328: if (!load_pkcs12(this, secrets, line, line_nr, prompt)) 1329: { 1330: break; 1331: } 1332: } 1333: else if (match("PIN", &token)) 1334: { 1335: if (!load_pin(secrets, line, line_nr, prompt)) 1336: { 1337: break; 1338: } 1339: } 1340: else if ((match("PSK", &token) && (type = SHARED_IKE)) || 1341: (match("EAP", &token) && (type = SHARED_EAP)) || 1342: (match("NTLM", &token) && (type = SHARED_NT_HASH)) || 1343: (match("XAUTH", &token) && (type = SHARED_EAP))) 1344: { 1345: if (!load_shared(secrets, line, line_nr, type, ids)) 1346: { 1347: break; 1348: } 1349: } 1350: else 1351: { 1352: DBG1(DBG_CFG, "line %d: token must be either RSA, ECDSA, BLISS, " 1353: "PKCS8 P12, PIN, PSK, EAP, XAUTH or NTLM", line_nr); 1354: break; 1355: } 1356: } 1357: chunk_unmap(src); 1358: 1359: if (level == 0) 1360: { /* replace secrets in active credential set */ 1361: this->creds->replace_secrets(this->creds, secrets, FALSE); 1362: secrets->destroy(secrets); 1363: } 1364: } 1365: 1366: /** 1367: * load all certificates from ipsec.d 1368: */ 1369: static void load_certs(private_stroke_cred_t *this) 1370: { 1371: mem_cred_t *creds; 1372: 1373: DBG1(DBG_CFG, "loading ca certificates from '%s'", 1374: CA_CERTIFICATE_DIR); 1375: creds = mem_cred_create(); 1376: load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA, creds); 1377: this->ca->replace_certs(this->ca, creds); 1378: creds->destroy(creds); 1379: 1380: DBG1(DBG_CFG, "loading aa certificates from '%s'", 1381: AA_CERTIFICATE_DIR); 1382: load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA, this->aacerts); 1383: 1384: DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'", 1385: OCSP_CERTIFICATE_DIR); 1386: load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER, 1387: this->creds); 1388: 1389: DBG1(DBG_CFG, "loading attribute certificates from '%s'", 1390: ATTR_CERTIFICATE_DIR); 1391: load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0, this->creds); 1392: 1393: DBG1(DBG_CFG, "loading crls from '%s'", 1394: CRL_DIR); 1395: load_certdir(this, CRL_DIR, CERT_X509_CRL, 0, this->creds); 1396: } 1397: 1398: METHOD(stroke_cred_t, reread, void, 1399: private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt) 1400: { 1401: mem_cred_t *creds; 1402: 1403: if (msg->reread.flags & REREAD_SECRETS) 1404: { 1405: DBG1(DBG_CFG, "rereading secrets"); 1406: load_secrets(this, NULL, this->secrets_file, 0, prompt); 1407: } 1408: if (msg->reread.flags & REREAD_CACERTS) 1409: { 1410: /* first reload certificates in ca sections, so we can refer to them */ 1411: this->ca->reload_certs(this->ca); 1412: 1413: DBG1(DBG_CFG, "rereading ca certificates from '%s'", 1414: CA_CERTIFICATE_DIR); 1415: creds = mem_cred_create(); 1416: load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA, creds); 1417: this->ca->replace_certs(this->ca, creds); 1418: creds->destroy(creds); 1419: } 1420: if (msg->reread.flags & REREAD_AACERTS) 1421: { 1422: DBG1(DBG_CFG, "rereading aa certificates from '%s'", 1423: AA_CERTIFICATE_DIR); 1424: creds = mem_cred_create(); 1425: load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA, creds); 1426: this->aacerts->replace_certs(this->aacerts, creds, FALSE); 1427: creds->destroy(creds); 1428: lib->credmgr->flush_cache(lib->credmgr, CERT_X509); 1429: } 1430: if (msg->reread.flags & REREAD_OCSPCERTS) 1431: { 1432: DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'", 1433: OCSP_CERTIFICATE_DIR); 1434: load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, 1435: X509_OCSP_SIGNER, this->creds); 1436: } 1437: if (msg->reread.flags & REREAD_ACERTS) 1438: { 1439: DBG1(DBG_CFG, "rereading attribute certificates from '%s'", 1440: ATTR_CERTIFICATE_DIR); 1441: load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0, this->creds); 1442: } 1443: if (msg->reread.flags & REREAD_CRLS) 1444: { 1445: DBG1(DBG_CFG, "rereading crls from '%s'", 1446: CRL_DIR); 1447: load_certdir(this, CRL_DIR, CERT_X509_CRL, 0, this->creds); 1448: } 1449: } 1450: 1451: METHOD(stroke_cred_t, add_shared, void, 1452: private_stroke_cred_t *this, shared_key_t *shared, linked_list_t *owners) 1453: { 1454: this->creds->add_shared_list(this->creds, shared, owners); 1455: } 1456: 1457: METHOD(stroke_cred_t, destroy, void, 1458: private_stroke_cred_t *this) 1459: { 1460: lib->credmgr->remove_set(lib->credmgr, &this->aacerts->set); 1461: lib->credmgr->remove_set(lib->credmgr, &this->creds->set); 1462: this->aacerts->destroy(this->aacerts); 1463: this->creds->destroy(this->creds); 1464: free(this); 1465: } 1466: 1467: /* 1468: * see header file 1469: */ 1470: stroke_cred_t *stroke_cred_create(stroke_ca_t *ca) 1471: { 1472: private_stroke_cred_t *this; 1473: 1474: INIT(this, 1475: .public = { 1476: .set = { 1477: .create_private_enumerator = (void*)return_null, 1478: .create_cert_enumerator = (void*)return_null, 1479: .create_shared_enumerator = (void*)return_null, 1480: .create_cdp_enumerator = (void*)return_null, 1481: .cache_cert = (void*)_cache_cert, 1482: }, 1483: .reread = _reread, 1484: .load_peer = _load_peer, 1485: .load_pubkey = _load_pubkey, 1486: .add_shared = _add_shared, 1487: .cachecrl = _cachecrl, 1488: .destroy = _destroy, 1489: }, 1490: .secrets_file = lib->settings->get_str(lib->settings, 1491: "%s.plugins.stroke.secrets_file", SECRETS_FILE, 1492: lib->ns), 1493: .creds = mem_cred_create(), 1494: .aacerts = mem_cred_create(), 1495: .ca = ca, 1496: ); 1497: 1498: if (lib->settings->get_bool(lib->settings, "%s.cache_crls", FALSE, lib->ns)) 1499: { 1500: cachecrl(this, TRUE); 1501: } 1502: lib->credmgr->add_set(lib->credmgr, &this->creds->set); 1503: lib->credmgr->add_set(lib->credmgr, &this->aacerts->set); 1504: 1505: this->force_ca_cert = lib->settings->get_bool(lib->settings, 1506: "%s.plugins.stroke.ignore_missing_ca_basic_constraint", 1507: FALSE, lib->ns); 1508: 1509: load_certs(this); 1510: load_secrets(this, NULL, this->secrets_file, 0, NULL); 1511: 1512: return &this->public; 1513: }