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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2014 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 "stroke_config.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <threading/mutex.h>
                     21: #include <utils/lexparser.h>
                     22: 
                     23: #include <netdb.h>
                     24: 
                     25: typedef struct private_stroke_config_t private_stroke_config_t;
                     26: 
                     27: /**
                     28:  * private data of stroke_config
                     29:  */
                     30: struct private_stroke_config_t {
                     31: 
                     32:        /**
                     33:         * public functions
                     34:         */
                     35:        stroke_config_t public;
                     36: 
                     37:        /**
                     38:         * list of peer_cfg_t
                     39:         */
                     40:        linked_list_t *list;
                     41: 
                     42:        /**
                     43:         * mutex to lock config list
                     44:         */
                     45:        mutex_t *mutex;
                     46: 
                     47:        /**
                     48:         * ca sections
                     49:         */
                     50:        stroke_ca_t *ca;
                     51: 
                     52:        /**
                     53:         * credentials
                     54:         */
                     55:        stroke_cred_t *cred;
                     56: 
                     57:        /**
                     58:         * Virtual IP pool / DNS backend
                     59:         */
                     60:        stroke_attribute_t *attributes;
                     61: };
                     62: 
                     63: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
                     64:        private_stroke_config_t *this, identification_t *me, identification_t *other)
                     65: {
                     66:        this->mutex->lock(this->mutex);
                     67:        return enumerator_create_cleaner(this->list->create_enumerator(this->list),
                     68:                                                                         (void*)this->mutex->unlock, this->mutex);
                     69: }
                     70: 
                     71: CALLBACK(ike_filter, bool,
                     72:        void *data, enumerator_t *orig, va_list args)
                     73: {
                     74:        peer_cfg_t *cfg;
                     75:        ike_cfg_t **out;
                     76: 
                     77:        VA_ARGS_VGET(args, out);
                     78: 
                     79:        if (orig->enumerate(orig, &cfg))
                     80:        {
                     81:                *out = cfg->get_ike_cfg(cfg);
                     82:                return TRUE;
                     83:        }
                     84:        return FALSE;
                     85: }
                     86: 
                     87: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
                     88:        private_stroke_config_t *this, host_t *me, host_t *other)
                     89: {
                     90:        this->mutex->lock(this->mutex);
                     91:        return enumerator_create_filter(this->list->create_enumerator(this->list),
                     92:                                                                        ike_filter, this->mutex,
                     93:                                                                        (void*)this->mutex->unlock);
                     94: }
                     95: 
                     96: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                     97:        private_stroke_config_t *this, char *name)
                     98: {
                     99:        enumerator_t *e1, *e2;
                    100:        peer_cfg_t *current, *found = NULL;
                    101:        child_cfg_t *child;
                    102: 
                    103:        this->mutex->lock(this->mutex);
                    104:        e1 = this->list->create_enumerator(this->list);
                    105:        while (e1->enumerate(e1, &current))
                    106:        {
                    107:                /* compare peer_cfgs name first */
                    108:                if (streq(current->get_name(current), name))
                    109:                {
                    110:                        found = current;
                    111:                        found->get_ref(found);
                    112:                        break;
                    113:                }
                    114:                /* compare all child_cfg names otherwise */
                    115:                e2 = current->create_child_cfg_enumerator(current);
                    116:                while (e2->enumerate(e2, &child))
                    117:                {
                    118:                        if (streq(child->get_name(child), name))
                    119:                        {
                    120:                                found = current;
                    121:                                found->get_ref(found);
                    122:                                break;
                    123:                        }
                    124:                }
                    125:                e2->destroy(e2);
                    126:                if (found)
                    127:                {
                    128:                        break;
                    129:                }
                    130:        }
                    131:        e1->destroy(e1);
                    132:        this->mutex->unlock(this->mutex);
                    133:        return found;
                    134: }
                    135: 
                    136: /**
                    137:  * parse a proposal string, either into ike_cfg or child_cfg
                    138:  */
                    139: static bool add_proposals(private_stroke_config_t *this, char *string,
                    140:                                ike_cfg_t *ike_cfg, child_cfg_t *child_cfg, protocol_id_t proto)
                    141: {
                    142:        if (string)
                    143:        {
                    144:                char *single;
                    145:                char *strict;
                    146:                proposal_t *proposal;
                    147: 
                    148:                strict = string + strlen(string) - 1;
                    149:                if (*strict == '!')
                    150:                {
                    151:                        *strict = '\0';
                    152:                }
                    153:                else
                    154:                {
                    155:                        strict = NULL;
                    156:                }
                    157:                while ((single = strsep(&string, ",")))
                    158:                {
                    159:                        proposal = proposal_create_from_string(proto, single);
                    160:                        if (proposal)
                    161:                        {
                    162:                                if (ike_cfg)
                    163:                                {
                    164:                                        ike_cfg->add_proposal(ike_cfg, proposal);
                    165:                                }
                    166:                                else
                    167:                                {
                    168:                                        child_cfg->add_proposal(child_cfg, proposal);
                    169:                                }
                    170:                                continue;
                    171:                        }
                    172:                        DBG1(DBG_CFG, "skipped invalid proposal string: %s", single);
                    173:                        return FALSE;
                    174:                }
                    175:                if (strict)
                    176:                {
                    177:                        return TRUE;
                    178:                }
                    179:                /* add default proposal to the end if not strict */
                    180:        }
                    181:        if (ike_cfg)
                    182:        {
                    183:                ike_cfg->add_proposal(ike_cfg, proposal_create_default(proto));
                    184:                ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(proto));
                    185:        }
                    186:        else
                    187:        {
                    188:                child_cfg->add_proposal(child_cfg, proposal_create_default(proto));
                    189:                child_cfg->add_proposal(child_cfg, proposal_create_default_aead(proto));
                    190:        }
                    191:        return TRUE;
                    192: }
                    193: 
                    194: /**
                    195:  * Check if any addresses in the given string are local
                    196:  */
                    197: static bool is_local(char *address, bool any_allowed)
                    198: {
                    199:        enumerator_t *enumerator;
                    200:        host_t *host;
                    201:        char *token;
                    202:        bool found = FALSE;
                    203: 
                    204:        enumerator = enumerator_create_token(address, ",", " ");
                    205:        while (enumerator->enumerate(enumerator, &token))
                    206:        {
                    207:                if (!strchr(token, '/'))
                    208:                {
                    209:                        host = host_create_from_dns(token, 0, 0);
                    210:                        if (host)
                    211:                        {
                    212:                                if (charon->kernel->get_interface(charon->kernel, host, NULL))
                    213:                                {
                    214:                                        found = TRUE;
                    215:                                }
                    216:                                else if (any_allowed && host->is_anyaddr(host))
                    217:                                {
                    218:                                        found = TRUE;
                    219:                                }
                    220:                                host->destroy(host);
                    221:                                if (found)
                    222:                                {
                    223:                                        break;
                    224:                                }
                    225:                        }
                    226:                }
                    227:        }
                    228:        enumerator->destroy(enumerator);
                    229:        return found;
                    230: }
                    231: 
                    232: /**
                    233:  * Swap ends if indicated by left|right
                    234:  */
                    235: static void swap_ends(stroke_msg_t *msg)
                    236: {
                    237:        if (!lib->settings->get_bool(lib->settings, "%s.plugins.stroke.allow_swap",
                    238:                                                                 TRUE, lib->ns))
                    239:        {
                    240:                return;
                    241:        }
                    242: 
                    243:        if (is_local(msg->add_conn.other.address, FALSE))
                    244:        {
                    245:                stroke_end_t tmp_end;
                    246: 
                    247:                DBG2(DBG_CFG, "left is other host, swapping ends");
                    248:                tmp_end = msg->add_conn.me;
                    249:                msg->add_conn.me = msg->add_conn.other;
                    250:                msg->add_conn.other = tmp_end;
                    251:        }
                    252:        else if (!is_local(msg->add_conn.me.address, TRUE))
                    253:        {
                    254:                DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
                    255:        }
                    256: }
                    257: 
                    258: /**
                    259:  * Build an IKE config from a stroke message
                    260:  */
                    261: static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
                    262: {
                    263:        ike_cfg_create_t ike;
                    264:        ike_cfg_t *ike_cfg;
                    265:        char me[256], other[256];
                    266: 
                    267:        swap_ends(msg);
                    268: 
                    269:        ike = (ike_cfg_create_t){
                    270:                .version = msg->add_conn.version,
                    271:                .local = msg->add_conn.me.address,
                    272:                .local_port = msg->add_conn.me.ikeport,
                    273:                .remote = msg->add_conn.other.address,
                    274:                .remote_port = msg->add_conn.other.ikeport,
                    275:                .no_certreq = msg->add_conn.other.sendcert == CERT_NEVER_SEND,
                    276:                .force_encap = msg->add_conn.force_encap,
                    277:                .fragmentation = msg->add_conn.fragmentation,
                    278:                .dscp = msg->add_conn.ikedscp,
                    279:        };
                    280:        if (msg->add_conn.me.allow_any)
                    281:        {
                    282:                snprintf(me, sizeof(me), "%s,0.0.0.0/0,::/0",
                    283:                                 msg->add_conn.me.address);
                    284:                ike.local = me;
                    285:        }
                    286:        if (msg->add_conn.other.allow_any)
                    287:        {
                    288:                snprintf(other, sizeof(other), "%s,0.0.0.0/0,::/0",
                    289:                                 msg->add_conn.other.address);
                    290:                ike.remote = other;
                    291:        }
                    292:        if (ike.local_port == IKEV2_UDP_PORT)
                    293:        {
                    294:                ike.local_port = charon->socket->get_port(charon->socket, FALSE);
                    295:        }
                    296:        ike_cfg = ike_cfg_create(&ike);
                    297: 
                    298:        if (!add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg,
                    299:                                           NULL, PROTO_IKE))
                    300:        {
                    301:                ike_cfg->destroy(ike_cfg);
                    302:                return NULL;
                    303:        }
                    304:        return ike_cfg;
                    305: }
                    306: 
                    307: /**
                    308:  * Add CRL constraint to config
                    309:  */
                    310: static void build_crl_policy(auth_cfg_t *cfg, bool local, int policy)
                    311: {
                    312:        /* CRL/OCSP policy, for remote config only */
                    313:        if (!local)
                    314:        {
                    315:                switch (policy)
                    316:                {
                    317:                        case CRL_STRICT_YES:
                    318:                                /* if yes, we require a GOOD validation */
                    319:                                cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
                    320:                                break;
                    321:                        case CRL_STRICT_IFURI:
                    322:                                /* for ifuri, a SKIPPED validation is sufficient */
                    323:                                cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, VALIDATION_SKIPPED);
                    324:                                break;
                    325:                        default:
                    326:                                break;
                    327:                }
                    328:        }
                    329: }
                    330: 
                    331: /**
                    332:  * build authentication config
                    333:  */
                    334: static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
                    335:                                                                  stroke_msg_t *msg, bool local, bool primary)
                    336: {
                    337:        identification_t *identity;
                    338:        certificate_t *certificate;
                    339:        char *auth, *id, *pubkey, *cert, *ca, *groups;
                    340:        stroke_end_t *end, *other_end;
                    341:        auth_cfg_t *cfg;
                    342:        bool loose = FALSE;
                    343: 
                    344:        /* select strings */
                    345:        if (local)
                    346:        {
                    347:                end = &msg->add_conn.me;
                    348:                other_end = &msg->add_conn.other;
                    349:        }
                    350:        else
                    351:        {
                    352:                end = &msg->add_conn.other;
                    353:                other_end = &msg->add_conn.me;
                    354:        }
                    355:        if (primary)
                    356:        {
                    357:                auth = end->auth;
                    358:                id = end->id;
                    359:                if (!id)
                    360:                {       /* leftid/rightid fallback to address */
                    361:                        id = end->address;
                    362:                }
                    363:                cert = end->cert;
                    364:                ca = end->ca;
                    365:                if (ca && streq(ca, "%same"))
                    366:                {
                    367:                        ca = other_end->ca;
                    368:                }
                    369:        }
                    370:        else
                    371:        {
                    372:                auth = end->auth2;
                    373:                id = end->id2;
                    374:                if (local && !id)
                    375:                {       /* leftid2 falls back to leftid */
                    376:                        id = end->id;
                    377:                }
                    378:                cert = end->cert2;
                    379:                ca = end->ca2;
                    380:                if (ca && streq(ca, "%same"))
                    381:                {
                    382:                        ca = other_end->ca2;
                    383:                }
                    384:        }
                    385:        if (id && *id == '%' && !streq(id, "%any") && !streq(id, "%any6"))
                    386:        {       /* has only an effect on rightid/2 */
                    387:                loose = !local;
                    388:                id++;
                    389:        }
                    390: 
                    391:        if (!auth)
                    392:        {
                    393:                if (primary)
                    394:                {
                    395:                        auth = "pubkey";
                    396:                }
                    397:                else
                    398:                {       /* no second authentication round, fine. But load certificates
                    399:                         * for other purposes (EAP-TLS) */
                    400:                        if (cert)
                    401:                        {
                    402:                                certificate = this->cred->load_peer(this->cred, cert);
                    403:                                if (certificate)
                    404:                                {
                    405:                                        certificate->destroy(certificate);
                    406:                                }
                    407:                        }
                    408:                        return NULL;
                    409:                }
                    410:        }
                    411: 
                    412:        cfg = auth_cfg_create();
                    413: 
                    414:        /* add identity and peer certificate */
                    415:        identity = identification_create_from_string(id);
                    416:        if (cert)
                    417:        {
                    418:                enumerator_t *enumerator;
                    419:                bool has_subject = FALSE;
                    420:                certificate_t *first = NULL;
                    421: 
                    422:                enumerator = enumerator_create_token(cert, ",", " ");
                    423:                while (enumerator->enumerate(enumerator, &cert))
                    424:                {
                    425:                        certificate = this->cred->load_peer(this->cred, cert);
                    426:                        if (certificate)
                    427:                        {
                    428:                                cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
                    429:                                if (!first)
                    430:                                {
                    431:                                        first = certificate;
                    432:                                }
                    433:                                if (identity->get_type(identity) != ID_ANY &&
                    434:                                        certificate->has_subject(certificate, identity))
                    435:                                {
                    436:                                        has_subject = TRUE;
                    437:                                }
                    438:                        }
                    439:                }
                    440:                enumerator->destroy(enumerator);
                    441: 
                    442:                if (first && !has_subject)
                    443:                {
                    444:                        DBG1(DBG_CFG, "  id '%Y' not confirmed by certificate, "
                    445:                                 "defaulting to '%Y'", identity, first->get_subject(first));
                    446:                        identity->destroy(identity);
                    447:                        identity = first->get_subject(first);
                    448:                        identity = identity->clone(identity);
                    449:                }
                    450:        }
                    451:        /* add raw RSA public key */
                    452:        pubkey = end->rsakey;
                    453:        if (pubkey && !streq(pubkey, "") && !streq(pubkey, "%cert"))
                    454:        {
                    455:                certificate = this->cred->load_pubkey(this->cred, pubkey, identity);
                    456:                if (certificate)
                    457:                {
                    458:                        cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate);
                    459:                }
                    460:        }
                    461:        if (identity->get_type(identity) != ID_ANY)
                    462:        {
                    463:                cfg->add(cfg, AUTH_RULE_IDENTITY, identity);
                    464:                if (loose)
                    465:                {
                    466:                        cfg->add(cfg, AUTH_RULE_IDENTITY_LOOSE, TRUE);
                    467:                }
                    468:        }
                    469:        else
                    470:        {
                    471:                identity->destroy(identity);
                    472:        }
                    473: 
                    474:        /* CA constraint */
                    475:        if (ca)
                    476:        {
                    477:                identity = identification_create_from_string(ca);
                    478:                certificate = lib->credmgr->get_cert(lib->credmgr, CERT_X509,
                    479:                                                                                         KEY_ANY, identity, TRUE);
                    480:                identity->destroy(identity);
                    481:                if (certificate)
                    482:                {
                    483:                        cfg->add(cfg, AUTH_RULE_CA_CERT, certificate);
                    484:                }
                    485:                else
                    486:                {
                    487:                        DBG1(DBG_CFG, "CA certificate \"%s\" not found, discarding CA "
                    488:                                 "constraint", ca);
                    489:                }
                    490:        }
                    491: 
                    492:        /* groups */
                    493:        groups = primary ? end->groups : end->groups2;
                    494:        if (groups)
                    495:        {
                    496:                enumerator_t *enumerator;
                    497:                char *group;
                    498: 
                    499:                enumerator = enumerator_create_token(groups, ",", " ");
                    500:                while (enumerator->enumerate(enumerator, &group))
                    501:                {
                    502:                        cfg->add(cfg, AUTH_RULE_GROUP,
                    503:                                         identification_create_from_string(group));
                    504:                }
                    505:                enumerator->destroy(enumerator);
                    506:        }
                    507: 
                    508:        /* certificatePolicies */
                    509:        if (end->cert_policy)
                    510:        {
                    511:                enumerator_t *enumerator;
                    512:                char *policy;
                    513: 
                    514:                enumerator = enumerator_create_token(end->cert_policy, ",", " ");
                    515:                while (enumerator->enumerate(enumerator, &policy))
                    516:                {
                    517:                        cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(policy));
                    518:                }
                    519:                enumerator->destroy(enumerator);
                    520:        }
                    521: 
                    522:        /* authentication method (class, actually) */
                    523:        if (strpfx(auth, "ike:") ||
                    524:                strpfx(auth, "pubkey") ||
                    525:                strpfx(auth, "rsa") ||
                    526:                strpfx(auth, "ecdsa") ||
                    527:                strpfx(auth, "bliss"))
                    528:        {
                    529:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
                    530:                build_crl_policy(cfg, local, msg->add_conn.crl_policy);
                    531:                cfg->add_pubkey_constraints(cfg, auth, TRUE);
                    532:        }
                    533:        else if (streq(auth, "psk") || streq(auth, "secret"))
                    534:        {
                    535:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
                    536:        }
                    537:        else if (strpfx(auth, "xauth"))
                    538:        {
                    539:                char *pos;
                    540: 
                    541:                pos = strchr(auth, '-');
                    542:                if (pos)
                    543:                {
                    544:                        cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
                    545:                }
                    546:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
                    547:                if (msg->add_conn.xauth_identity)
                    548:                {
                    549:                        cfg->add(cfg, AUTH_RULE_XAUTH_IDENTITY,
                    550:                                identification_create_from_string(msg->add_conn.xauth_identity));
                    551:                }
                    552:        }
                    553:        else if (strpfx(auth, "eap"))
                    554:        {
                    555:                eap_vendor_type_t *type;
                    556:                char *pos;
                    557: 
                    558:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
                    559:                /* check for public key constraints for EAP-TLS etc. */
                    560:                pos = strchr(auth, ':');
                    561:                if (pos)
                    562:                {
                    563:                        *pos = 0;
                    564:                        cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
                    565:                }
                    566:                type = eap_vendor_type_from_string(auth);
                    567:                if (type)
                    568:                {
                    569:                        cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
                    570:                        if (type->vendor)
                    571:                        {
                    572:                                cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
                    573:                        }
                    574:                        free(type);
                    575:                }
                    576: 
                    577:                if (msg->add_conn.eap_identity)
                    578:                {
                    579:                        if (streq(msg->add_conn.eap_identity, "%identity"))
                    580:                        {
                    581:                                identity = identification_create_from_encoding(ID_ANY,
                    582:                                                                                                                           chunk_empty);
                    583:                        }
                    584:                        else
                    585:                        {
                    586:                                identity = identification_create_from_string(
                    587:                                                                                                        msg->add_conn.eap_identity);
                    588:                        }
                    589:                        cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, identity);
                    590:                }
                    591:                if (msg->add_conn.aaa_identity)
                    592:                {
                    593:                        cfg->add(cfg, AUTH_RULE_AAA_IDENTITY,
                    594:                                identification_create_from_string(msg->add_conn.aaa_identity));
                    595:                }
                    596:        }
                    597:        else
                    598:        {
                    599:                if (!streq(auth, "any"))
                    600:                {
                    601:                        DBG1(DBG_CFG, "authentication method %s unknown, fallback to any",
                    602:                                 auth);
                    603:                }
                    604:                build_crl_policy(cfg, local, msg->add_conn.crl_policy);
                    605:        }
                    606:        return cfg;
                    607: }
                    608: 
                    609: /**
                    610:  * build a mem_pool_t from an address range
                    611:  */
                    612: static mem_pool_t *create_pool_range(char *str)
                    613: {
                    614:        mem_pool_t *pool;
                    615:        host_t *from, *to;
                    616: 
                    617:        if (!host_create_from_range(str, &from, &to))
                    618:        {
                    619:                return NULL;
                    620:        }
                    621:        pool = mem_pool_create_range(str, from, to);
                    622:        from->destroy(from);
                    623:        to->destroy(to);
                    624:        return pool;
                    625: }
                    626: 
                    627: /**
                    628:  * build a peer_cfg from a stroke msg
                    629:  */
                    630: static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
                    631:                                                                  stroke_msg_t *msg, ike_cfg_t *ike_cfg)
                    632: {
                    633:        peer_cfg_t *peer_cfg;
                    634:        auth_cfg_t *auth_cfg;
                    635:        peer_cfg_create_t peer = {
                    636:                .cert_policy = msg->add_conn.me.sendcert,
                    637:                .keyingtries = msg->add_conn.rekey.tries,
                    638:                .no_mobike = !msg->add_conn.mobike,
                    639:                .aggressive = msg->add_conn.aggressive,
                    640:                .push_mode = msg->add_conn.pushmode,
                    641:                .dpd = msg->add_conn.dpd.delay,
                    642:                .dpd_timeout = msg->add_conn.dpd.timeout,
                    643:        };
                    644: 
                    645: #ifdef ME
                    646:        if (msg->add_conn.ikeme.mediation && msg->add_conn.ikeme.mediated_by)
                    647:        {
                    648:                DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
                    649:                         "at the same time, aborting");
                    650:                return NULL;
                    651:        }
                    652: 
                    653:        if (msg->add_conn.ikeme.mediation)
                    654:        {
                    655:                peer.mediation = TRUE;
                    656:                /* force unique connections for mediation connections */
                    657:                msg->add_conn.unique = 1;
                    658:        }
                    659:        else if (msg->add_conn.ikeme.mediated_by)
                    660:        {
                    661:                peer.mediated_by = msg->add_conn.ikeme.mediated_by;
                    662:                if (msg->add_conn.ikeme.peerid)
                    663:                {
                    664:                        peer.peer_id = identification_create_from_string(
                    665:                                                                                                msg->add_conn.ikeme.peerid);
                    666:                }
                    667:                else if (msg->add_conn.other.id)
                    668:                {
                    669:                        peer.peer_id = identification_create_from_string(
                    670:                                                                                                msg->add_conn.other.id);
                    671:                }
                    672:        }
                    673: #endif /* ME */
                    674: 
                    675:        peer.jitter_time = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100;
                    676:        peer.over_time = msg->add_conn.rekey.margin;
                    677:        if (msg->add_conn.rekey.reauth)
                    678:        {
                    679:                peer.reauth_time = msg->add_conn.rekey.ike_lifetime - peer.over_time;
                    680:        }
                    681:        else
                    682:        {
                    683:                peer.rekey_time = msg->add_conn.rekey.ike_lifetime - peer.over_time;
                    684:        }
                    685:        switch (msg->add_conn.unique)
                    686:        {
                    687:                case 1: /* yes */
                    688:                case 2: /* replace */
                    689:                        peer.unique = UNIQUE_REPLACE;
                    690:                        break;
                    691:                case 3: /* keep */
                    692:                        peer.unique = UNIQUE_KEEP;
                    693:                        break;
                    694:                case 4: /* never */
                    695:                        peer.unique = UNIQUE_NEVER;
                    696:                        break;
                    697:                default: /* no */
                    698:                        peer.unique = UNIQUE_NO;
                    699:                        break;
                    700:        }
                    701:        if (msg->add_conn.dpd.action == 0)
                    702:        {       /* dpdaction=none disables DPD */
                    703:                peer.dpd = 0;
                    704:        }
                    705: 
                    706:        /* other.sourceip is managed in stroke_attributes. If it is set, we define
                    707:         * the pool name as the connection name, which the attribute provider
                    708:         * uses to serve pool addresses. */
                    709:        peer_cfg = peer_cfg_create(msg->add_conn.name, ike_cfg, &peer);
                    710: 
                    711:        if (msg->add_conn.other.sourceip)
                    712:        {
                    713:                enumerator_t *enumerator;
                    714:                char *token;
                    715: 
                    716:                enumerator = enumerator_create_token(msg->add_conn.other.sourceip,
                    717:                                                                                         ",", " ");
                    718:                while (enumerator->enumerate(enumerator, &token))
                    719:                {
                    720:                        if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
                    721:                                streq(token, "%config") || streq(token, "%cfg") ||
                    722:                                streq(token, "%config4") || streq(token, "%config6"))
                    723:                        {
                    724:                                /* empty pool, uses connection name */
                    725:                                this->attributes->add_pool(this->attributes,
                    726:                                                                mem_pool_create(msg->add_conn.name, NULL, 0));
                    727:                                peer_cfg->add_pool(peer_cfg, msg->add_conn.name);
                    728:                        }
                    729:                        else if (*token == '%')
                    730:                        {
                    731:                                /* external named pool */
                    732:                                peer_cfg->add_pool(peer_cfg, token + 1);
                    733:                        }
                    734:                        else
                    735:                        {
                    736:                                /* in-memory pool, using range or CIDR notation */
                    737:                                mem_pool_t *pool;
                    738:                                host_t *base;
                    739:                                int bits;
                    740: 
                    741:                                pool = create_pool_range(token);
                    742:                                if (!pool)
                    743:                                {
                    744:                                        base = host_create_from_subnet(token, &bits);
                    745:                                        if (base)
                    746:                                        {
                    747:                                                pool = mem_pool_create(token, base, bits);
                    748:                                                base->destroy(base);
                    749:                                        }
                    750:                                }
                    751:                                if (pool)
                    752:                                {
                    753:                                        this->attributes->add_pool(this->attributes, pool);
                    754:                                        peer_cfg->add_pool(peer_cfg, token);
                    755:                                }
                    756:                                else
                    757:                                {
                    758:                                        DBG1(DBG_CFG, "IP pool %s invalid, ignored", token);
                    759:                                }
                    760:                        }
                    761:                }
                    762:                enumerator->destroy(enumerator);
                    763:        }
                    764: 
                    765:        if (msg->add_conn.me.sourceip && msg->add_conn.other.sourceip)
                    766:        {
                    767:                DBG1(DBG_CFG, "'%s' has both left- and rightsourceip, but IKE can "
                    768:                         "negotiate one virtual IP only, ignoring local virtual IP",
                    769:                         msg->add_conn.name);
                    770:        }
                    771:        else if (msg->add_conn.me.sourceip)
                    772:        {
                    773:                enumerator_t *enumerator;
                    774:                char *token;
                    775: 
                    776:                enumerator = enumerator_create_token(msg->add_conn.me.sourceip, ",", " ");
                    777:                while (enumerator->enumerate(enumerator, &token))
                    778:                {
                    779:                        host_t *vip = NULL;
                    780: 
                    781:                        if (streq(token, "%modeconfig") || streq(token, "%modecfg") ||
                    782:                                streq(token, "%config") || streq(token, "%cfg"))
                    783:                        {       /* try to deduce an address family */
                    784:                                if (msg->add_conn.me.subnets)
                    785:                                {       /* use the same family as in local subnet, if any */
                    786:                                        if (strchr(msg->add_conn.me.subnets, '.'))
                    787:                                        {
                    788:                                                vip = host_create_any(AF_INET);
                    789:                                        }
                    790:                                        else
                    791:                                        {
                    792:                                                vip = host_create_any(AF_INET6);
                    793:                                        }
                    794:                                }
                    795:                                else if (msg->add_conn.other.subnets)
                    796:                                {       /* use the same family as in remote subnet, if any */
                    797:                                        if (strchr(msg->add_conn.other.subnets, '.'))
                    798:                                        {
                    799:                                                vip = host_create_any(AF_INET);
                    800:                                        }
                    801:                                        else
                    802:                                        {
                    803:                                                vip = host_create_any(AF_INET6);
                    804:                                        }
                    805:                                }
                    806:                                else
                    807:                                {
                    808:                                        char *addr, *next, *hit;
                    809: 
                    810:                                        /* guess virtual IP family based on local address. If
                    811:                                         * multiple addresses are specified, we look at the first
                    812:                                         * only, as with leftallowany a ::/0 is always appended. */
                    813:                                        addr = ike_cfg->get_my_addr(ike_cfg);
                    814:                                        next = strchr(addr, ',');
                    815:                                        hit = strchr(addr, ':');
                    816:                                        if (hit && (!next || hit < next))
                    817:                                        {
                    818:                                                vip = host_create_any(AF_INET6);
                    819:                                        }
                    820:                                        else
                    821:                                        {
                    822:                                                vip = host_create_any(AF_INET);
                    823:                                        }
                    824:                                }
                    825:                        }
                    826:                        else if (streq(token, "%config4"))
                    827:                        {
                    828:                                vip = host_create_any(AF_INET);
                    829:                        }
                    830:                        else if (streq(token, "%config6"))
                    831:                        {
                    832:                                vip = host_create_any(AF_INET6);
                    833:                        }
                    834:                        else
                    835:                        {
                    836:                                vip = host_create_from_string(token, 0);
                    837:                                if (!vip)
                    838:                                {
                    839:                                        DBG1(DBG_CFG, "ignored invalid subnet token: %s", token);
                    840:                                }
                    841:                        }
                    842: 
                    843:                        if (vip)
                    844:                        {
                    845:                                peer_cfg->add_virtual_ip(peer_cfg, vip);
                    846:                        }
                    847:                }
                    848:                enumerator->destroy(enumerator);
                    849:        }
                    850: 
                    851:        /* build leftauth= */
                    852:        auth_cfg = build_auth_cfg(this, msg, TRUE, TRUE);
                    853:        if (auth_cfg)
                    854:        {
                    855:                peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
                    856:        }
                    857:        else
                    858:        {       /* we require at least one config on our side */
                    859:                peer_cfg->destroy(peer_cfg);
                    860:                return NULL;
                    861:        }
                    862:        /* build leftauth2= */
                    863:        auth_cfg = build_auth_cfg(this, msg, TRUE, FALSE);
                    864:        if (auth_cfg)
                    865:        {
                    866:                peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
                    867:        }
                    868:        /* build rightauth= */
                    869:        auth_cfg = build_auth_cfg(this, msg, FALSE, TRUE);
                    870:        if (auth_cfg)
                    871:        {
                    872:                peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
                    873:        }
                    874:        /* build rightauth2= */
                    875:        auth_cfg = build_auth_cfg(this, msg, FALSE, FALSE);
                    876:        if (auth_cfg)
                    877:        {
                    878:                peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
                    879:        }
                    880:        return peer_cfg;
                    881: }
                    882: 
                    883: /**
                    884:  * Parse a protoport specifier
                    885:  */
                    886: static bool parse_protoport(char *token, uint16_t *from_port,
                    887:                                                        uint16_t *to_port, uint8_t *protocol)
                    888: {
                    889:        char *sep, *port = "", *endptr;
                    890:        struct protoent *proto;
                    891:        struct servent *svc;
                    892:        long int p;
                    893: 
                    894:        sep = strrchr(token, ']');
                    895:        if (!sep)
                    896:        {
                    897:                return FALSE;
                    898:        }
                    899:        *sep = '\0';
                    900: 
                    901:        sep = strchr(token, '/');
                    902:        if (sep)
                    903:        {       /* protocol/port */
                    904:                *sep = '\0';
                    905:                port = sep + 1;
                    906:        }
                    907: 
                    908:        if (streq(token, "%any"))
                    909:        {
                    910:                *protocol = 0;
                    911:        }
                    912:        else
                    913:        {
                    914:                proto = getprotobyname(token);
                    915:                if (proto)
                    916:                {
                    917:                        *protocol = proto->p_proto;
                    918:                }
                    919:                else
                    920:                {
                    921:                        p = strtol(token, &endptr, 0);
                    922:                        if ((*token && *endptr) || p < 0 || p > 0xff)
                    923:                        {
                    924:                                return FALSE;
                    925:                        }
                    926:                        *protocol = (uint8_t)p;
                    927:                }
                    928:        }
                    929:        if (streq(port, "%any"))
                    930:        {
                    931:                *from_port = 0;
                    932:                *to_port = 0xffff;
                    933:        }
                    934:        else if (streq(port, "%opaque"))
                    935:        {
                    936:                *from_port = 0xffff;
                    937:                *to_port = 0;
                    938:        }
                    939:        else if (*port)
                    940:        {
                    941:                svc = getservbyname(port, NULL);
                    942:                if (svc)
                    943:                {
                    944:                        *from_port = *to_port = ntohs(svc->s_port);
                    945:                }
                    946:                else
                    947:                {
                    948:                        p = strtol(port, &endptr, 0);
                    949:                        if (p < 0 || p > 0xffff)
                    950:                        {
                    951:                                return FALSE;
                    952:                        }
                    953:                        *from_port = p;
                    954:                        if (*endptr == '-')
                    955:                        {
                    956:                                port = endptr + 1;
                    957:                                p = strtol(port, &endptr, 0);
                    958:                                if (p < 0 || p > 0xffff)
                    959:                                {
                    960:                                        return FALSE;
                    961:                                }
                    962:                        }
                    963:                        *to_port = p;
                    964:                        if (*endptr)
                    965:                        {
                    966:                                return FALSE;
                    967:                        }
                    968:                }
                    969:        }
                    970:        return TRUE;
                    971: }
                    972: 
                    973: /**
                    974:  * build a traffic selector from a stroke_end
                    975:  */
                    976: static void add_ts(private_stroke_config_t *this,
                    977:                                   stroke_end_t *end, child_cfg_t *child_cfg, bool local)
                    978: {
                    979:        traffic_selector_t *ts;
                    980:        bool ts_added = FALSE;
                    981: 
                    982:        if (end->subnets)
                    983:        {
                    984:                enumerator_t *enumerator;
                    985:                char *subnet, *pos;
                    986:                uint16_t from_port, to_port;
                    987:                uint8_t proto;
                    988: 
                    989:                enumerator = enumerator_create_token(end->subnets, ",", " ");
                    990:                while (enumerator->enumerate(enumerator, &subnet))
                    991:                {
                    992:                        from_port = end->from_port;
                    993:                        to_port = end->to_port;
                    994:                        proto = end->protocol;
                    995: 
                    996:                        pos = strchr(subnet, '[');
                    997:                        if (pos)
                    998:                        {
                    999:                                *(pos++) = '\0';
                   1000:                                if (!parse_protoport(pos, &from_port, &to_port, &proto))
                   1001:                                {
                   1002:                                        DBG1(DBG_CFG, "invalid proto/port: %s, skipped subnet",
                   1003:                                                 pos);
                   1004:                                        continue;
                   1005:                                }
                   1006:                        }
                   1007:                        if (streq(subnet, "%dynamic"))
                   1008:                        {
                   1009:                                ts = traffic_selector_create_dynamic(proto,
                   1010:                                                                                                         from_port, to_port);
                   1011:                        }
                   1012:                        else
                   1013:                        {
                   1014:                                ts = traffic_selector_create_from_cidr(subnet, proto,
                   1015:                                                                                                           from_port, to_port);
                   1016:                        }
                   1017:                        if (ts)
                   1018:                        {
                   1019:                                child_cfg->add_traffic_selector(child_cfg, local, ts);
                   1020:                                ts_added = TRUE;
                   1021:                        }
                   1022:                        else
                   1023:                        {
                   1024:                                DBG1(DBG_CFG, "invalid subnet: %s, skipped", subnet);
                   1025:                        }
                   1026:                }
                   1027:                enumerator->destroy(enumerator);
                   1028:        }
                   1029:        if (!ts_added)
                   1030:        {
                   1031:                ts = traffic_selector_create_dynamic(end->protocol,
                   1032:                                                                                         end->from_port, end->to_port);
                   1033:                child_cfg->add_traffic_selector(child_cfg, local, ts);
                   1034:        }
                   1035: }
                   1036: 
                   1037: /**
                   1038:  * map starter magic values to our action type
                   1039:  */
                   1040: static action_t map_action(int starter_action)
                   1041: {
                   1042:        switch (starter_action)
                   1043:        {
                   1044:                case 2: /* =hold */
                   1045:                        return ACTION_ROUTE;
                   1046:                case 3: /* =restart */
                   1047:                        return ACTION_RESTART;
                   1048:                default:
                   1049:                        return ACTION_NONE;
                   1050:        }
                   1051: }
                   1052: 
                   1053: /**
                   1054:  * build a child config from the stroke message
                   1055:  */
                   1056: static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
                   1057:                                                                        stroke_msg_t *msg)
                   1058: {
                   1059:        child_cfg_t *child_cfg;
                   1060:        bool success;
                   1061:        child_cfg_create_t child = {
                   1062:                .lifetime = {
                   1063:                        .time = {
                   1064:                                .life = msg->add_conn.rekey.ipsec_lifetime,
                   1065:                                .rekey = msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
                   1066:                                .jitter = msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100
                   1067:                        },
                   1068:                        .bytes = {
                   1069:                                .life = msg->add_conn.rekey.life_bytes,
                   1070:                                .rekey = msg->add_conn.rekey.life_bytes - msg->add_conn.rekey.margin_bytes,
                   1071:                                .jitter = msg->add_conn.rekey.margin_bytes * msg->add_conn.rekey.fuzz / 100
                   1072:                        },
                   1073:                        .packets = {
                   1074:                                .life = msg->add_conn.rekey.life_packets,
                   1075:                                .rekey = msg->add_conn.rekey.life_packets - msg->add_conn.rekey.margin_packets,
                   1076:                                .jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
                   1077:                        },
                   1078:                },
                   1079:                .mark_in = {
                   1080:                        .value = msg->add_conn.mark_in.value,
                   1081:                        .mask = msg->add_conn.mark_in.mask
                   1082:                },
                   1083:                .mark_out = {
                   1084:                        .value = msg->add_conn.mark_out.value,
                   1085:                        .mask = msg->add_conn.mark_out.mask
                   1086:                },
                   1087:                .reqid = msg->add_conn.reqid,
                   1088:                .mode = msg->add_conn.mode,
                   1089:                .options = (msg->add_conn.proxy_mode ? OPT_PROXY_MODE : 0) |
                   1090:                                   (msg->add_conn.ipcomp ? OPT_IPCOMP : 0) |
                   1091:                                   (msg->add_conn.me.hostaccess ? OPT_HOSTACCESS : 0) |
                   1092:                                   (msg->add_conn.install_policy ? 0 : OPT_NO_POLICIES) |
                   1093:                                   (msg->add_conn.sha256_96 ? OPT_SHA256_96 : 0),
                   1094:                .tfc = msg->add_conn.tfc,
                   1095:                .inactivity = msg->add_conn.inactivity,
                   1096:                .dpd_action = map_action(msg->add_conn.dpd.action),
                   1097:                .close_action = map_action(msg->add_conn.close_action),
                   1098:                .updown = msg->add_conn.me.updown,
                   1099:        };
                   1100: 
                   1101:        child_cfg = child_cfg_create(msg->add_conn.name, &child);
                   1102:        if (msg->add_conn.replay_window != -1)
                   1103:        {
                   1104:                child_cfg->set_replay_window(child_cfg, msg->add_conn.replay_window);
                   1105:        }
                   1106:        add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
                   1107:        add_ts(this, &msg->add_conn.other, child_cfg, FALSE);
                   1108: 
                   1109:        if (msg->add_conn.algorithms.ah)
                   1110:        {
                   1111:                success = add_proposals(this, msg->add_conn.algorithms.ah,
                   1112:                                                                NULL, child_cfg, PROTO_AH);
                   1113:        }
                   1114:        else
                   1115:        {
                   1116:                success = add_proposals(this, msg->add_conn.algorithms.esp,
                   1117:                                                                NULL, child_cfg, PROTO_ESP);
                   1118:        }
                   1119:        if (!success)
                   1120:        {
                   1121:                child_cfg->destroy(child_cfg);
                   1122:                return NULL;
                   1123:        }
                   1124:        return child_cfg;
                   1125: }
                   1126: 
                   1127: METHOD(stroke_config_t, add, void,
                   1128:        private_stroke_config_t *this, stroke_msg_t *msg)
                   1129: {
                   1130:        ike_cfg_t *ike_cfg, *existing_ike;
                   1131:        peer_cfg_t *peer_cfg, *existing;
                   1132:        child_cfg_t *child_cfg;
                   1133:        enumerator_t *enumerator;
                   1134:        bool use_existing = FALSE;
                   1135: 
                   1136:        ike_cfg = build_ike_cfg(this, msg);
                   1137:        if (!ike_cfg)
                   1138:        {
                   1139:                return;
                   1140:        }
                   1141:        peer_cfg = build_peer_cfg(this, msg, ike_cfg);
                   1142:        if (!peer_cfg)
                   1143:        {
                   1144:                ike_cfg->destroy(ike_cfg);
                   1145:                return;
                   1146:        }
                   1147: 
                   1148:        enumerator = create_peer_cfg_enumerator(this, NULL, NULL);
                   1149:        while (enumerator->enumerate(enumerator, &existing))
                   1150:        {
                   1151:                existing_ike = existing->get_ike_cfg(existing);
                   1152:                if (existing->equals(existing, peer_cfg) &&
                   1153:                        existing_ike->equals(existing_ike, peer_cfg->get_ike_cfg(peer_cfg)))
                   1154:                {
                   1155:                        use_existing = TRUE;
                   1156:                        peer_cfg->destroy(peer_cfg);
                   1157:                        peer_cfg = existing;
                   1158:                        peer_cfg->get_ref(peer_cfg);
                   1159:                        DBG1(DBG_CFG, "added child to existing configuration '%s'",
                   1160:                                 peer_cfg->get_name(peer_cfg));
                   1161:                        break;
                   1162:                }
                   1163:        }
                   1164:        enumerator->destroy(enumerator);
                   1165: 
                   1166:        child_cfg = build_child_cfg(this, msg);
                   1167:        if (!child_cfg)
                   1168:        {
                   1169:                peer_cfg->destroy(peer_cfg);
                   1170:                return;
                   1171:        }
                   1172:        peer_cfg->add_child_cfg(peer_cfg, child_cfg);
                   1173: 
                   1174:        if (use_existing)
                   1175:        {
                   1176:                peer_cfg->destroy(peer_cfg);
                   1177:        }
                   1178:        else
                   1179:        {
                   1180:                /* add config to backend */
                   1181:                DBG1(DBG_CFG, "added configuration '%s'", msg->add_conn.name);
                   1182:                this->mutex->lock(this->mutex);
                   1183:                this->list->insert_last(this->list, peer_cfg);
                   1184:                this->mutex->unlock(this->mutex);
                   1185:        }
                   1186: }
                   1187: 
                   1188: METHOD(stroke_config_t, del, void,
                   1189:        private_stroke_config_t *this, stroke_msg_t *msg)
                   1190: {
                   1191:        enumerator_t *enumerator, *children;
                   1192:        peer_cfg_t *peer;
                   1193:        child_cfg_t *child;
                   1194:        bool deleted = FALSE;
                   1195: 
                   1196:        this->mutex->lock(this->mutex);
                   1197:        enumerator = this->list->create_enumerator(this->list);
                   1198:        while (enumerator->enumerate(enumerator, &peer))
                   1199:        {
                   1200:                bool keep = FALSE;
                   1201: 
                   1202:                /* remove any child with such a name */
                   1203:                children = peer->create_child_cfg_enumerator(peer);
                   1204:                while (children->enumerate(children, &child))
                   1205:                {
                   1206:                        if (streq(child->get_name(child), msg->del_conn.name))
                   1207:                        {
                   1208:                                peer->remove_child_cfg(peer, children);
                   1209:                                child->destroy(child);
                   1210:                                deleted = TRUE;
                   1211:                        }
                   1212:                        else
                   1213:                        {
                   1214:                                keep = TRUE;
                   1215:                        }
                   1216:                }
                   1217:                children->destroy(children);
                   1218: 
                   1219:                /* if peer config has no children anymore, remove it */
                   1220:                if (!keep)
                   1221:                {
                   1222:                        this->list->remove_at(this->list, enumerator);
                   1223:                        peer->destroy(peer);
                   1224:                }
                   1225:        }
                   1226:        enumerator->destroy(enumerator);
                   1227:        this->mutex->unlock(this->mutex);
                   1228: 
                   1229:        if (deleted)
                   1230:        {
                   1231:                DBG1(DBG_CFG, "deleted connection '%s'", msg->del_conn.name);
                   1232:        }
                   1233:        else
                   1234:        {
                   1235:                DBG1(DBG_CFG, "connection '%s' not found", msg->del_conn.name);
                   1236:        }
                   1237: }
                   1238: 
                   1239: METHOD(stroke_config_t, set_user_credentials, void,
                   1240:        private_stroke_config_t *this, stroke_msg_t *msg, FILE *prompt)
                   1241: {
                   1242:        enumerator_t *enumerator, *children, *remote_auth;
                   1243:        peer_cfg_t *peer, *found = NULL;
                   1244:        auth_cfg_t *auth_cfg, *remote_cfg;
                   1245:        auth_class_t auth_class;
                   1246:        child_cfg_t *child;
                   1247:        identification_t *id, *identity, *gw = NULL;
                   1248:        shared_key_type_t type = SHARED_ANY;
                   1249:        chunk_t password = chunk_empty;
                   1250: 
                   1251:        this->mutex->lock(this->mutex);
                   1252:        enumerator = this->list->create_enumerator(this->list);
                   1253:        while (enumerator->enumerate(enumerator, (void**)&peer))
                   1254:        {       /* find the peer (or child) config with the given name */
                   1255:                if (streq(peer->get_name(peer), msg->user_creds.name))
                   1256:                {
                   1257:                        found = peer;
                   1258:                }
                   1259:                else
                   1260:                {
                   1261:                        children = peer->create_child_cfg_enumerator(peer);
                   1262:                        while (children->enumerate(children, &child))
                   1263:                        {
                   1264:                                if (streq(child->get_name(child), msg->user_creds.name))
                   1265:                                {
                   1266:                                        found = peer;
                   1267:                                        break;
                   1268:                                }
                   1269:                        }
                   1270:                        children->destroy(children);
                   1271:                }
                   1272: 
                   1273:                if (found)
                   1274:                {
                   1275:                        break;
                   1276:                }
                   1277:        }
                   1278:        enumerator->destroy(enumerator);
                   1279: 
                   1280:        if (!found)
                   1281:        {
                   1282:                DBG1(DBG_CFG, "  no config named '%s'", msg->user_creds.name);
                   1283:                fprintf(prompt, "no config named '%s'\n", msg->user_creds.name);
                   1284:                this->mutex->unlock(this->mutex);
                   1285:                return;
                   1286:        }
                   1287: 
                   1288:        id = identification_create_from_string(msg->user_creds.username);
                   1289:        if (strlen(msg->user_creds.username) == 0 ||
                   1290:                !id || id->get_type(id) == ID_ANY)
                   1291:        {
                   1292:                DBG1(DBG_CFG, "  invalid username '%s'", msg->user_creds.username);
                   1293:                fprintf(prompt, "invalid username '%s'\n", msg->user_creds.username);
                   1294:                this->mutex->unlock(this->mutex);
                   1295:                DESTROY_IF(id);
                   1296:                return;
                   1297:        }
                   1298: 
                   1299:        /* replace/set the username in the first EAP/XAuth auth_cfg, also look for
                   1300:         * a suitable remote ID.
                   1301:         * note that adding the identity here is not fully thread-safe as the
                   1302:         * peer_cfg and in turn the auth_cfg could be in use. for the default use
                   1303:         * case (setting user credentials before upping the connection) this will
                   1304:         * not be a problem, though. */
                   1305:        enumerator = found->create_auth_cfg_enumerator(found, TRUE);
                   1306:        remote_auth = found->create_auth_cfg_enumerator(found, FALSE);
                   1307:        while (enumerator->enumerate(enumerator, (void**)&auth_cfg))
                   1308:        {
                   1309:                if (remote_auth->enumerate(remote_auth, (void**)&remote_cfg))
                   1310:                {       /* fall back on rightid, in case aaa_identity is not specified */
                   1311:                        identity = remote_cfg->get(remote_cfg, AUTH_RULE_IDENTITY);
                   1312:                        if (identity && identity->get_type(identity) != ID_ANY)
                   1313:                        {
                   1314:                                gw = identity;
                   1315:                        }
                   1316:                }
                   1317: 
                   1318:                auth_class = (uintptr_t)auth_cfg->get(auth_cfg, AUTH_RULE_AUTH_CLASS);
                   1319:                if (auth_class == AUTH_CLASS_EAP || auth_class == AUTH_CLASS_XAUTH)
                   1320:                {
                   1321:                        if (auth_class == AUTH_CLASS_EAP)
                   1322:                        {
                   1323:                                auth_cfg->add(auth_cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
                   1324:                                /* if aaa_identity is specified use that as remote ID */
                   1325:                                identity = auth_cfg->get(auth_cfg, AUTH_RULE_AAA_IDENTITY);
                   1326:                                if (identity && identity->get_type(identity) != ID_ANY)
                   1327:                                {
                   1328:                                        gw = identity;
                   1329:                                }
                   1330:                                DBG1(DBG_CFG, "  configured EAP-Identity %Y", id);
                   1331:                        }
                   1332:                        else
                   1333:                        {
                   1334:                                auth_cfg->add(auth_cfg, AUTH_RULE_XAUTH_IDENTITY,
                   1335:                                                          id->clone(id));
                   1336:                                DBG1(DBG_CFG, "  configured XAuth username %Y", id);
                   1337:                        }
                   1338:                        type = SHARED_EAP;
                   1339:                        break;
                   1340:                }
                   1341:        }
                   1342:        enumerator->destroy(enumerator);
                   1343:        remote_auth->destroy(remote_auth);
                   1344:        /* clone the gw ID before unlocking the mutex */
                   1345:        if (gw)
                   1346:        {
                   1347:                gw = gw->clone(gw);
                   1348:        }
                   1349:        this->mutex->unlock(this->mutex);
                   1350: 
                   1351:        if (type == SHARED_ANY)
                   1352:        {
                   1353:                DBG1(DBG_CFG, "  config '%s' unsuitable for user credentials",
                   1354:                         msg->user_creds.name);
                   1355:                fprintf(prompt, "config '%s' unsuitable for user credentials\n",
                   1356:                                msg->user_creds.name);
                   1357:                id->destroy(id);
                   1358:                DESTROY_IF(gw);
                   1359:                return;
                   1360:        }
                   1361: 
                   1362:        if (msg->user_creds.password)
                   1363:        {
                   1364:                char *pass;
                   1365: 
                   1366:                pass = msg->user_creds.password;
                   1367:                password = chunk_clone(chunk_create(pass, strlen(pass)));
                   1368:                memwipe(pass, strlen(pass));
                   1369:        }
                   1370:        else
                   1371:        {       /* prompt the user for the password */
                   1372:                char buf[256];
                   1373: 
                   1374:                fprintf(prompt, "Password:\n");
                   1375:                if (fgets(buf, sizeof(buf), prompt))
                   1376:                {
                   1377:                        password = chunk_clone(chunk_create(buf, strlen(buf)));
                   1378:                        if (password.len > 0)
                   1379:                        {       /* trim trailing \n */
                   1380:                                password.len--;
                   1381:                        }
                   1382:                        memwipe(buf, sizeof(buf));
                   1383:                }
                   1384:        }
                   1385: 
                   1386:        if (password.len)
                   1387:        {
                   1388:                shared_key_t *shared;
                   1389:                linked_list_t *owners;
                   1390: 
                   1391:                shared = shared_key_create(type, password);
                   1392: 
                   1393:                owners = linked_list_create();
                   1394:                owners->insert_last(owners, id->clone(id));
                   1395:                if (gw && gw->get_type(gw) != ID_ANY)
                   1396:                {
                   1397:                        owners->insert_last(owners, gw->clone(gw));
                   1398:                        DBG1(DBG_CFG, "  added %N secret for %Y %Y", shared_key_type_names,
                   1399:                                 type, id, gw);
                   1400:                }
                   1401:                else
                   1402:                {
                   1403:                        DBG1(DBG_CFG, "  added %N secret for %Y", shared_key_type_names,
                   1404:                                 type, id);
                   1405:                }
                   1406:                this->cred->add_shared(this->cred, shared, owners);
                   1407:                DBG4(DBG_CFG, "  secret: %#B", &password);
                   1408:        }
                   1409:        else
                   1410:        {       /* in case a user answers the password prompt by just pressing enter */
                   1411:                chunk_clear(&password);
                   1412:        }
                   1413:        id->destroy(id);
                   1414:        DESTROY_IF(gw);
                   1415: }
                   1416: 
                   1417: METHOD(stroke_config_t, destroy, void,
                   1418:        private_stroke_config_t *this)
                   1419: {
                   1420:        this->list->destroy_offset(this->list, offsetof(peer_cfg_t, destroy));
                   1421:        this->mutex->destroy(this->mutex);
                   1422:        free(this);
                   1423: }
                   1424: 
                   1425: /*
                   1426:  * see header file
                   1427:  */
                   1428: stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred,
                   1429:                                                                          stroke_attribute_t *attributes)
                   1430: {
                   1431:        private_stroke_config_t *this;
                   1432: 
                   1433:        INIT(this,
                   1434:                .public = {
                   1435:                        .backend = {
                   1436:                                .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
                   1437:                                .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
                   1438:                                .get_peer_cfg_by_name = _get_peer_cfg_by_name,
                   1439:                        },
                   1440:                        .add = _add,
                   1441:                        .del = _del,
                   1442:                        .set_user_credentials = _set_user_credentials,
                   1443:                        .destroy = _destroy,
                   1444:                },
                   1445:                .list = linked_list_create(),
                   1446:                .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
                   1447:                .ca = ca,
                   1448:                .cred = cred,
                   1449:                .attributes = attributes,
                   1450:        );
                   1451: 
                   1452:        return &this->public;
                   1453: }

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