Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_cred.c, revision 1.1.1.1

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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>