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

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

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