Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_config.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2014 Martin Willi
                      3:  * Copyright (C) 2014 revosec AG
                      4:  *
                      5:  * Copyright (C) 2015-2019 Tobias Brunner
                      6:  * Copyright (C) 2015-2018 Andreas Steffen
                      7:  * HSR Hochschule fuer Technik Rapperswil
                      8:  *
                      9:  * This program is free software; you can redistribute it and/or modify it
                     10:  * under the terms of the GNU General Public License as published by the
                     11:  * Free Software Foundation; either version 2 of the License, or (at your
                     12:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     13:  *
                     14:  * This program is distributed in the hope that it will be useful, but
                     15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     16:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     17:  * for more details.
                     18:  */
                     19: 
                     20: /*
                     21:  * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
                     22:  *
                     23:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     24:  * of this software and associated documentation files (the "Software"), to deal
                     25:  * in the Software without restriction, including without limitation the rights
                     26:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     27:  * copies of the Software, and to permit persons to whom the Software is
                     28:  * furnished to do so, subject to the following conditions:
                     29:  *
                     30:  * The above copyright notice and this permission notice shall be included in
                     31:  * all copies or substantial portions of the Software.
                     32:  *
                     33:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     34:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     35:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     36:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     37:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     38:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     39:  * THE SOFTWARE.
                     40:  */
                     41: 
                     42: #define _GNU_SOURCE
                     43: 
                     44: #include "vici_config.h"
                     45: #include "vici_builder.h"
                     46: 
                     47: #include <daemon.h>
                     48: #include <threading/rwlock.h>
                     49: #include <threading/rwlock_condvar.h>
                     50: #include <collections/array.h>
                     51: #include <collections/linked_list.h>
                     52: 
                     53: #include <pubkey_cert.h>
                     54: 
                     55: #include <stdio.h>
                     56: 
                     57: /**
                     58:  * Magic value for an undefined lifetime
                     59:  */
                     60: #define LFT_UNDEFINED (~(uint64_t)0)
                     61: 
                     62: /**
                     63:  * Default IKE rekey time
                     64:  */
                     65: #define LFT_DEFAULT_IKE_REKEY_TIME             (4 * 60 * 60)
                     66: 
                     67: /**
                     68:  * Default CHILD rekey time
                     69:  */
                     70: #define LFT_DEFAULT_CHILD_REKEY_TIME   (1 * 60 * 60)
                     71: 
                     72: /**
                     73:  * Default CHILD rekey bytes
                     74:  */
                     75: #define LFT_DEFAULT_CHILD_REKEY_BYTES          0
                     76: 
                     77: /**
                     78:  * Default CHILD rekey packets
                     79:  */
                     80: #define LFT_DEFAULT_CHILD_REKEY_PACKETS                0
                     81: 
                     82: /**
                     83:  * Undefined replay window
                     84:  */
                     85: #define REPLAY_UNDEFINED (~(uint32_t)0)
                     86: 
                     87: typedef struct private_vici_config_t private_vici_config_t;
                     88: 
                     89: /**
                     90:  * Private data of an vici_config_t object.
                     91:  */
                     92: struct private_vici_config_t {
                     93: 
                     94:        /**
                     95:         * Public vici_config_t interface.
                     96:         */
                     97:        vici_config_t public;
                     98: 
                     99:        /**
                    100:         * Dispatcher
                    101:         */
                    102:        vici_dispatcher_t *dispatcher;
                    103: 
                    104:        /**
                    105:         * List of loaded connections, as peer_cfg_t
                    106:         */
                    107:        linked_list_t *conns;
                    108: 
                    109:        /**
                    110:         * Lock for conns list
                    111:         */
                    112:        rwlock_t *lock;
                    113: 
                    114:        /**
                    115:         * Condvar used to sync running actions
                    116:         */
                    117:        rwlock_condvar_t *condvar;
                    118: 
                    119:        /**
                    120:         * True while we run or undo a start action
                    121:         */
                    122:        bool handling_actions;
                    123: 
                    124:        /**
                    125:         * Credential backend managed by VICI used for our certificates
                    126:         */
                    127:        vici_cred_t *cred;
                    128: 
                    129:        /**
                    130:         * Auxiliary certification authority information
                    131:         */
                    132:        vici_authority_t *authority;
                    133: 
                    134: };
                    135: 
                    136: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
                    137:        private_vici_config_t *this, identification_t *me, identification_t *other)
                    138: {
                    139:        this->lock->read_lock(this->lock);
                    140:        return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
                    141:                                                                         (void*)this->lock->unlock, this->lock);
                    142: }
                    143: 
                    144: CALLBACK(ike_filter, bool,
                    145:        void *data, enumerator_t *orig, va_list args)
                    146: {
                    147:        peer_cfg_t *cfg;
                    148:        ike_cfg_t **out;
                    149: 
                    150:        VA_ARGS_VGET(args, out);
                    151: 
                    152:        if (orig->enumerate(orig, &cfg))
                    153:        {
                    154:                *out = cfg->get_ike_cfg(cfg);
                    155:                return TRUE;
                    156:        }
                    157:        return FALSE;
                    158: }
                    159: 
                    160: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
                    161:        private_vici_config_t *this, host_t *me, host_t *other)
                    162: {
                    163:        this->lock->read_lock(this->lock);
                    164:        return enumerator_create_filter(this->conns->create_enumerator(this->conns),
                    165:                                                                        ike_filter, this->lock,
                    166:                                                                        (void*)this->lock->unlock);
                    167: }
                    168: 
                    169: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
                    170:        private_vici_config_t *this, char *name)
                    171: {
                    172:        peer_cfg_t *current, *found = NULL;
                    173:        enumerator_t *enumerator;
                    174: 
                    175:        this->lock->read_lock(this->lock);
                    176:        enumerator = this->conns->create_enumerator(this->conns);
                    177:        while (enumerator->enumerate(enumerator, &current))
                    178:        {
                    179:                if (streq(current->get_name(current), name))
                    180:                {
                    181:                        found = current;
                    182:                        found->get_ref(found);
                    183:                        break;
                    184:                }
                    185:        }
                    186:        enumerator->destroy(enumerator);
                    187:        this->lock->unlock(this->lock);
                    188: 
                    189:        return found;
                    190: }
                    191: 
                    192: /**
                    193:  * Create a (error) reply message
                    194:  */
                    195: static vici_message_t* create_reply(char *fmt, ...)
                    196: {
                    197:        vici_builder_t *builder;
                    198:        va_list args;
                    199: 
                    200:        builder = vici_builder_create();
                    201:        builder->add_kv(builder, "success", fmt ? "no" : "yes");
                    202:        if (fmt)
                    203:        {
                    204:                va_start(args, fmt);
                    205:                builder->vadd_kv(builder, "errmsg", fmt, args);
                    206:                va_end(args);
                    207:        }
                    208:        return builder->finalize(builder);
                    209: }
                    210: 
                    211: /**
                    212:  * A rule to parse a key/value or list item
                    213:  */
                    214: typedef struct {
                    215:        /** name of the key/value or list */
                    216:        char *name;
                    217:        /** function to parse value */
                    218:        bool (*parse)(void *out, chunk_t value);
                    219:        /** result, passed to parse() */
                    220:        void *out;
                    221: } parse_rule_t;
                    222: 
                    223: /**
                    224:  * Parse key/values using a rule-set
                    225:  */
                    226: static bool parse_rules(parse_rule_t *rules, int count, char *name,
                    227:                                                chunk_t value, vici_message_t **reply)
                    228: {
                    229:        int i;
                    230: 
                    231:        for (i = 0; i < count; i++)
                    232:        {
                    233:                if (streq(name, rules[i].name))
                    234:                {
                    235:                        if (rules[i].parse(rules[i].out, value))
                    236:                        {
                    237:                                return TRUE;
                    238:                        }
                    239:                        *reply = create_reply("invalid value for: %s, config discarded",
                    240:                                                                  name);
                    241:                        return FALSE;
                    242:                }
                    243:        }
                    244:        *reply = create_reply("unknown option: %s, config discarded", name);
                    245:        return FALSE;
                    246: }
                    247: 
                    248: /**
                    249:  * Parse callback data, passed to each callback
                    250:  */
                    251: typedef struct {
                    252:        private_vici_config_t *this;
                    253:        vici_message_t *reply;
                    254: } request_data_t;
                    255: 
                    256: /**
                    257:  * Certificate data
                    258:  */
                    259: typedef struct {
                    260:        request_data_t *request;
                    261:        char *handle;
                    262:        uint32_t slot;
                    263:        char *module;
                    264:        char *file;
                    265: } cert_data_t;
                    266: 
                    267: /**
                    268:  * Clean up certificate data
                    269:  */
                    270: static void free_cert_data(cert_data_t *data)
                    271: {
                    272:        free(data->handle);
                    273:        free(data->module);
                    274:        free(data->file);
                    275:        free(data);
                    276: }
                    277: 
                    278: /**
                    279:  * Auth config data
                    280:  */
                    281: typedef struct {
                    282:        request_data_t *request;
                    283:        auth_cfg_t *cfg;
                    284:        uint32_t round;
                    285: } auth_data_t;
                    286: 
                    287: /**
                    288:  * Clean up auth config data
                    289:  */
                    290: static void free_auth_data(auth_data_t *data)
                    291: {
                    292:        DESTROY_IF(data->cfg);
                    293:        free(data);
                    294: }
                    295: 
                    296: /**
                    297:  * Data associated to a peer config
                    298:  */
                    299: typedef struct {
                    300:        request_data_t *request;
                    301:        uint32_t version;
                    302:        bool aggressive;
                    303:        bool encap;
                    304:        bool mobike;
                    305:        bool send_certreq;
                    306:        bool pull;
                    307:        identification_t *ppk_id;
                    308:        bool ppk_required;
                    309:        cert_policy_t send_cert;
                    310:        uint64_t dpd_delay;
                    311:        uint64_t dpd_timeout;
                    312:        fragmentation_t fragmentation;
                    313:        childless_t childless;
                    314:        unique_policy_t unique;
                    315:        uint32_t keyingtries;
                    316:        uint32_t local_port;
                    317:        uint32_t remote_port;
                    318:        char *local_addrs;
                    319:        char *remote_addrs;
                    320:        linked_list_t *local;
                    321:        linked_list_t *remote;
                    322:        linked_list_t *proposals;
                    323:        linked_list_t *children;
                    324:        linked_list_t *vips;
                    325:        char *pools;
                    326:        uint64_t reauth_time;
                    327:        uint64_t rekey_time;
                    328:        uint64_t over_time;
                    329:        uint64_t rand_time;
                    330:        uint8_t dscp;
                    331:        uint32_t if_id_in;
                    332:        uint32_t if_id_out;
                    333: #ifdef ME
                    334:        bool mediation;
                    335:        char *mediated_by;
                    336:        identification_t *peer_id;
                    337: #endif /* ME */
                    338: } peer_data_t;
                    339: 
                    340: /**
                    341:  * Log relevant auth config data
                    342:  */
                    343: static void log_auth(auth_cfg_t *auth)
                    344: {
                    345:        enumerator_t *enumerator;
                    346:        auth_rule_t rule;
                    347:        union {
                    348:                uintptr_t u;
                    349:                identification_t *id;
                    350:                certificate_t *cert;
                    351:                char *str;
                    352:        } v;
                    353: 
                    354:        enumerator = auth->create_enumerator(auth);
                    355:        while (enumerator->enumerate(enumerator, &rule, &v))
                    356:        {
                    357:                switch (rule)
                    358:                {
                    359:                        case AUTH_RULE_AUTH_CLASS:
                    360:                                DBG2(DBG_CFG, "   class = %N", auth_class_names, v.u);
                    361:                                break;
                    362:                        case AUTH_RULE_EAP_TYPE:
                    363:                                DBG2(DBG_CFG, "   eap-type = %N", eap_type_names, v.u);
                    364:                                break;
                    365:                        case AUTH_RULE_EAP_VENDOR:
                    366:                                DBG2(DBG_CFG, "   eap-vendor = %u", v.u);
                    367:                                break;
                    368:                        case AUTH_RULE_XAUTH_BACKEND:
                    369:                                DBG2(DBG_CFG, "   xauth = %s", v.str);
                    370:                                break;
                    371:                        case AUTH_RULE_CRL_VALIDATION:
                    372:                                DBG2(DBG_CFG, "   revocation = %N", cert_validation_names, v.u);
                    373:                                break;
                    374:                        case AUTH_RULE_IDENTITY:
                    375:                                DBG2(DBG_CFG, "   id = %Y", v.id);
                    376:                                break;
                    377:                        case AUTH_RULE_CA_IDENTITY:
                    378:                                DBG2(DBG_CFG, "   ca_id = %Y", v.id);
                    379:                                break;
                    380:                        case AUTH_RULE_AAA_IDENTITY:
                    381:                                DBG2(DBG_CFG, "   aaa_id = %Y", v.id);
                    382:                                break;
                    383:                        case AUTH_RULE_EAP_IDENTITY:
                    384:                                DBG2(DBG_CFG, "   eap_id = %Y", v.id);
                    385:                                break;
                    386:                        case AUTH_RULE_XAUTH_IDENTITY:
                    387:                                DBG2(DBG_CFG, "   xauth_id = %Y", v.id);
                    388:                                break;
                    389:                        case AUTH_RULE_GROUP:
                    390:                                DBG2(DBG_CFG, "   group = %Y", v.id);
                    391:                                break;
                    392:                        case AUTH_RULE_SUBJECT_CERT:
                    393:                                DBG2(DBG_CFG, "   cert = %Y", v.cert->get_subject(v.cert));
                    394:                                break;
                    395:                        case AUTH_RULE_CA_CERT:
                    396:                                DBG2(DBG_CFG, "   cacert = %Y", v.cert->get_subject(v.cert));
                    397:                                break;
                    398:                        default:
                    399:                                break;
                    400:                }
                    401:        }
                    402:        enumerator->destroy(enumerator);
                    403: }
                    404: 
                    405: /**
                    406:  * Log parsed peer data
                    407:  */
                    408: static void log_peer_data(peer_data_t *data)
                    409: {
                    410:        enumerator_t *enumerator;
                    411:        auth_data_t *auth;
                    412:        host_t *host;
                    413: 
                    414:        DBG2(DBG_CFG, "  version = %u", data->version);
                    415:        DBG2(DBG_CFG, "  local_addrs = %s", data->local_addrs);
                    416:        DBG2(DBG_CFG, "  remote_addrs = %s", data->remote_addrs);
                    417:        DBG2(DBG_CFG, "  local_port = %u", data->local_port);
                    418:        DBG2(DBG_CFG, "  remote_port = %u", data->remote_port);
                    419:        DBG2(DBG_CFG, "  send_certreq = %u", data->send_certreq);
                    420:        DBG2(DBG_CFG, "  send_cert = %N", cert_policy_names, data->send_cert);
                    421:        DBG2(DBG_CFG, "  ppk_id = %Y",  data->ppk_id);
                    422:        DBG2(DBG_CFG, "  ppk_required = %u",  data->ppk_required);
                    423:        DBG2(DBG_CFG, "  mobike = %u", data->mobike);
                    424:        DBG2(DBG_CFG, "  aggressive = %u", data->aggressive);
                    425:        DBG2(DBG_CFG, "  dscp = 0x%.2x", data->dscp);
                    426:        DBG2(DBG_CFG, "  encap = %u", data->encap);
                    427:        DBG2(DBG_CFG, "  dpd_delay = %llu", data->dpd_delay);
                    428:        DBG2(DBG_CFG, "  dpd_timeout = %llu", data->dpd_timeout);
                    429:        DBG2(DBG_CFG, "  fragmentation = %u",  data->fragmentation);
                    430:        DBG2(DBG_CFG, "  childless = %u",  data->childless);
                    431:        DBG2(DBG_CFG, "  unique = %N", unique_policy_names, data->unique);
                    432:        DBG2(DBG_CFG, "  keyingtries = %u", data->keyingtries);
                    433:        DBG2(DBG_CFG, "  reauth_time = %llu", data->reauth_time);
                    434:        DBG2(DBG_CFG, "  rekey_time = %llu", data->rekey_time);
                    435:        DBG2(DBG_CFG, "  over_time = %llu", data->over_time);
                    436:        DBG2(DBG_CFG, "  rand_time = %llu", data->rand_time);
                    437:        DBG2(DBG_CFG, "  proposals = %#P", data->proposals);
                    438:        DBG2(DBG_CFG, "  if_id_in = %u", data->if_id_in);
                    439:        DBG2(DBG_CFG, "  if_id_out = %u", data->if_id_out);
                    440: #ifdef ME
                    441:        DBG2(DBG_CFG, "  mediation = %u", data->mediation);
                    442:        if (data->mediated_by)
                    443:        {
                    444:                DBG2(DBG_CFG, "  mediated_by = %s", data->mediated_by);
                    445:                DBG2(DBG_CFG, "  mediation_peer = %Y", data->peer_id);
                    446:        }
                    447: #endif /* ME */
                    448: 
                    449:        if (data->vips->get_count(data->vips))
                    450:        {
                    451:                DBG2(DBG_CFG, "  vips:");
                    452:        }
                    453:        enumerator = data->vips->create_enumerator(data->vips);
                    454:        while (enumerator->enumerate(enumerator, &host))
                    455:        {
                    456:                DBG2(DBG_CFG, "   %H", host);
                    457:        }
                    458:        enumerator->destroy(enumerator);
                    459: 
                    460:        enumerator = data->local->create_enumerator(data->local);
                    461:        while (enumerator->enumerate(enumerator, &auth))
                    462:        {
                    463:                DBG2(DBG_CFG, "  local:");
                    464:                log_auth(auth->cfg);
                    465:        }
                    466:        enumerator->destroy(enumerator);
                    467: 
                    468:        enumerator = data->remote->create_enumerator(data->remote);
                    469:        while (enumerator->enumerate(enumerator, &auth))
                    470:        {
                    471:                DBG2(DBG_CFG, "  remote:");
                    472:                log_auth(auth->cfg);
                    473:        }
                    474:        enumerator->destroy(enumerator);
                    475: }
                    476: 
                    477: /**
                    478:  * Clean up peer config data
                    479:  */
                    480: static void free_peer_data(peer_data_t *data)
                    481: {
                    482:        data->local->destroy_function(data->local, (void*)free_auth_data);
                    483:        data->remote->destroy_function(data->remote, (void*)free_auth_data);
                    484:        data->children->destroy_offset(data->children,
                    485:                                                                        offsetof(child_cfg_t, destroy));
                    486:        data->proposals->destroy_offset(data->proposals,
                    487:                                                                        offsetof(proposal_t, destroy));
                    488:        data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
                    489:        free(data->pools);
                    490:        free(data->local_addrs);
                    491:        free(data->remote_addrs);
                    492:        DESTROY_IF(data->ppk_id);
                    493: #ifdef ME
                    494:        free(data->mediated_by);
                    495:        DESTROY_IF(data->peer_id);
                    496: #endif /* ME */
                    497: }
                    498: 
                    499: /**
                    500:  * CHILD config data
                    501:  */
                    502: typedef struct {
                    503:        request_data_t *request;
                    504:        linked_list_t *proposals;
                    505:        linked_list_t *local_ts;
                    506:        linked_list_t *remote_ts;
                    507:        uint32_t replay_window;
                    508:        child_cfg_create_t cfg;
                    509: } child_data_t;
                    510: 
                    511: /**
                    512:  * Log parsed CHILD config data
                    513:  */
                    514: static void log_child_data(child_data_t *data, char *name)
                    515: {
                    516:        child_cfg_create_t *cfg = &data->cfg;
                    517: 
                    518: #define has_opt(opt) ({ (cfg->options & (opt)) == (opt); })
                    519:        DBG2(DBG_CFG, "  child %s:", name);
                    520:        DBG2(DBG_CFG, "   rekey_time = %llu", cfg->lifetime.time.rekey);
                    521:        DBG2(DBG_CFG, "   life_time = %llu", cfg->lifetime.time.life);
                    522:        DBG2(DBG_CFG, "   rand_time = %llu", cfg->lifetime.time.jitter);
                    523:        DBG2(DBG_CFG, "   rekey_bytes = %llu", cfg->lifetime.bytes.rekey);
                    524:        DBG2(DBG_CFG, "   life_bytes = %llu", cfg->lifetime.bytes.life);
                    525:        DBG2(DBG_CFG, "   rand_bytes = %llu", cfg->lifetime.bytes.jitter);
                    526:        DBG2(DBG_CFG, "   rekey_packets = %llu", cfg->lifetime.packets.rekey);
                    527:        DBG2(DBG_CFG, "   life_packets = %llu", cfg->lifetime.packets.life);
                    528:        DBG2(DBG_CFG, "   rand_packets = %llu", cfg->lifetime.packets.jitter);
                    529:        DBG2(DBG_CFG, "   updown = %s", cfg->updown);
                    530:        DBG2(DBG_CFG, "   hostaccess = %u", has_opt(OPT_HOSTACCESS));
                    531:        DBG2(DBG_CFG, "   ipcomp = %u", has_opt(OPT_IPCOMP));
                    532:        DBG2(DBG_CFG, "   mode = %N%s", ipsec_mode_names, cfg->mode,
                    533:                 has_opt(OPT_PROXY_MODE) ? "_PROXY" : "");
                    534:        DBG2(DBG_CFG, "   policies = %u", !has_opt(OPT_NO_POLICIES));
                    535:        DBG2(DBG_CFG, "   policies_fwd_out = %u", has_opt(OPT_FWD_OUT_POLICIES));
                    536:        if (data->replay_window != REPLAY_UNDEFINED)
                    537:        {
                    538:                DBG2(DBG_CFG, "   replay_window = %u", data->replay_window);
                    539:        }
                    540:        DBG2(DBG_CFG, "   dpd_action = %N", action_names, cfg->dpd_action);
                    541:        DBG2(DBG_CFG, "   start_action = %N", action_names, cfg->start_action);
                    542:        DBG2(DBG_CFG, "   close_action = %N", action_names, cfg->close_action);
                    543:        DBG2(DBG_CFG, "   reqid = %u", cfg->reqid);
                    544:        DBG2(DBG_CFG, "   tfc = %d", cfg->tfc);
                    545:        DBG2(DBG_CFG, "   priority = %d", cfg->priority);
                    546:        DBG2(DBG_CFG, "   interface = %s", cfg->interface);
                    547:        DBG2(DBG_CFG, "   if_id_in = %u", cfg->if_id_in);
                    548:        DBG2(DBG_CFG, "   if_id_out = %u", cfg->if_id_out);
                    549:        DBG2(DBG_CFG, "   mark_in = %u/%u",
                    550:                 cfg->mark_in.value, cfg->mark_in.mask);
                    551:        DBG2(DBG_CFG, "   mark_in_sa = %u", has_opt(OPT_MARK_IN_SA));
                    552:        DBG2(DBG_CFG, "   mark_out = %u/%u",
                    553:                 cfg->mark_out.value, cfg->mark_out.mask);
                    554:        DBG2(DBG_CFG, "   set_mark_in = %u/%u",
                    555:                 cfg->set_mark_in.value, cfg->set_mark_in.mask);
                    556:        DBG2(DBG_CFG, "   set_mark_out = %u/%u",
                    557:                 cfg->set_mark_out.value, cfg->set_mark_out.mask);
                    558:        DBG2(DBG_CFG, "   inactivity = %llu", cfg->inactivity);
                    559:        DBG2(DBG_CFG, "   proposals = %#P", data->proposals);
                    560:        DBG2(DBG_CFG, "   local_ts = %#R", data->local_ts);
                    561:        DBG2(DBG_CFG, "   remote_ts = %#R", data->remote_ts);
                    562:        DBG2(DBG_CFG, "   hw_offload = %N", hw_offload_names, cfg->hw_offload);
                    563:        DBG2(DBG_CFG, "   sha256_96 = %u", has_opt(OPT_SHA256_96));
                    564:        DBG2(DBG_CFG, "   copy_df = %u", !has_opt(OPT_NO_COPY_DF));
                    565:        DBG2(DBG_CFG, "   copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN));
                    566:        DBG2(DBG_CFG, "   copy_dscp = %N", dscp_copy_names, cfg->copy_dscp);
                    567: }
                    568: 
                    569: /**
                    570:  * Clean up CHILD config data
                    571:  */
                    572: static void free_child_data(child_data_t *data)
                    573: {
                    574:        data->proposals->destroy_offset(data->proposals,
                    575:                                                                        offsetof(proposal_t, destroy));
                    576:        data->local_ts->destroy_offset(data->local_ts,
                    577:                                                                        offsetof(traffic_selector_t, destroy));
                    578:        data->remote_ts->destroy_offset(data->remote_ts,
                    579:                                                                        offsetof(traffic_selector_t, destroy));
                    580:        free(data->cfg.updown);
                    581:        free(data->cfg.interface);
                    582: }
                    583: 
                    584: /**
                    585:  * Common proposal parsing
                    586:  */
                    587: static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v)
                    588: {
                    589:        char buf[BUF_LEN];
                    590:        proposal_t *proposal;
                    591: 
                    592:        if (!vici_stringify(v, buf, sizeof(buf)))
                    593:        {
                    594:                return FALSE;
                    595:        }
                    596:        if (strcaseeq("default", buf))
                    597:        {
                    598:                proposal = proposal_create_default(proto);
                    599:                if (proposal)
                    600:                {
                    601:                        list->insert_last(list, proposal);
                    602:                }
                    603:                proposal = proposal_create_default_aead(proto);
                    604:                if (proposal)
                    605:                {
                    606:                        list->insert_last(list, proposal);
                    607:                }
                    608:                return TRUE;
                    609:        }
                    610:        proposal = proposal_create_from_string(proto, buf);
                    611:        if (proposal)
                    612:        {
                    613:                list->insert_last(list, proposal);
                    614:                return TRUE;
                    615:        }
                    616:        return FALSE;
                    617: }
                    618: 
                    619: /**
                    620:  * Parse IKE proposal
                    621:  */
                    622: CALLBACK(parse_ike_proposal, bool,
                    623:        linked_list_t *out, chunk_t v)
                    624: {
                    625:        return parse_proposal(out, PROTO_IKE, v);
                    626: }
                    627: 
                    628: /**
                    629:  * Parse ESP proposal
                    630:  */
                    631: CALLBACK(parse_esp_proposal, bool,
                    632:        linked_list_t *out, chunk_t v)
                    633: {
                    634:        return parse_proposal(out, PROTO_ESP, v);
                    635: }
                    636: 
                    637: /**
                    638:  * Parse AH proposal
                    639:  */
                    640: CALLBACK(parse_ah_proposal, bool,
                    641:        linked_list_t *out, chunk_t v)
                    642: {
                    643:        return parse_proposal(out, PROTO_AH, v);
                    644: }
                    645: 
                    646: /**
                    647:  * Parse a traffic selector
                    648:  */
                    649: CALLBACK(parse_ts, bool,
                    650:        linked_list_t *out, chunk_t v)
                    651: {
                    652:        char buf[BUF_LEN], *protoport, *sep, *port = "", *end;
                    653:        traffic_selector_t *ts = NULL;
                    654:        struct protoent *protoent;
                    655:        struct servent *svc;
                    656:        long int p;
                    657:        uint16_t from = 0, to = 0xffff;
                    658:        uint8_t proto = 0;
                    659: 
                    660:        if (!vici_stringify(v, buf, sizeof(buf)))
                    661:        {
                    662:                return FALSE;
                    663:        }
                    664: 
                    665:        protoport = strchr(buf, '[');
                    666:        if (protoport)
                    667:        {
                    668:                *(protoport++) = '\0';
                    669: 
                    670:                sep = strrchr(protoport, ']');
                    671:                if (!sep)
                    672:                {
                    673:                        return FALSE;
                    674:                }
                    675:                *sep = '\0';
                    676: 
                    677:                sep = strchr(protoport, '/');
                    678:                if (sep)
                    679:                {       /* protocol/port */
                    680:                        *sep = '\0';
                    681:                        port = sep + 1;
                    682:                }
                    683: 
                    684:                if (streq(protoport, "any"))
                    685:                {
                    686:                        proto = 0;
                    687:                }
                    688:                else
                    689:                {
                    690:                        protoent = getprotobyname(protoport);
                    691:                        if (protoent)
                    692:                        {
                    693:                                proto = protoent->p_proto;
                    694:                        }
                    695:                        else
                    696:                        {
                    697:                                p = strtol(protoport, &end, 0);
                    698:                                if ((*protoport && *end) || p < 0 || p > 0xff)
                    699:                                {
                    700:                                        return FALSE;
                    701:                                }
                    702:                                proto = (uint8_t)p;
                    703:                        }
                    704:                }
                    705:                if (streq(port, "opaque"))
                    706:                {
                    707:                        from = 0xffff;
                    708:                        to = 0;
                    709:                }
                    710:                else if (*port && !streq(port, "any"))
                    711:                {
                    712:                        svc = getservbyname(port, NULL);
                    713:                        if (svc)
                    714:                        {
                    715:                                from = to = ntohs(svc->s_port);
                    716:                        }
                    717:                        else
                    718:                        {
                    719:                                p = strtol(port, &end, 0);
                    720:                                if (p < 0 || p > 0xffff)
                    721:                                {
                    722:                                        return FALSE;
                    723:                                }
                    724:                                from = p;
                    725:                                if (*end == '-')
                    726:                                {
                    727:                                        port = end + 1;
                    728:                                        p = strtol(port, &end, 0);
                    729:                                        if (p < 0 || p > 0xffff)
                    730:                                        {
                    731:                                                return FALSE;
                    732:                                        }
                    733:                                }
                    734:                                to = p;
                    735:                                if (*end)
                    736:                                {
                    737:                                        return FALSE;
                    738:                                }
                    739:                        }
                    740:                }
                    741:        }
                    742:        if (streq(buf, "dynamic"))
                    743:        {
                    744:                ts = traffic_selector_create_dynamic(proto, from, to);
                    745:        }
                    746:        else if (strchr(buf, '-'))
                    747:        {
                    748:                host_t *lower, *upper;
                    749:                ts_type_t type;
                    750: 
                    751:                if (host_create_from_range(buf, &lower, &upper))
                    752:                {
                    753:                        type = (lower->get_family(lower) == AF_INET) ?
                    754:                                                                TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
                    755:                        ts = traffic_selector_create_from_bytes(proto, type,
                    756:                                                                lower->get_address(lower), from,
                    757:                                                                upper->get_address(upper), to);
                    758:                        lower->destroy(lower);
                    759:                        upper->destroy(upper);
                    760:                }
                    761:        }
                    762:        else
                    763:        {
                    764:                ts = traffic_selector_create_from_cidr(buf, proto, from, to);
                    765:        }
                    766:        if (!ts)
                    767:        {
                    768:                return FALSE;
                    769:        }
                    770:        out->insert_last(out, ts);
                    771:        return TRUE;
                    772: }
                    773: 
                    774: /**
                    775:  * Parse a string
                    776:  */
                    777: CALLBACK(parse_string, bool,
                    778:        char **out, chunk_t v)
                    779: {
                    780:        if (!chunk_printable(v, NULL, ' '))
                    781:        {
                    782:                return FALSE;
                    783:        }
                    784:        free(*out);
                    785:        *out = NULL;
                    786:        if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
                    787:        {
                    788:                return FALSE;
                    789:        }
                    790:        return TRUE;
                    791: }
                    792: 
                    793: /**
                    794:  * Map a string to an integer
                    795:  */
                    796: typedef struct {
                    797:        char *str;
                    798:        int d;
                    799: } enum_map_t;
                    800: 
                    801: /**
                    802:  * Parse a string to an integer mapping
                    803:  */
                    804: static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
                    805: {
                    806:        char buf[BUF_LEN];
                    807:        int i;
                    808: 
                    809:        if (!vici_stringify(v, buf, sizeof(buf)))
                    810:        {
                    811:                return FALSE;
                    812:        }
                    813:        for (i = 0; i < count; i++)
                    814:        {
                    815:                if (strcaseeq(map[i].str, buf))
                    816:                {
                    817:                        *out = map[i].d;
                    818:                        return TRUE;
                    819:                }
                    820:        }
                    821:        return FALSE;
                    822: }
                    823: 
                    824: /**
                    825:  * Parse a boolean
                    826:  */
                    827: CALLBACK(parse_bool, bool,
                    828:        bool *out, chunk_t v)
                    829: {
                    830:        enum_map_t map[] = {
                    831:                { "yes",                TRUE    },
                    832:                { "true",               TRUE    },
                    833:                { "enabled",    TRUE    },
                    834:                { "1",                  TRUE    },
                    835:                { "no",                 FALSE   },
                    836:                { "false",              FALSE   },
                    837:                { "disabled",   FALSE   },
                    838:                { "0",                  FALSE   },
                    839:        };
                    840:        int d;
                    841: 
                    842:        if (parse_map(map, countof(map), &d, v))
                    843:        {
                    844:                *out = d;
                    845:                return TRUE;
                    846:        }
                    847:        return FALSE;
                    848: }
                    849: 
                    850: /**
                    851:  * Parse a ipsec_mode_t
                    852:  */
                    853: CALLBACK(parse_mode, bool,
                    854:        child_cfg_create_t *cfg, chunk_t v)
                    855: {
                    856:        enum_map_t map[] = {
                    857:                { "tunnel",                             MODE_TUNNEL             },
                    858:                { "transport",                  MODE_TRANSPORT  },
                    859:                { "transport_proxy",    MODE_TRANSPORT  },
                    860:                { "beet",                               MODE_BEET               },
                    861:                { "drop",                               MODE_DROP               },
                    862:                { "pass",                               MODE_PASS               },
                    863:        };
                    864:        int d;
                    865: 
                    866:        if (parse_map(map, countof(map), &d, v))
                    867:        {
                    868:                cfg->mode = d;
                    869:                if ((d == MODE_TRANSPORT) && (v.len > 9))
                    870:                {
                    871:                        cfg->options |= OPT_PROXY_MODE;
                    872:                }
                    873:                return TRUE;
                    874:        }
                    875:        return FALSE;
                    876: }
                    877: 
                    878: /**
                    879:  * Enable a child_cfg_option_t, the flag controls whether the option is enabled
                    880:  * if the parsed value is TRUE or FALSE.
                    881:  */
                    882: static bool parse_option(child_cfg_option_t *out, child_cfg_option_t opt,
                    883:                                                 chunk_t v, bool add_if_true)
                    884: {
                    885:        bool val;
                    886: 
                    887:        if (parse_bool(&val, v))
                    888:        {
                    889:                if (val == add_if_true)
                    890:                {
                    891:                        *out |= opt;
                    892:                }
                    893:                return TRUE;
                    894:        }
                    895:        return FALSE;
                    896: }
                    897: 
                    898: /**
                    899:  * Parse OPT_HOSTACCESS option
                    900:  */
                    901: CALLBACK(parse_opt_haccess, bool,
                    902:        child_cfg_option_t *out, chunk_t v)
                    903: {
                    904:        return parse_option(out, OPT_HOSTACCESS, v, TRUE);
                    905: }
                    906: 
                    907: /**
                    908:  * Parse OPT_NO_POLICIES option
                    909:  */
                    910: CALLBACK(parse_opt_policies, bool,
                    911:        child_cfg_option_t *out, chunk_t v)
                    912: {
                    913:        return parse_option(out, OPT_NO_POLICIES, v, FALSE);
                    914: }
                    915: 
                    916: /**
                    917:  * Parse OPT_FWD_OUT_POLICIES option
                    918:  */
                    919: CALLBACK(parse_opt_fwd_out, bool,
                    920:        child_cfg_option_t *out, chunk_t v)
                    921: {
                    922:        return parse_option(out, OPT_FWD_OUT_POLICIES, v, TRUE);
                    923: }
                    924: 
                    925: /**
                    926:  * Parse OPT_IPCOMP option
                    927:  */
                    928: CALLBACK(parse_opt_ipcomp, bool,
                    929:        child_cfg_option_t *out, chunk_t v)
                    930: {
                    931:        return parse_option(out, OPT_IPCOMP, v, TRUE);
                    932: }
                    933: 
                    934: /**
                    935:  * Parse OPT_SHA256_96 option
                    936:  */
                    937: CALLBACK(parse_opt_sha256_96, bool,
                    938:        child_cfg_option_t *out, chunk_t v)
                    939: {
                    940:        return parse_option(out, OPT_SHA256_96, v, TRUE);
                    941: }
                    942: 
                    943: /**
                    944:  * Parse OPT_MARK_IN_SA option
                    945:  */
                    946: CALLBACK(parse_opt_mark_in, bool,
                    947:        child_cfg_option_t *out, chunk_t v)
                    948: {
                    949:        return parse_option(out, OPT_MARK_IN_SA, v, TRUE);
                    950: }
                    951: 
                    952: /**
                    953:  * Parse OPT_NO_COPY_DF option
                    954:  */
                    955: CALLBACK(parse_opt_copy_df, bool,
                    956:        child_cfg_option_t *out, chunk_t v)
                    957: {
                    958:        return parse_option(out, OPT_NO_COPY_DF, v, FALSE);
                    959: }
                    960: 
                    961: /**
                    962:  * Parse OPT_NO_COPY_ECN option
                    963:  */
                    964: CALLBACK(parse_opt_copy_ecn, bool,
                    965:        child_cfg_option_t *out, chunk_t v)
                    966: {
                    967:        return parse_option(out, OPT_NO_COPY_ECN, v, FALSE);
                    968: }
                    969: 
                    970: /**
                    971:  * Parse a dscp_copy_t
                    972:  */
                    973: CALLBACK(parse_copy_dscp, bool,
                    974:        dscp_copy_t *out, chunk_t v)
                    975: {
                    976:        enum_map_t map[] = {
                    977:                { "no",         DSCP_COPY_NO            },
                    978:                { "in",         DSCP_COPY_IN_ONLY       },
                    979:                { "out",        DSCP_COPY_OUT_ONLY      },
                    980:                { "yes",        DSCP_COPY_YES           },
                    981:        };
                    982:        int d;
                    983: 
                    984:        if (parse_map(map, countof(map), &d, v))
                    985:        {
                    986:                *out = d;
                    987:                return TRUE;
                    988:        }
                    989:        return FALSE;
                    990: }
                    991: 
                    992: /**
                    993:  * Parse an action_t
                    994:  */
                    995: CALLBACK(parse_action, bool,
                    996:        action_t *out, chunk_t v)
                    997: {
                    998:        enum_map_t map[] = {
                    999:                { "start",              ACTION_RESTART  },
                   1000:                { "restart",    ACTION_RESTART  },
                   1001:                { "route",              ACTION_ROUTE    },
                   1002:                { "trap",               ACTION_ROUTE    },
                   1003:                { "none",               ACTION_NONE             },
                   1004:                { "clear",              ACTION_NONE             },
                   1005:        };
                   1006:        int d;
                   1007: 
                   1008:        if (parse_map(map, countof(map), &d, v))
                   1009:        {
                   1010:                *out = d;
                   1011:                return TRUE;
                   1012:        }
                   1013:        return FALSE;
                   1014: }
                   1015: 
                   1016: /**
                   1017:  * Parse an hw_offload_t
                   1018:  */
                   1019: CALLBACK(parse_hw_offload, bool,
                   1020:        action_t *out, chunk_t v)
                   1021: {
                   1022:        enum_map_t map[] = {
                   1023:                { "no",         HW_OFFLOAD_NO   },
                   1024:                { "yes",        HW_OFFLOAD_YES  },
                   1025:                { "auto",       HW_OFFLOAD_AUTO },
                   1026:        };
                   1027:        int d;
                   1028: 
                   1029:        if (parse_map(map, countof(map), &d, v))
                   1030:        {
                   1031:                *out = d;
                   1032:                return TRUE;
                   1033:        }
                   1034:        return FALSE;
                   1035: }
                   1036: 
                   1037: /**
                   1038:  * Parse a uint32_t with the given base
                   1039:  */
                   1040: static bool parse_uint32_base(uint32_t *out, chunk_t v, int base)
                   1041: {
                   1042:        char buf[16], *end;
                   1043:        u_long l;
                   1044: 
                   1045:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1046:        {
                   1047:                return FALSE;
                   1048:        }
                   1049:        l = strtoul(buf, &end, base);
                   1050:        if (*end == 0)
                   1051:        {
                   1052:                *out = l;
                   1053:                return TRUE;
                   1054:        }
                   1055:        return FALSE;
                   1056: }
                   1057: 
                   1058: /**
                   1059:  * Parse a uint32_t
                   1060:  */
                   1061: CALLBACK(parse_uint32, bool,
                   1062:        uint32_t *out, chunk_t v)
                   1063: {
                   1064:        return parse_uint32_base(out, v, 0);
                   1065: }
                   1066: 
                   1067: /**
                   1068:  * Parse a uint32_t in binary encoding
                   1069:  */
                   1070: CALLBACK(parse_uint32_bin, bool,
                   1071:        uint32_t *out, chunk_t v)
                   1072: {
                   1073:        return parse_uint32_base(out, v, 2);
                   1074: }
                   1075: 
                   1076: /**
                   1077:  * Parse a uint64_t
                   1078:  */
                   1079: CALLBACK(parse_uint64, bool,
                   1080:        uint64_t *out, chunk_t v)
                   1081: {
                   1082:        char buf[16], *end;
                   1083:        unsigned long long l;
                   1084: 
                   1085:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1086:        {
                   1087:                return FALSE;
                   1088:        }
                   1089:        l = strtoull(buf, &end, 0);
                   1090:        if (*end == 0)
                   1091:        {
                   1092:                *out = l;
                   1093:                return TRUE;
                   1094:        }
                   1095:        return FALSE;
                   1096: }
                   1097: 
                   1098: /**
                   1099:  * Parse a relative time
                   1100:  */
                   1101: CALLBACK(parse_time, bool,
                   1102:        uint64_t *out, chunk_t v)
                   1103: {
                   1104:        char buf[16], *end;
                   1105:        u_long l;
                   1106: 
                   1107:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1108:        {
                   1109:                return FALSE;
                   1110:        }
                   1111: 
                   1112:        l = strtoul(buf, &end, 0);
                   1113:        while (*end == ' ')
                   1114:        {
                   1115:                end++;
                   1116:        }
                   1117:        switch (*end)
                   1118:        {
                   1119:                case 'd':
                   1120:                case 'D':
                   1121:                        l *= 24;
                   1122:                        /* fall */
                   1123:                case 'h':
                   1124:                case 'H':
                   1125:                        l *= 60;
                   1126:                        /* fall */
                   1127:                case 'm':
                   1128:                case 'M':
                   1129:                        l *= 60;
                   1130:                        /* fall */
                   1131:                case 's':
                   1132:                case 'S':
                   1133:                        end++;
                   1134:                        break;
                   1135:                case '\0':
                   1136:                        break;
                   1137:                default:
                   1138:                        return FALSE;
                   1139:        }
                   1140:        if (*end)
                   1141:        {
                   1142:                return FALSE;
                   1143:        }
                   1144:        *out = l;
                   1145:        return TRUE;
                   1146: }
                   1147: 
                   1148: /**
                   1149:  * Parse a relative time (32-bit)
                   1150:  */
                   1151: CALLBACK(parse_time32, bool,
                   1152:        uint32_t *out, chunk_t v)
                   1153: {
                   1154:        uint64_t time;
                   1155: 
                   1156:        if (parse_time(&time, v))
                   1157:        {
                   1158:                *out = time;
                   1159:                return TRUE;
                   1160:        }
                   1161:        return FALSE;
                   1162: }
                   1163: 
                   1164: /**
                   1165:  * Parse byte volume
                   1166:  */
                   1167: CALLBACK(parse_bytes, bool,
                   1168:        uint64_t *out, chunk_t v)
                   1169: {
                   1170:        char buf[16], *end;
                   1171:        unsigned long long l;
                   1172: 
                   1173:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1174:        {
                   1175:                return FALSE;
                   1176:        }
                   1177: 
                   1178:        l = strtoull(buf, &end, 0);
                   1179:        while (*end == ' ')
                   1180:        {
                   1181:                end++;
                   1182:        }
                   1183:        switch (*end)
                   1184:        {
                   1185:                case 'g':
                   1186:                case 'G':
                   1187:                        l *= 1024;
                   1188:                        /* fall */
                   1189:                case 'm':
                   1190:                case 'M':
                   1191:                        l *= 1024;
                   1192:                        /* fall */
                   1193:                case 'k':
                   1194:                case 'K':
                   1195:                        l *= 1024;
                   1196:                        end++;
                   1197:                        break;
                   1198:                case '\0':
                   1199:                        break;
                   1200:                default:
                   1201:                        return FALSE;
                   1202:        }
                   1203:        if (*end)
                   1204:        {
                   1205:                return FALSE;
                   1206:        }
                   1207:        *out = l;
                   1208:        return TRUE;
                   1209: }
                   1210: 
                   1211: /**
                   1212:  * Parse a mark_t
                   1213:  */
                   1214: CALLBACK(parse_mark, bool,
                   1215:        mark_t *out, chunk_t v)
                   1216: {
                   1217:        char buf[32];
                   1218: 
                   1219:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1220:        {
                   1221:                return FALSE;
                   1222:        }
                   1223:        return mark_from_string(buf, MARK_OP_UNIQUE, out);
                   1224: }
                   1225: 
                   1226: /**
                   1227:  * Parse a mark_t when using it as set_mark.
                   1228:  */
                   1229: CALLBACK(parse_set_mark, bool,
                   1230:        mark_t *out, chunk_t v)
                   1231: {
                   1232:        char buf[32];
                   1233: 
                   1234:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1235:        {
                   1236:                return FALSE;
                   1237:        }
                   1238:        return mark_from_string(buf, MARK_OP_SAME, out);
                   1239: }
                   1240: 
                   1241: /**
                   1242:  * Parse interface ID
                   1243:  */
                   1244: CALLBACK(parse_if_id, bool,
                   1245:        uint32_t *out, chunk_t v)
                   1246: {
                   1247:        char buf[32];
                   1248: 
                   1249:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1250:        {
                   1251:                return FALSE;
                   1252:        }
                   1253:        return if_id_from_string(buf, out);
                   1254: }
                   1255: 
                   1256: /**
                   1257:  * Parse TFC padding option
                   1258:  */
                   1259: CALLBACK(parse_tfc, bool,
                   1260:        uint32_t *out, chunk_t v)
                   1261: {
                   1262:        if (chunk_equals(v, chunk_from_str("mtu")))
                   1263:        {
                   1264:                *out = -1;
                   1265:                return TRUE;
                   1266:        }
                   1267:        return parse_uint32(out, v);
                   1268: }
                   1269: 
                   1270: /**
                   1271:  * Parse 6-bit DSCP value
                   1272:  */
                   1273: CALLBACK(parse_dscp, bool,
                   1274:        uint8_t *out, chunk_t v)
                   1275: {
                   1276:        if (parse_uint32_bin(out, v))
                   1277:        {
                   1278:                *out = *out & 0x3f;
                   1279:                return TRUE;
                   1280:        }
                   1281:        return FALSE;
                   1282: }
                   1283: 
                   1284: /**
                   1285:  * Parse authentication config
                   1286:  */
                   1287: CALLBACK(parse_auth, bool,
                   1288:        auth_cfg_t *cfg, chunk_t v)
                   1289: {
                   1290:        char buf[64], *pos;
                   1291:        eap_vendor_type_t *type;
                   1292: 
                   1293:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1294:        {
                   1295:                return FALSE;
                   1296:        }
                   1297:        if (strpfx(buf, "ike:") ||
                   1298:                strpfx(buf, "pubkey") ||
                   1299:                strpfx(buf, "rsa") ||
                   1300:                strpfx(buf, "ecdsa") ||
                   1301:                strpfx(buf, "bliss"))
                   1302:        {
                   1303:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
                   1304:                cfg->add_pubkey_constraints(cfg, buf, TRUE);
                   1305:                return TRUE;
                   1306:        }
                   1307:        if (strcaseeq(buf, "psk"))
                   1308:        {
                   1309:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
                   1310:                return TRUE;
                   1311:        }
                   1312:        if (strcasepfx(buf, "xauth"))
                   1313:        {
                   1314:                pos = strchr(buf, '-');
                   1315:                if (pos)
                   1316:                {
                   1317:                        cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
                   1318:                }
                   1319:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
                   1320:                return TRUE;
                   1321:        }
                   1322:        if (strcasepfx(buf, "eap"))
                   1323:        {
                   1324:                char *pos;
                   1325: 
                   1326:                cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
                   1327: 
                   1328:                pos = strchr(buf, ':');
                   1329:                if (pos)
                   1330:                {
                   1331:                        *pos = 0;
                   1332:                        cfg->add_pubkey_constraints(cfg, pos + 1, FALSE);
                   1333:                }
                   1334:                type = eap_vendor_type_from_string(buf);
                   1335:                if (type)
                   1336:                {
                   1337:                        cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
                   1338:                        if (type->vendor)
                   1339:                        {
                   1340:                                cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
                   1341:                        }
                   1342:                        free(type);
                   1343:                }
                   1344:                return TRUE;
                   1345:        }
                   1346:        return FALSE;
                   1347: }
                   1348: 
                   1349: /**
                   1350:  * Parse identity; add as auth rule to config
                   1351:  */
                   1352: static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
                   1353: {
                   1354:        char buf[BUF_LEN];
                   1355: 
                   1356:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1357:        {
                   1358:                return FALSE;
                   1359:        }
                   1360:        cfg->add(cfg, rule, identification_create_from_string(buf));
                   1361:        return TRUE;
                   1362: }
                   1363: 
                   1364: /**
                   1365:  * Parse IKE identity
                   1366:  */
                   1367: CALLBACK(parse_ike_id, bool,
                   1368:        auth_cfg_t *cfg, chunk_t v)
                   1369: {
                   1370:        return parse_id(cfg, AUTH_RULE_IDENTITY, v);
                   1371: }
                   1372: 
                   1373: /**
                   1374:  * Parse CA identity constraint
                   1375:  */
                   1376: CALLBACK(parse_ca_id, bool,
                   1377:        auth_cfg_t *cfg, chunk_t v)
                   1378: {
                   1379:        return parse_id(cfg, AUTH_RULE_CA_IDENTITY, v);
                   1380: }
                   1381: 
                   1382: /**
                   1383:  * Parse AAA identity
                   1384:  */
                   1385: CALLBACK(parse_aaa_id, bool,
                   1386:        auth_cfg_t *cfg, chunk_t v)
                   1387: {
                   1388:        return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
                   1389: }
                   1390: 
                   1391: /**
                   1392:  * Parse EAP identity
                   1393:  */
                   1394: CALLBACK(parse_eap_id, bool,
                   1395:        auth_cfg_t *cfg, chunk_t v)
                   1396: {
                   1397:        return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
                   1398: }
                   1399: 
                   1400: /**
                   1401:  * Parse XAuth identity
                   1402:  */
                   1403: CALLBACK(parse_xauth_id, bool,
                   1404:        auth_cfg_t *cfg, chunk_t v)
                   1405: {
                   1406:        return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
                   1407: }
                   1408: 
                   1409: /**
                   1410:  * Parse group membership
                   1411:  */
                   1412: CALLBACK(parse_group, bool,
                   1413:        auth_cfg_t *cfg, chunk_t v)
                   1414: {
                   1415:        return parse_id(cfg, AUTH_RULE_GROUP, v);
                   1416: }
                   1417: 
                   1418: /**
                   1419:  * Parse certificate policy
                   1420:  */
                   1421: CALLBACK(parse_cert_policy, bool,
                   1422:        auth_cfg_t *cfg, chunk_t v)
                   1423: {
                   1424:        char buf[BUF_LEN];
                   1425: 
                   1426:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1427:        {
                   1428:                return FALSE;
                   1429:        }
                   1430:        cfg->add(cfg, AUTH_RULE_CERT_POLICY, strdup(buf));
                   1431:        return TRUE;
                   1432: }
                   1433: 
                   1434: /**
                   1435:  * Add a certificate as auth rule to config
                   1436:  */
                   1437: static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert)
                   1438: {
                   1439:        vici_cred_t *cred;
                   1440: 
                   1441:        cred = auth->request->this->cred;
                   1442:        cert = cred->add_cert(cred, cert);
                   1443:        auth->cfg->add(auth->cfg, rule, cert);
                   1444:        return TRUE;
                   1445: }
                   1446: 
                   1447: /**
                   1448:  * Parse a certificate; add as auth rule to config
                   1449:  */
                   1450: static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
                   1451: {
                   1452:        certificate_t *cert;
                   1453: 
                   1454:        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                   1455:                                                          BUILD_BLOB_PEM, v, BUILD_END);
                   1456:        if (cert)
                   1457:        {
                   1458:                return add_cert(auth, rule, cert);
                   1459:        }
                   1460:        return FALSE;
                   1461: }
                   1462: 
                   1463: /**
                   1464:  * Parse subject certificates
                   1465:  */
                   1466: CALLBACK(parse_certs, bool,
                   1467:        auth_data_t *auth, chunk_t v)
                   1468: {
                   1469:        return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v);
                   1470: }
                   1471: 
                   1472: /**
                   1473:  * Parse CA certificates
                   1474:  */
                   1475: CALLBACK(parse_cacerts, bool,
                   1476:        auth_data_t *auth, chunk_t v)
                   1477: {
                   1478:        return parse_cert(auth, AUTH_RULE_CA_CERT, v);
                   1479: }
                   1480: 
                   1481: /**
                   1482:  * Parse raw public keys
                   1483:  */
                   1484: CALLBACK(parse_pubkeys, bool,
                   1485:        auth_data_t *auth, chunk_t v)
                   1486: {
                   1487:        vici_cred_t *cred;
                   1488:        certificate_t *cert;
                   1489: 
                   1490:        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
                   1491:                                                          BUILD_BLOB_PEM, v, BUILD_END);
                   1492:        if (cert)
                   1493:        {
                   1494:                cred = auth->request->this->cred;
                   1495:                cert = cred->add_cert(cred, cert);
                   1496:                auth->cfg->add(auth->cfg, AUTH_RULE_SUBJECT_CERT, cert);
                   1497:                return TRUE;
                   1498:        }
                   1499:        return FALSE;
                   1500: }
                   1501: 
                   1502: /**
                   1503:  * Parse revocation status
                   1504:  */
                   1505: CALLBACK(parse_revocation, bool,
                   1506:        auth_cfg_t *cfg, chunk_t v)
                   1507: {
                   1508:        enum_map_t map[] = {
                   1509:                { "strict",             VALIDATION_GOOD         },
                   1510:                { "ifuri",              VALIDATION_SKIPPED      },
                   1511:                { "relaxed",    VALIDATION_FAILED       },
                   1512:        };
                   1513:        int d;
                   1514: 
                   1515:        if (parse_map(map, countof(map), &d, v))
                   1516:        {
                   1517:                if (d != VALIDATION_FAILED)
                   1518:                {
                   1519:                        cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
                   1520:                }
                   1521:                return TRUE;
                   1522:        }
                   1523:        return FALSE;
                   1524: }
                   1525: 
                   1526: /**
                   1527:  * Parse list items to comma separated strings
                   1528:  */
                   1529: CALLBACK(parse_stringlist, bool,
                   1530:        char **out, chunk_t v)
                   1531: {
                   1532:        char *current;
                   1533: 
                   1534:        if (!chunk_printable(v, NULL, ' '))
                   1535:        {
                   1536:                return FALSE;
                   1537:        }
                   1538:        current = *out;
                   1539:        if (current)
                   1540:        {
                   1541:                if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
                   1542:                {
                   1543:                        return FALSE;
                   1544:                }
                   1545:                free(current);
                   1546:        }
                   1547:        else
                   1548:        {
                   1549:                if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
                   1550:                {
                   1551:                        return FALSE;
                   1552:                }
                   1553:        }
                   1554:        return TRUE;
                   1555: }
                   1556: 
                   1557: /**
                   1558:  * Parse an fragmentation_t
                   1559:  */
                   1560: CALLBACK(parse_frag, bool,
                   1561:        fragmentation_t *out, chunk_t v)
                   1562: {
                   1563:        enum_map_t map[] = {
                   1564:                { "yes",                FRAGMENTATION_YES               },
                   1565:                { "accept",             FRAGMENTATION_ACCEPT    },
                   1566:                { "no",                 FRAGMENTATION_NO                },
                   1567:                { "force",              FRAGMENTATION_FORCE             },
                   1568:        };
                   1569:        int d;
                   1570: 
                   1571:        if (parse_map(map, countof(map), &d, v))
                   1572:        {
                   1573:                *out = d;
                   1574:                return TRUE;
                   1575:        }
                   1576:        return FALSE;
                   1577: }
                   1578: 
                   1579: /**
                   1580:  * Parse a childless_t
                   1581:  */
                   1582: CALLBACK(parse_childless, bool,
                   1583:        childless_t *out, chunk_t v)
                   1584: {
                   1585:        enum_map_t map[] = {
                   1586:                { "allow",              CHILDLESS_ALLOW         },
                   1587:                { "never",              CHILDLESS_NEVER         },
                   1588:                { "force",              CHILDLESS_FORCE         },
                   1589:        };
                   1590:        int d;
                   1591: 
                   1592:        if (parse_map(map, countof(map), &d, v))
                   1593:        {
                   1594:                *out = d;
                   1595:                return TRUE;
                   1596:        }
                   1597:        return FALSE;
                   1598: }
                   1599: 
                   1600: /**
                   1601:  * Parse a cert_policy_t
                   1602:  */
                   1603: CALLBACK(parse_send_cert, bool,
                   1604:        cert_policy_t *out, chunk_t v)
                   1605: {
                   1606:        enum_map_t map[] = {
                   1607:                { "ifasked",    CERT_SEND_IF_ASKED      },
                   1608:                { "always",             CERT_ALWAYS_SEND        },
                   1609:                { "never",              CERT_NEVER_SEND         },
                   1610:        };
                   1611:        int d;
                   1612: 
                   1613:        if (parse_map(map, countof(map), &d, v))
                   1614:        {
                   1615:                *out = d;
                   1616:                return TRUE;
                   1617:        }
                   1618:        return FALSE;
                   1619: }
                   1620: 
                   1621: /**
                   1622:  * Parse a unique_policy_t
                   1623:  */
                   1624: CALLBACK(parse_unique, bool,
                   1625:        unique_policy_t *out, chunk_t v)
                   1626: {
                   1627:        enum_map_t map[] = {
                   1628:                { "never",              UNIQUE_NEVER            },
                   1629:                { "no",                 UNIQUE_NO                       },
                   1630:                { "replace",    UNIQUE_REPLACE          },
                   1631:                { "keep",               UNIQUE_KEEP                     },
                   1632:        };
                   1633:        int d;
                   1634: 
                   1635:        if (parse_map(map, countof(map), &d, v))
                   1636:        {
                   1637:                *out = d;
                   1638:                return TRUE;
                   1639:        }
                   1640:        return FALSE;
                   1641: }
                   1642: 
                   1643: /**
                   1644:  * Parse host_t into a list
                   1645:  */
                   1646: CALLBACK(parse_hosts, bool,
                   1647:        linked_list_t *list, chunk_t v)
                   1648: {
                   1649:        char buf[64];
                   1650:        host_t *host;
                   1651: 
                   1652:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1653:        {
                   1654:                return FALSE;
                   1655:        }
                   1656:        host = host_create_from_string(buf, 0);
                   1657:        if (!host)
                   1658:        {
                   1659:                return FALSE;
                   1660:        }
                   1661:        list->insert_last(list, host);
                   1662:        return TRUE;
                   1663: }
                   1664: 
                   1665: /**
                   1666:  * Parse peer/ppk ID
                   1667:  */
                   1668: CALLBACK(parse_peer_id, bool,
                   1669:        identification_t **out, chunk_t v)
                   1670: {
                   1671:        char buf[BUF_LEN];
                   1672: 
                   1673:        if (!vici_stringify(v, buf, sizeof(buf)))
                   1674:        {
                   1675:                return FALSE;
                   1676:        }
                   1677:        *out = identification_create_from_string(buf);
                   1678:        return TRUE;
                   1679: }
                   1680: 
                   1681: 
                   1682: CALLBACK(cert_kv, bool,
                   1683:        cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
                   1684: {
                   1685:        parse_rule_t rules[] = {
                   1686:                { "handle",                     parse_string,           &cert->handle                           },
                   1687:                { "slot",                       parse_uint32,           &cert->slot                                     },
                   1688:                { "module",                     parse_string,           &cert->module                           },
                   1689:                { "file",                       parse_string,           &cert->file                                     },
                   1690:        };
                   1691: 
                   1692:        return parse_rules(rules, countof(rules), name, value,
                   1693:                                           &cert->request->reply);
                   1694: }
                   1695: 
                   1696: CALLBACK(child_li, bool,
                   1697:        child_data_t *child, vici_message_t *message, char *name, chunk_t value)
                   1698: {
                   1699:        parse_rule_t rules[] = {
                   1700:                { "ah_proposals",       parse_ah_proposal,      child->proposals                        },
                   1701:                { "esp_proposals",      parse_esp_proposal,     child->proposals                        },
                   1702:                { "local_ts",           parse_ts,                       child->local_ts                         },
                   1703:                { "remote_ts",          parse_ts,                       child->remote_ts                        },
                   1704:        };
                   1705: 
                   1706:        return parse_rules(rules, countof(rules), name, value,
                   1707:                                           &child->request->reply);
                   1708: }
                   1709: 
                   1710: CALLBACK(child_kv, bool,
                   1711:        child_data_t *child, vici_message_t *message, char *name, chunk_t value)
                   1712: {
                   1713:        parse_rule_t rules[] = {
                   1714:                { "updown",                             parse_string,           &child->cfg.updown                                      },
                   1715:                { "hostaccess",                 parse_opt_haccess,      &child->cfg.options                                     },
                   1716:                { "mode",                               parse_mode,                     &child->cfg                                                     },
                   1717:                { "policies",                   parse_opt_policies,     &child->cfg.options                                     },
                   1718:                { "policies_fwd_out",   parse_opt_fwd_out,      &child->cfg.options                                     },
                   1719:                { "replay_window",              parse_uint32,           &child->replay_window                           },
                   1720:                { "rekey_time",                 parse_time,                     &child->cfg.lifetime.time.rekey         },
                   1721:                { "life_time",                  parse_time,                     &child->cfg.lifetime.time.life          },
                   1722:                { "rand_time",                  parse_time,                     &child->cfg.lifetime.time.jitter        },
                   1723:                { "rekey_bytes",                parse_bytes,            &child->cfg.lifetime.bytes.rekey        },
                   1724:                { "life_bytes",                 parse_bytes,            &child->cfg.lifetime.bytes.life         },
                   1725:                { "rand_bytes",                 parse_bytes,            &child->cfg.lifetime.bytes.jitter       },
                   1726:                { "rekey_packets",              parse_uint64,           &child->cfg.lifetime.packets.rekey      },
                   1727:                { "life_packets",               parse_uint64,           &child->cfg.lifetime.packets.life       },
                   1728:                { "rand_packets",               parse_uint64,           &child->cfg.lifetime.packets.jitter     },
                   1729:                { "dpd_action",                 parse_action,           &child->cfg.dpd_action                          },
                   1730:                { "start_action",               parse_action,           &child->cfg.start_action                        },
                   1731:                { "close_action",               parse_action,           &child->cfg.close_action                        },
                   1732:                { "ipcomp",                             parse_opt_ipcomp,       &child->cfg.options                                     },
                   1733:                { "inactivity",                 parse_time32,           &child->cfg.inactivity                          },
                   1734:                { "reqid",                              parse_uint32,           &child->cfg.reqid                                       },
                   1735:                { "mark_in",                    parse_mark,                     &child->cfg.mark_in                                     },
                   1736:                { "mark_in_sa",                 parse_opt_mark_in,      &child->cfg.options                                     },
                   1737:                { "mark_out",                   parse_mark,                     &child->cfg.mark_out                            },
                   1738:                { "set_mark_in",                parse_set_mark,         &child->cfg.set_mark_in                         },
                   1739:                { "set_mark_out",               parse_set_mark,         &child->cfg.set_mark_out                        },
                   1740:                { "tfc_padding",                parse_tfc,                      &child->cfg.tfc                                         },
                   1741:                { "priority",                   parse_uint32,           &child->cfg.priority                            },
                   1742:                { "interface",                  parse_string,           &child->cfg.interface                           },
                   1743:                { "hw_offload",                 parse_hw_offload,       &child->cfg.hw_offload                          },
                   1744:                { "sha256_96",                  parse_opt_sha256_96,&child->cfg.options                                 },
                   1745:                { "copy_df",                    parse_opt_copy_df,      &child->cfg.options                                     },
                   1746:                { "copy_ecn",                   parse_opt_copy_ecn,     &child->cfg.options                                     },
                   1747:                { "copy_dscp",                  parse_copy_dscp,        &child->cfg.copy_dscp                           },
                   1748:                { "if_id_in",                   parse_if_id,            &child->cfg.if_id_in                            },
                   1749:                { "if_id_out",                  parse_if_id,            &child->cfg.if_id_out                           },
                   1750:        };
                   1751: 
                   1752:        return parse_rules(rules, countof(rules), name, value,
                   1753:                                           &child->request->reply);
                   1754: }
                   1755: 
                   1756: CALLBACK(auth_li, bool,
                   1757:        auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
                   1758: {
                   1759:        parse_rule_t rules[] = {
                   1760:                { "groups",                     parse_group,            auth->cfg                                       },
                   1761:                { "cert_policy",        parse_cert_policy,      auth->cfg                                       },
                   1762:                { "certs",                      parse_certs,            auth                                            },
                   1763:                { "cacerts",            parse_cacerts,          auth                                            },
                   1764:                { "pubkeys",            parse_pubkeys,          auth                                            },
                   1765:        };
                   1766: 
                   1767:        return parse_rules(rules, countof(rules), name, value,
                   1768:                                           &auth->request->reply);
                   1769: }
                   1770: 
                   1771: CALLBACK(auth_kv, bool,
                   1772:        auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
                   1773: {
                   1774:        parse_rule_t rules[] = {
                   1775:                { "auth",                       parse_auth,                     auth->cfg                                       },
                   1776:                { "id",                         parse_ike_id,           auth->cfg                                       },
                   1777:                { "ca_id",                      parse_ca_id,            auth->cfg                                       },
                   1778:                { "aaa_id",                     parse_aaa_id,           auth->cfg                                       },
                   1779:                { "eap_id",                     parse_eap_id,           auth->cfg                                       },
                   1780:                { "xauth_id",           parse_xauth_id,         auth->cfg                                       },
                   1781:                { "revocation",         parse_revocation,       auth->cfg                                       },
                   1782:                { "round",                      parse_uint32,           &auth->round                            },
                   1783:        };
                   1784: 
                   1785:        return parse_rules(rules, countof(rules), name, value,
                   1786:                                           &auth->request->reply);
                   1787: }
                   1788: 
                   1789: CALLBACK(peer_li, bool,
                   1790:        peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
                   1791: {
                   1792:        parse_rule_t rules[] = {
                   1793:                { "local_addrs",        parse_stringlist,       &peer->local_addrs                      },
                   1794:                { "remote_addrs",       parse_stringlist,       &peer->remote_addrs                     },
                   1795:                { "proposals",          parse_ike_proposal,     peer->proposals                         },
                   1796:                { "vips",                       parse_hosts,            peer->vips                                      },
                   1797:                { "pools",                      parse_stringlist,       &peer->pools                            },
                   1798:        };
                   1799: 
                   1800:        return parse_rules(rules, countof(rules), name, value,
                   1801:                                           &peer->request->reply);
                   1802: }
                   1803: 
                   1804: CALLBACK(peer_kv, bool,
                   1805:        peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
                   1806: {
                   1807:        parse_rule_t rules[] = {
                   1808:                { "version",            parse_uint32,           &peer->version                          },
                   1809:                { "aggressive",         parse_bool,                     &peer->aggressive                       },
                   1810:                { "pull",                       parse_bool,                     &peer->pull                                     },
                   1811:                { "dscp",                       parse_dscp,                     &peer->dscp                                     },
                   1812:                { "encap",                      parse_bool,                     &peer->encap                            },
                   1813:                { "mobike",                     parse_bool,                     &peer->mobike                           },
                   1814:                { "dpd_delay",          parse_time,                     &peer->dpd_delay                        },
                   1815:                { "dpd_timeout",        parse_time,                     &peer->dpd_timeout                      },
                   1816:                { "fragmentation",      parse_frag,                     &peer->fragmentation            },
                   1817:                { "childless",          parse_childless,        &peer->childless                        },
                   1818:                { "send_certreq",       parse_bool,                     &peer->send_certreq                     },
                   1819:                { "send_cert",          parse_send_cert,        &peer->send_cert                        },
                   1820:                { "keyingtries",        parse_uint32,           &peer->keyingtries                      },
                   1821:                { "unique",                     parse_unique,           &peer->unique                           },
                   1822:                { "local_port",         parse_uint32,           &peer->local_port                       },
                   1823:                { "remote_port",        parse_uint32,           &peer->remote_port                      },
                   1824:                { "reauth_time",        parse_time,                     &peer->reauth_time                      },
                   1825:                { "rekey_time",         parse_time,                     &peer->rekey_time                       },
                   1826:                { "over_time",          parse_time,                     &peer->over_time                        },
                   1827:                { "rand_time",          parse_time,                     &peer->rand_time                        },
                   1828:                { "ppk_id",                     parse_peer_id,          &peer->ppk_id                           },
                   1829:                { "ppk_required",       parse_bool,                     &peer->ppk_required                     },
                   1830:                { "if_id_in",           parse_if_id,            &peer->if_id_in                         },
                   1831:                { "if_id_out",          parse_if_id,            &peer->if_id_out                        },
                   1832: #ifdef ME
                   1833:                { "mediation",          parse_bool,                     &peer->mediation                        },
                   1834:                { "mediated_by",        parse_string,           &peer->mediated_by                      },
                   1835:                { "mediation_peer",     parse_peer_id,          &peer->peer_id                          },
                   1836: #endif /* ME */
                   1837:        };
                   1838: 
                   1839:        return parse_rules(rules, countof(rules), name, value,
                   1840:                                           &peer->request->reply);
                   1841: }
                   1842: 
                   1843: CALLBACK(auth_sn, bool,
                   1844:        auth_data_t *auth, vici_message_t *message, vici_parse_context_t *ctx,
                   1845:        char *name)
                   1846: {
                   1847:        if (strcasepfx(name, "cert") ||
                   1848:                strcasepfx(name, "cacert"))
                   1849:        {
                   1850:                cert_data_t *data;
                   1851:                auth_rule_t rule;
                   1852:                certificate_t *cert;
                   1853:                chunk_t handle;
                   1854: 
                   1855:                INIT(data,
                   1856:                        .request = auth->request,
                   1857:                        .slot = -1,
                   1858:                );
                   1859: 
                   1860:                if (!message->parse(message, ctx, NULL, cert_kv, NULL, data))
                   1861:                {
                   1862:                        free_cert_data(data);
                   1863:                        return FALSE;
                   1864:                }
                   1865:                if  (!data->handle && !data->file)
                   1866:                {
                   1867:                        auth->request->reply = create_reply("handle or file path missing: "
                   1868:                                                                                                "%s", name);
                   1869:                        free_cert_data(data);
                   1870:                        return FALSE;
                   1871:                }
                   1872:                else if (data->handle && data->file)
                   1873:                {
                   1874:                        auth->request->reply = create_reply("handle and file path given: "
                   1875:                                                                                                "%s", name);
                   1876:                        free_cert_data(data);
                   1877:                        return FALSE;
                   1878:                }
                   1879: 
                   1880:                if (data->file)
                   1881:                {
                   1882:                        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                   1883:                                                                BUILD_FROM_FILE, data->file, BUILD_END);
                   1884:                }
                   1885:                else
                   1886:                {
                   1887:                        handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
                   1888:                        if (data->slot != -1)
                   1889:                        {
                   1890:                                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                   1891:                                                                CERT_X509, BUILD_PKCS11_KEYID, handle,
                   1892:                                                                BUILD_PKCS11_SLOT, data->slot,
                   1893:                                                                data->module ? BUILD_PKCS11_MODULE : BUILD_END,
                   1894:                                                                data->module, BUILD_END);
                   1895:                        }
                   1896:                        else
                   1897:                        {
                   1898:                                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                   1899:                                                                CERT_X509, BUILD_PKCS11_KEYID, handle,
                   1900:                                                                data->module ? BUILD_PKCS11_MODULE : BUILD_END,
                   1901:                                                                data->module, BUILD_END);
                   1902:                        }
                   1903:                        chunk_free(&handle);
                   1904:                }
                   1905:                free_cert_data(data);
                   1906:                if (!cert)
                   1907:                {
                   1908:                        auth->request->reply = create_reply("unable to load certificate: "
                   1909:                                                                                                "%s", name);
                   1910:                        return FALSE;
                   1911:                }
                   1912:                rule = strcasepfx(name, "cert") ? AUTH_RULE_SUBJECT_CERT
                   1913:                                                                                : AUTH_RULE_CA_CERT;
                   1914:                return add_cert(auth, rule, cert);
                   1915:        }
                   1916:        auth->request->reply = create_reply("invalid section: %s", name);
                   1917:        return FALSE;
                   1918: }
                   1919: 
                   1920: /**
                   1921:  * Check and update lifetimes
                   1922:  */
                   1923: static void check_lifetimes(lifetime_cfg_t *lft)
                   1924: {
                   1925:        /* if no hard lifetime specified, add one at soft lifetime + 10% */
                   1926:        if (lft->time.life == LFT_UNDEFINED)
                   1927:        {
                   1928:                lft->time.life = lft->time.rekey * 110 / 100;
                   1929:        }
                   1930:        if (lft->bytes.life == LFT_UNDEFINED)
                   1931:        {
                   1932:                lft->bytes.life = lft->bytes.rekey * 110 / 100;
                   1933:        }
                   1934:        if (lft->packets.life == LFT_UNDEFINED)
                   1935:        {
                   1936:                lft->packets.life = lft->packets.rekey * 110 / 100;
                   1937:        }
                   1938:        /* if no rand time defined, use difference of hard and soft */
                   1939:        if (lft->time.jitter == LFT_UNDEFINED)
                   1940:        {
                   1941:                lft->time.jitter = lft->time.life -
                   1942:                                                                        min(lft->time.life, lft->time.rekey);
                   1943:        }
                   1944:        if (lft->bytes.jitter == LFT_UNDEFINED)
                   1945:        {
                   1946:                lft->bytes.jitter = lft->bytes.life -
                   1947:                                                                        min(lft->bytes.life, lft->bytes.rekey);
                   1948:        }
                   1949:        if (lft->packets.jitter == LFT_UNDEFINED)
                   1950:        {
                   1951:                lft->packets.jitter = lft->packets.life -
                   1952:                                                                        min(lft->packets.life, lft->packets.rekey);
                   1953:        }
                   1954: }
                   1955: 
                   1956: CALLBACK(children_sn, bool,
                   1957:        peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
                   1958:        char *name)
                   1959: {
                   1960:        child_data_t child = {
                   1961:                .request = peer->request,
                   1962:                .proposals = linked_list_create(),
                   1963:                .local_ts = linked_list_create(),
                   1964:                .remote_ts = linked_list_create(),
                   1965:                .replay_window = REPLAY_UNDEFINED,
                   1966:                .cfg = {
                   1967:                        .mode = MODE_TUNNEL,
                   1968:                        .lifetime = {
                   1969:                                .time = {
                   1970:                                        .rekey = LFT_DEFAULT_CHILD_REKEY_TIME,
                   1971:                                        .life = LFT_UNDEFINED,
                   1972:                                        .jitter = LFT_UNDEFINED,
                   1973:                                },
                   1974:                                .bytes = {
                   1975:                                        .rekey = LFT_DEFAULT_CHILD_REKEY_BYTES,
                   1976:                                        .life = LFT_UNDEFINED,
                   1977:                                        .jitter = LFT_UNDEFINED,
                   1978:                                },
                   1979:                                .packets = {
                   1980:                                        .rekey = LFT_DEFAULT_CHILD_REKEY_PACKETS,
                   1981:                                        .life = LFT_UNDEFINED,
                   1982:                                        .jitter = LFT_UNDEFINED,
                   1983:                                },
                   1984:                        },
                   1985:                },
                   1986:        };
                   1987:        child_cfg_t *cfg;
                   1988:        proposal_t *proposal;
                   1989:        traffic_selector_t *ts;
                   1990: 
                   1991:        if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
                   1992:        {
                   1993:                free_child_data(&child);
                   1994:                return FALSE;
                   1995:        }
                   1996: 
                   1997:        if (child.local_ts->get_count(child.local_ts) == 0)
                   1998:        {
                   1999:                child.local_ts->insert_last(child.local_ts,
                   2000:                                                        traffic_selector_create_dynamic(0, 0, 65535));
                   2001:        }
                   2002:        if (child.remote_ts->get_count(child.remote_ts) == 0)
                   2003:        {
                   2004:                child.remote_ts->insert_last(child.remote_ts,
                   2005:                                                        traffic_selector_create_dynamic(0, 0, 65535));
                   2006:        }
                   2007:        if (child.proposals->get_count(child.proposals) == 0)
                   2008:        {
                   2009:                proposal = proposal_create_default(PROTO_ESP);
                   2010:                if (proposal)
                   2011:                {
                   2012:                        child.proposals->insert_last(child.proposals, proposal);
                   2013:                }
                   2014:                proposal = proposal_create_default_aead(PROTO_ESP);
                   2015:                if (proposal)
                   2016:                {
                   2017:                        child.proposals->insert_last(child.proposals, proposal);
                   2018:                }
                   2019:        }
                   2020: 
                   2021:        check_lifetimes(&child.cfg.lifetime);
                   2022: 
                   2023:        log_child_data(&child, name);
                   2024: 
                   2025:        cfg = child_cfg_create(name, &child.cfg);
                   2026: 
                   2027:        if (child.replay_window != REPLAY_UNDEFINED)
                   2028:        {
                   2029:                cfg->set_replay_window(cfg, child.replay_window);
                   2030:        }
                   2031:        while (child.local_ts->remove_first(child.local_ts,
                   2032:                                                                                (void**)&ts) == SUCCESS)
                   2033:        {
                   2034:                cfg->add_traffic_selector(cfg, TRUE, ts);
                   2035:        }
                   2036:        while (child.remote_ts->remove_first(child.remote_ts,
                   2037:                                                                                 (void**)&ts) == SUCCESS)
                   2038:        {
                   2039:                cfg->add_traffic_selector(cfg, FALSE, ts);
                   2040:        }
                   2041:        while (child.proposals->remove_first(child.proposals,
                   2042:                                                                                 (void**)&proposal) == SUCCESS)
                   2043:        {
                   2044:                cfg->add_proposal(cfg, proposal);
                   2045:        }
                   2046: 
                   2047:        peer->children->insert_last(peer->children, cfg);
                   2048: 
                   2049:        free_child_data(&child);
                   2050: 
                   2051:        return TRUE;
                   2052: }
                   2053: 
                   2054: CALLBACK(peer_sn, bool,
                   2055:        peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
                   2056:        char *name)
                   2057: {
                   2058:        if (strcaseeq(name, "children"))
                   2059:        {
                   2060:                return message->parse(message, ctx, children_sn, NULL, NULL, peer);
                   2061:        }
                   2062:        if (strcasepfx(name, "local") ||
                   2063:                strcasepfx(name, "remote"))
                   2064:        {
                   2065:                enumerator_t *enumerator;
                   2066:                linked_list_t *auths;
                   2067:                auth_data_t *auth, *current;
                   2068:                auth_rule_t rule;
                   2069:                certificate_t *cert;
                   2070:                pubkey_cert_t *pubkey_cert;
                   2071:                identification_t *id;
                   2072:                bool default_id = FALSE;
                   2073: 
                   2074:                INIT(auth,
                   2075:                        .request = peer->request,
                   2076:                        .cfg = auth_cfg_create(),
                   2077:                );
                   2078: 
                   2079:                if (!message->parse(message, ctx, auth_sn, auth_kv, auth_li, auth))
                   2080:                {
                   2081:                        free_auth_data(auth);
                   2082:                        return FALSE;
                   2083:                }
                   2084:                id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY);
                   2085: 
                   2086:                enumerator = auth->cfg->create_enumerator(auth->cfg);
                   2087:                while (enumerator->enumerate(enumerator, &rule, &cert))
                   2088:                {
                   2089:                        if (rule == AUTH_RULE_SUBJECT_CERT && !default_id)
                   2090:                        {
                   2091:                                if (id == NULL)
                   2092:                                {
                   2093:                                        id = cert->get_subject(cert);
                   2094:                                        DBG1(DBG_CFG, "  id not specified, defaulting to"
                   2095:                                                                  " cert subject '%Y'", id);
                   2096:                                        auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id));
                   2097:                                        default_id = TRUE;
                   2098:                                }
                   2099:                                else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY &&
                   2100:                                                 id->get_type != ID_ANY)
                   2101:                                {
                   2102:                                        /* set the subject of all raw public keys to the id */
                   2103:                                        pubkey_cert = (pubkey_cert_t*)cert;
                   2104:                                        pubkey_cert->set_subject(pubkey_cert, id);
                   2105:                                }
                   2106:                        }
                   2107:                }
                   2108:                enumerator->destroy(enumerator);
                   2109: 
                   2110:                auths = strcasepfx(name, "local") ? peer->local : peer->remote;
                   2111:                enumerator = auths->create_enumerator(auths);
                   2112:                while (enumerator->enumerate(enumerator, &current))
                   2113:                {
                   2114:                        if (auth->round < current->round)
                   2115:                        {
                   2116:                                break;
                   2117:                        }
                   2118:                }
                   2119:                auths->insert_before(auths, enumerator, auth);
                   2120:                enumerator->destroy(enumerator);
                   2121:                return TRUE;
                   2122:        }
                   2123:        peer->request->reply = create_reply("invalid section: %s", name);
                   2124:        return FALSE;
                   2125: }
                   2126: 
                   2127: /**
                   2128:  * Perform start actions associated with a child config
                   2129:  */
                   2130: static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
                   2131:                                                         child_cfg_t *child_cfg)
                   2132: {
                   2133:        switch (child_cfg->get_start_action(child_cfg))
                   2134:        {
                   2135:                case ACTION_RESTART:
                   2136:                        DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
                   2137:                        charon->controller->initiate(charon->controller,
                   2138:                                        peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
                   2139:                                        NULL, NULL, 0, FALSE);
                   2140:                        break;
                   2141:                case ACTION_ROUTE:
                   2142:                        DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
                   2143:                        switch (child_cfg->get_mode(child_cfg))
                   2144:                        {
                   2145:                                case MODE_PASS:
                   2146:                                case MODE_DROP:
                   2147:                                        charon->shunts->install(charon->shunts,
                   2148:                                                                        peer_cfg->get_name(peer_cfg), child_cfg);
                   2149:                                        break;
                   2150:                                default:
                   2151:                                        charon->traps->install(charon->traps, peer_cfg, child_cfg);
                   2152:                                        break;
                   2153:                        }
                   2154:                        break;
                   2155:                default:
                   2156:                        break;
                   2157:        }
                   2158: }
                   2159: 
                   2160: /**
                   2161:  * Undo start actions associated with a child config
                   2162:  */
                   2163: static void clear_start_action(private_vici_config_t *this, char *peer_name,
                   2164:                                                           child_cfg_t *child_cfg)
                   2165: {
                   2166:        enumerator_t *enumerator, *children;
                   2167:        child_sa_t *child_sa;
                   2168:        ike_sa_t *ike_sa;
                   2169:        uint32_t id = 0, others;
                   2170:        array_t *ids = NULL, *ikeids = NULL;
                   2171:        char *name;
                   2172: 
                   2173:        name = child_cfg->get_name(child_cfg);
                   2174: 
                   2175:        switch (child_cfg->get_start_action(child_cfg))
                   2176:        {
                   2177:                case ACTION_RESTART:
                   2178:                        enumerator = charon->controller->create_ike_sa_enumerator(
                   2179:                                                                                                        charon->controller, TRUE);
                   2180:                        while (enumerator->enumerate(enumerator, &ike_sa))
                   2181:                        {
                   2182:                                if (!streq(ike_sa->get_name(ike_sa), peer_name))
                   2183:                                {
                   2184:                                        continue;
                   2185:                                }
                   2186:                                others = id = 0;
                   2187:                                children = ike_sa->create_child_sa_enumerator(ike_sa);
                   2188:                                while (children->enumerate(children, &child_sa))
                   2189:                                {
                   2190:                                        if (child_sa->get_state(child_sa) != CHILD_DELETING &&
                   2191:                                                child_sa->get_state(child_sa) != CHILD_DELETED)
                   2192:                                        {
                   2193:                                                if (streq(name, child_sa->get_name(child_sa)))
                   2194:                                                {
                   2195:                                                        id = child_sa->get_unique_id(child_sa);
                   2196:                                                }
                   2197:                                                else
                   2198:                                                {
                   2199:                                                        others++;
                   2200:                                                }
                   2201:                                        }
                   2202:                                }
                   2203:                                children->destroy(children);
                   2204: 
                   2205:                                if (id && !others)
                   2206:                                {
                   2207:                                        /* found matching children only, delete full IKE_SA */
                   2208:                                        id = ike_sa->get_unique_id(ike_sa);
                   2209:                                        array_insert_create_value(&ikeids, sizeof(id),
                   2210:                                                                                          ARRAY_TAIL, &id);
                   2211:                                }
                   2212:                                else
                   2213:                                {
                   2214:                                        children = ike_sa->create_child_sa_enumerator(ike_sa);
                   2215:                                        while (children->enumerate(children, &child_sa))
                   2216:                                        {
                   2217:                                                if (streq(name, child_sa->get_name(child_sa)))
                   2218:                                                {
                   2219:                                                        id = child_sa->get_unique_id(child_sa);
                   2220:                                                        array_insert_create_value(&ids, sizeof(id),
                   2221:                                                                                                          ARRAY_TAIL, &id);
                   2222:                                                }
                   2223:                                        }
                   2224:                                        children->destroy(children);
                   2225:                                }
                   2226:                        }
                   2227:                        enumerator->destroy(enumerator);
                   2228: 
                   2229:                        if (array_count(ids))
                   2230:                        {
                   2231:                                while (array_remove(ids, ARRAY_HEAD, &id))
                   2232:                                {
                   2233:                                        DBG1(DBG_CFG, "closing '%s' #%u", name, id);
                   2234:                                        charon->controller->terminate_child(charon->controller,
                   2235:                                                                                                                id, NULL, NULL, 0);
                   2236:                                }
                   2237:                                array_destroy(ids);
                   2238:                        }
                   2239:                        if (array_count(ikeids))
                   2240:                        {
                   2241:                                while (array_remove(ikeids, ARRAY_HEAD, &id))
                   2242:                                {
                   2243:                                        DBG1(DBG_CFG, "closing IKE_SA #%u", id);
                   2244:                                        charon->controller->terminate_ike(charon->controller, id,
                   2245:                                                                                                          FALSE, NULL, NULL, 0);
                   2246:                                }
                   2247:                                array_destroy(ikeids);
                   2248:                        }
                   2249:                        break;
                   2250:                case ACTION_ROUTE:
                   2251:                        DBG1(DBG_CFG, "uninstalling '%s'", name);
                   2252:                        switch (child_cfg->get_mode(child_cfg))
                   2253:                        {
                   2254:                                case MODE_PASS:
                   2255:                                case MODE_DROP:
                   2256:                                        charon->shunts->uninstall(charon->shunts, peer_name, name);
                   2257:                                        break;
                   2258:                                default:
                   2259:                                        charon->traps->uninstall(charon->traps, peer_name, name);
                   2260:                                        break;
                   2261:                        }
                   2262:                        break;
                   2263:                default:
                   2264:                        break;
                   2265:        }
                   2266: }
                   2267: 
                   2268: /**
                   2269:  * Run or undo a start actions associated with a child config
                   2270:  */
                   2271: static void handle_start_action(private_vici_config_t *this,
                   2272:                                                                peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
                   2273:                                                                bool undo)
                   2274: {
                   2275:        this->handling_actions = TRUE;
                   2276:        this->lock->unlock(this->lock);
                   2277: 
                   2278:        if (undo)
                   2279:        {
                   2280:                clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
                   2281:        }
                   2282:        else
                   2283:        {
                   2284:                run_start_action(this, peer_cfg, child_cfg);
                   2285:        }
                   2286: 
                   2287:        this->lock->write_lock(this->lock);
                   2288:        this->handling_actions = FALSE;
                   2289: }
                   2290: 
                   2291: /**
                   2292:  * Run or undo start actions associated with all child configs of a peer config
                   2293:  */
                   2294: static void handle_start_actions(private_vici_config_t *this,
                   2295:                                                                 peer_cfg_t *peer_cfg, bool undo)
                   2296: {
                   2297:        enumerator_t *enumerator;
                   2298:        child_cfg_t *child_cfg;
                   2299: 
                   2300:        this->handling_actions = TRUE;
                   2301:        this->lock->unlock(this->lock);
                   2302: 
                   2303:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                   2304:        while (enumerator->enumerate(enumerator, &child_cfg))
                   2305:        {
                   2306:                if (undo)
                   2307:                {
                   2308:                        clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
                   2309:                }
                   2310:                else
                   2311:                {
                   2312:                        run_start_action(this, peer_cfg, child_cfg);
                   2313:                }
                   2314:        }
                   2315:        enumerator->destroy(enumerator);
                   2316: 
                   2317:        this->lock->write_lock(this->lock);
                   2318:        this->handling_actions = FALSE;
                   2319: }
                   2320: 
                   2321: /**
                   2322:  * Replace children of a peer config by a new config
                   2323:  */
                   2324: static void replace_children(private_vici_config_t *this,
                   2325:                                                         peer_cfg_t *from, peer_cfg_t *to)
                   2326: {
                   2327:        enumerator_t *enumerator;
                   2328:        child_cfg_t *child;
                   2329:        bool added;
                   2330: 
                   2331:        enumerator = to->replace_child_cfgs(to, from);
                   2332:        while (enumerator->enumerate(enumerator, &child, &added))
                   2333:        {
                   2334:                handle_start_action(this, to, child, !added);
                   2335:        }
                   2336:        enumerator->destroy(enumerator);
                   2337: }
                   2338: 
                   2339: /**
                   2340:  * Merge/replace a peer config with existing configs
                   2341:  */
                   2342: static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
                   2343: {
                   2344:        enumerator_t *enumerator;
                   2345:        peer_cfg_t *current;
                   2346:        ike_cfg_t *ike_cfg;
                   2347:        bool merged = FALSE;
                   2348: 
                   2349:        this->lock->write_lock(this->lock);
                   2350:        while (this->handling_actions)
                   2351:        {
                   2352:                this->condvar->wait(this->condvar, this->lock);
                   2353:        }
                   2354: 
                   2355:        enumerator = this->conns->create_enumerator(this->conns);
                   2356:        while (enumerator->enumerate(enumerator, &current))
                   2357:        {
                   2358:                if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
                   2359:                {
                   2360:                        ike_cfg = current->get_ike_cfg(current);
                   2361:                        if (peer_cfg->equals(peer_cfg, current) &&
                   2362:                                ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
                   2363:                        {
                   2364:                                DBG1(DBG_CFG, "updated vici connection: %s",
                   2365:                                         peer_cfg->get_name(peer_cfg));
                   2366:                                replace_children(this, peer_cfg, current);
                   2367:                                peer_cfg->destroy(peer_cfg);
                   2368:                        }
                   2369:                        else
                   2370:                        {
                   2371:                                DBG1(DBG_CFG, "replaced vici connection: %s",
                   2372:                                         peer_cfg->get_name(peer_cfg));
                   2373:                                this->conns->insert_before(this->conns, enumerator, peer_cfg);
                   2374:                                this->conns->remove_at(this->conns, enumerator);
                   2375:                                handle_start_actions(this, current, TRUE);
                   2376:                                handle_start_actions(this, peer_cfg, FALSE);
                   2377:                                current->destroy(current);
                   2378:                        }
                   2379:                        merged = TRUE;
                   2380:                        break;
                   2381:                }
                   2382:        }
                   2383:        enumerator->destroy(enumerator);
                   2384: 
                   2385:        if (!merged)
                   2386:        {
                   2387:                DBG1(DBG_CFG, "added vici connection: %s", peer_cfg->get_name(peer_cfg));
                   2388:                this->conns->insert_last(this->conns, peer_cfg);
                   2389:                handle_start_actions(this, peer_cfg, FALSE);
                   2390:        }
                   2391:        this->condvar->signal(this->condvar);
                   2392:        this->lock->unlock(this->lock);
                   2393: }
                   2394: 
                   2395: CALLBACK(config_sn, bool,
                   2396:        request_data_t *request, vici_message_t *message,
                   2397:        vici_parse_context_t *ctx, char *name)
                   2398: {
                   2399:        peer_data_t peer = {
                   2400:                .request = request,
                   2401:                .local = linked_list_create(),
                   2402:                .remote = linked_list_create(),
                   2403:                .vips = linked_list_create(),
                   2404:                .children = linked_list_create(),
                   2405:                .proposals = linked_list_create(),
                   2406:                .mobike = TRUE,
                   2407:                .send_certreq = TRUE,
                   2408:                .pull = TRUE,
                   2409:                .send_cert = CERT_SEND_IF_ASKED,
                   2410:                .version = IKE_ANY,
                   2411:                .remote_port = IKEV2_UDP_PORT,
                   2412:                .fragmentation = FRAGMENTATION_YES,
                   2413:                .unique = UNIQUE_NO,
                   2414:                .keyingtries = 1,
                   2415:                .rekey_time = LFT_UNDEFINED,
                   2416:                .reauth_time = LFT_UNDEFINED,
                   2417:                .over_time = LFT_UNDEFINED,
                   2418:                .rand_time = LFT_UNDEFINED,
                   2419:        };
                   2420:        enumerator_t *enumerator;
                   2421:        peer_cfg_create_t cfg;
                   2422:        peer_cfg_t *peer_cfg;
                   2423:        ike_cfg_create_t ike;
                   2424:        ike_cfg_t *ike_cfg;
                   2425:        child_cfg_t *child_cfg;
                   2426:        auth_data_t *auth;
                   2427:        proposal_t *proposal;
                   2428:        host_t *host;
                   2429:        char *str;
                   2430: 
                   2431:        DBG2(DBG_CFG, " conn %s:", name);
                   2432: 
                   2433:        if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
                   2434:        {
                   2435:                free_peer_data(&peer);
                   2436:                return FALSE;
                   2437:        }
                   2438: 
                   2439:        if (peer.local->get_count(peer.local) == 0)
                   2440:        {
                   2441:                INIT(auth,
                   2442:                        .cfg = auth_cfg_create(),
                   2443:                );
                   2444:                peer.local->insert_last(peer.local, auth);
                   2445:        }
                   2446:        if (peer.remote->get_count(peer.remote) == 0)
                   2447:        {
                   2448:                INIT(auth,
                   2449:                        .cfg = auth_cfg_create(),
                   2450:                );
                   2451:                peer.remote->insert_last(peer.remote, auth);
                   2452:        }
                   2453:        if (peer.proposals->get_count(peer.proposals) == 0)
                   2454:        {
                   2455:                proposal = proposal_create_default(PROTO_IKE);
                   2456:                if (proposal)
                   2457:                {
                   2458:                        peer.proposals->insert_last(peer.proposals, proposal);
                   2459:                }
                   2460:                proposal = proposal_create_default_aead(PROTO_IKE);
                   2461:                if (proposal)
                   2462:                {
                   2463:                        peer.proposals->insert_last(peer.proposals, proposal);
                   2464:                }
                   2465:        }
                   2466:        if (!peer.local_addrs)
                   2467:        {
                   2468:                peer.local_addrs = strdup("%any");
                   2469:        }
                   2470:        if (!peer.remote_addrs)
                   2471:        {
                   2472:                peer.remote_addrs = strdup("%any");
                   2473:        }
                   2474:        if (!peer.local_port)
                   2475:        {
                   2476:                peer.local_port = charon->socket->get_port(charon->socket, FALSE);
                   2477:        }
                   2478: 
                   2479:        if (peer.rekey_time == LFT_UNDEFINED && peer.reauth_time == LFT_UNDEFINED)
                   2480:        {
                   2481:                /* apply a default rekey time if no rekey/reauth time set */
                   2482:                peer.rekey_time = LFT_DEFAULT_IKE_REKEY_TIME;
                   2483:                peer.reauth_time = 0;
                   2484:        }
                   2485:        if (peer.rekey_time == LFT_UNDEFINED)
                   2486:        {
                   2487:                peer.rekey_time = 0;
                   2488:        }
                   2489:        if (peer.reauth_time == LFT_UNDEFINED)
                   2490:        {
                   2491:                peer.reauth_time = 0;
                   2492:        }
                   2493:        if (peer.over_time == LFT_UNDEFINED)
                   2494:        {
                   2495:                /* default over_time to 10% of rekey/reauth time if not given */
                   2496:                peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
                   2497:        }
                   2498:        if (peer.rand_time == LFT_UNDEFINED)
                   2499:        {
                   2500:                /* default rand_time to over_time if not given, but don't make it
                   2501:                 * longer than half of rekey/rauth time */
                   2502:                if (peer.rekey_time && peer.reauth_time)
                   2503:                {
                   2504:                        peer.rand_time = min(peer.rekey_time, peer.reauth_time);
                   2505:                }
                   2506:                else
                   2507:                {
                   2508:                        peer.rand_time = max(peer.rekey_time, peer.reauth_time);
                   2509:                }
                   2510:                peer.rand_time = min(peer.over_time, peer.rand_time / 2);
                   2511:        }
                   2512: 
                   2513: #ifdef ME
                   2514:        if (peer.mediation && peer.mediated_by)
                   2515:        {
                   2516:                DBG1(DBG_CFG, "a mediation connection cannot be a mediated connection "
                   2517:                         "at the same time, config discarded");
                   2518:                free_peer_data(&peer);
                   2519:                return FALSE;
                   2520:        }
                   2521:        if (peer.mediation)
                   2522:        {       /* force unique connections for mediation connections */
                   2523:                peer.unique = UNIQUE_REPLACE;
                   2524:        }
                   2525:        else if (peer.mediated_by)
                   2526:        {       /* fallback to remote identity of first auth round if peer_id is not
                   2527:                 * given explicitly */
                   2528:                auth_cfg_t *cfg;
                   2529: 
                   2530:                if (!peer.peer_id &&
                   2531:                        peer.remote->get_first(peer.remote, (void**)&cfg) == SUCCESS)
                   2532:                {
                   2533:                        peer.peer_id = cfg->get(cfg, AUTH_RULE_IDENTITY);
                   2534:                        if (peer.peer_id)
                   2535:                        {
                   2536:                                peer.peer_id = peer.peer_id->clone(peer.peer_id);
                   2537:                        }
                   2538:                        else
                   2539:                        {
                   2540:                                DBG1(DBG_CFG, "mediation peer missing for mediated connection, "
                   2541:                                         "config discarded");
                   2542:                                free_peer_data(&peer);
                   2543:                                return FALSE;
                   2544:                        }
                   2545:                }
                   2546:        }
                   2547: #endif /* ME */
                   2548: 
                   2549:        log_peer_data(&peer);
                   2550: 
                   2551:        ike = (ike_cfg_create_t){
                   2552:                .version = peer.version,
                   2553:                .local = peer.local_addrs,
                   2554:                .local_port = peer.local_port,
                   2555:                .remote = peer.remote_addrs,
                   2556:                .remote_port = peer.remote_port,
                   2557:                .no_certreq = !peer.send_certreq,
                   2558:                .force_encap = peer.encap,
                   2559:                .fragmentation = peer.fragmentation,
                   2560:                .childless = peer.childless,
                   2561:                .dscp = peer.dscp,
                   2562:        };
                   2563:        ike_cfg = ike_cfg_create(&ike);
                   2564: 
                   2565:        cfg = (peer_cfg_create_t){
                   2566:                .cert_policy = peer.send_cert,
                   2567:                .unique = peer.unique,
                   2568:                .keyingtries = peer.keyingtries,
                   2569:                .rekey_time = peer.rekey_time,
                   2570:                .reauth_time = peer.reauth_time,
                   2571:                .jitter_time = peer.rand_time,
                   2572:                .over_time = peer.over_time,
                   2573:                .no_mobike = !peer.mobike,
                   2574:                .aggressive = peer.aggressive,
                   2575:                .push_mode = !peer.pull,
                   2576:                .dpd = peer.dpd_delay,
                   2577:                .dpd_timeout = peer.dpd_timeout,
                   2578:                .ppk_id = peer.ppk_id ? peer.ppk_id->clone(peer.ppk_id) : NULL,
                   2579:                .ppk_required = peer.ppk_required,
                   2580:                .if_id_in = peer.if_id_in,
                   2581:                .if_id_out = peer.if_id_out,
                   2582:        };
                   2583: #ifdef ME
                   2584:        cfg.mediation = peer.mediation;
                   2585:        if (peer.mediated_by)
                   2586:        {
                   2587:                cfg.mediated_by = peer.mediated_by;
                   2588:                if (peer.peer_id)
                   2589:                {
                   2590:                        cfg.peer_id = peer.peer_id->clone(peer.peer_id);
                   2591:                }
                   2592:        }
                   2593: #endif /* ME */
                   2594:        peer_cfg = peer_cfg_create(name, ike_cfg, &cfg);
                   2595: 
                   2596:        while (peer.local->remove_first(peer.local,
                   2597:                                                                        (void**)&auth) == SUCCESS)
                   2598:        {
                   2599:                peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE);
                   2600:                auth->cfg = NULL;
                   2601:                free_auth_data(auth);
                   2602:        }
                   2603:        while (peer.remote->remove_first(peer.remote,
                   2604:                                                                         (void**)&auth) == SUCCESS)
                   2605:        {
                   2606:                peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE);
                   2607:                auth->cfg = NULL;
                   2608:                free_auth_data(auth);
                   2609:        }
                   2610:        while (peer.children->remove_first(peer.children,
                   2611:                                                                           (void**)&child_cfg) == SUCCESS)
                   2612:        {
                   2613:                peer_cfg->add_child_cfg(peer_cfg, child_cfg);
                   2614:        }
                   2615:        while (peer.proposals->remove_first(peer.proposals,
                   2616:                                                                                (void**)&proposal) == SUCCESS)
                   2617:        {
                   2618:                ike_cfg->add_proposal(ike_cfg, proposal);
                   2619:        }
                   2620:        while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
                   2621:        {
                   2622:                peer_cfg->add_virtual_ip(peer_cfg, host);
                   2623:        }
                   2624:        if (peer.pools)
                   2625:        {
                   2626:                enumerator = enumerator_create_token(peer.pools, ",", " ");
                   2627:                while (enumerator->enumerate(enumerator, &str))
                   2628:                {
                   2629:                        peer_cfg->add_pool(peer_cfg, str);
                   2630:                }
                   2631:                enumerator->destroy(enumerator);
                   2632:        }
                   2633: 
                   2634:        free_peer_data(&peer);
                   2635: 
                   2636:        merge_config(request->this, peer_cfg);
                   2637: 
                   2638:        return TRUE;
                   2639: }
                   2640: 
                   2641: CALLBACK(load_conn, vici_message_t*,
                   2642:        private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
                   2643: {
                   2644:        request_data_t request = {
                   2645:                .this = this,
                   2646:        };
                   2647: 
                   2648:        if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
                   2649:        {
                   2650:                if (request.reply)
                   2651:                {
                   2652:                        return request.reply;
                   2653:                }
                   2654:                return create_reply("parsing request failed");
                   2655:        }
                   2656:        return create_reply(NULL);
                   2657: }
                   2658: 
                   2659: CALLBACK(unload_conn, vici_message_t*,
                   2660:        private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
                   2661: {
                   2662:        enumerator_t *enumerator;
                   2663:        peer_cfg_t *cfg;
                   2664:        char *conn_name;
                   2665:        bool found = FALSE;
                   2666: 
                   2667:        conn_name = message->get_str(message, NULL, "name");
                   2668:        if (!conn_name)
                   2669:        {
                   2670:                return create_reply("unload: missing connection name");
                   2671:        }
                   2672: 
                   2673:        this->lock->write_lock(this->lock);
                   2674:        while (this->handling_actions)
                   2675:        {
                   2676:                this->condvar->wait(this->condvar, this->lock);
                   2677:        }
                   2678:        enumerator = this->conns->create_enumerator(this->conns);
                   2679:        while (enumerator->enumerate(enumerator, &cfg))
                   2680:        {
                   2681:                if (streq(cfg->get_name(cfg), conn_name))
                   2682:                {
                   2683:                        this->conns->remove_at(this->conns, enumerator);
                   2684:                        handle_start_actions(this, cfg, TRUE);
                   2685:                        cfg->destroy(cfg);
                   2686:                        found = TRUE;
                   2687:                        break;
                   2688:                }
                   2689:        }
                   2690:        enumerator->destroy(enumerator);
                   2691:        this->condvar->signal(this->condvar);
                   2692:        this->lock->unlock(this->lock);
                   2693: 
                   2694:        if (!found)
                   2695:        {
                   2696:                return create_reply("unload: connection '%s' not found", conn_name);
                   2697:        }
                   2698:        return create_reply(NULL);
                   2699: }
                   2700: 
                   2701: CALLBACK(get_conns, vici_message_t*,
                   2702:        private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
                   2703: {
                   2704:        vici_builder_t *builder;
                   2705:        enumerator_t *enumerator;
                   2706:        peer_cfg_t *cfg;
                   2707: 
                   2708:        builder = vici_builder_create();
                   2709:        builder->begin_list(builder, "conns");
                   2710: 
                   2711:        this->lock->read_lock(this->lock);
                   2712:        enumerator = this->conns->create_enumerator(this->conns);
                   2713:        while (enumerator->enumerate(enumerator, &cfg))
                   2714:        {
                   2715:                builder->add_li(builder, "%s", cfg->get_name(cfg));
                   2716:        }
                   2717:        enumerator->destroy(enumerator);
                   2718:        this->lock->unlock(this->lock);
                   2719: 
                   2720:        builder->end_list(builder);
                   2721: 
                   2722:        return builder->finalize(builder);
                   2723: }
                   2724: 
                   2725: static void manage_command(private_vici_config_t *this,
                   2726:                                                   char *name, vici_command_cb_t cb, bool reg)
                   2727: {
                   2728:        this->dispatcher->manage_command(this->dispatcher, name,
                   2729:                                                                         reg ? cb : NULL, this);
                   2730: }
                   2731: 
                   2732: /**
                   2733:  * (Un-)register dispatcher functions
                   2734:  */
                   2735: static void manage_commands(private_vici_config_t *this, bool reg)
                   2736: {
                   2737:        manage_command(this, "load-conn", load_conn, reg);
                   2738:        manage_command(this, "unload-conn", unload_conn, reg);
                   2739:        manage_command(this, "get-conns", get_conns, reg);
                   2740: }
                   2741: 
                   2742: METHOD(vici_config_t, destroy, void,
                   2743:        private_vici_config_t *this)
                   2744: {
                   2745:        manage_commands(this, FALSE);
                   2746:        this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
                   2747:        this->condvar->destroy(this->condvar);
                   2748:        this->lock->destroy(this->lock);
                   2749:        free(this);
                   2750: }
                   2751: 
                   2752: /**
                   2753:  * See header
                   2754:  */
                   2755: vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
                   2756:                                                                  vici_authority_t *authority,
                   2757:                                                                  vici_cred_t *cred)
                   2758: {
                   2759:        private_vici_config_t *this;
                   2760: 
                   2761:        INIT(this,
                   2762:                .public = {
                   2763:                        .backend = {
                   2764:                                .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
                   2765:                                .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
                   2766:                                .get_peer_cfg_by_name = _get_peer_cfg_by_name,
                   2767:                        },
                   2768:                        .destroy = _destroy,
                   2769:                },
                   2770:                .dispatcher = dispatcher,
                   2771:                .conns = linked_list_create(),
                   2772:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                   2773:                .condvar = rwlock_condvar_create(),
                   2774:                .authority = authority,
                   2775:                .cred = cred,
                   2776:        );
                   2777: 
                   2778:        manage_commands(this, TRUE);
                   2779: 
                   2780:        return &this->public;
                   2781: }

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