Annotation of embedaddon/strongswan/src/libcharon/plugins/vici/vici_control.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2015-2017 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2014 Martin Willi
        !             6:  * Copyright (C) 2014 revosec AG
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include "vici_control.h"
        !            20: #include "vici_builder.h"
        !            21: 
        !            22: #include <inttypes.h>
        !            23: 
        !            24: #include <daemon.h>
        !            25: #include <collections/array.h>
        !            26: #include <processing/jobs/rekey_ike_sa_job.h>
        !            27: #include <processing/jobs/rekey_child_sa_job.h>
        !            28: #include <processing/jobs/redirect_job.h>
        !            29: 
        !            30: typedef struct private_vici_control_t private_vici_control_t;
        !            31: 
        !            32: /**
        !            33:  * Private data of an vici_control_t object.
        !            34:  */
        !            35: struct private_vici_control_t {
        !            36: 
        !            37:        /**
        !            38:         * Public vici_control_t interface.
        !            39:         */
        !            40:        vici_control_t public;
        !            41: 
        !            42:        /**
        !            43:         * Dispatcher
        !            44:         */
        !            45:        vici_dispatcher_t *dispatcher;
        !            46: };
        !            47: 
        !            48: /**
        !            49:  * Log callback helper data
        !            50:  */
        !            51: typedef struct {
        !            52:        /** dispatcher to send log messages over */
        !            53:        vici_dispatcher_t *dispatcher;
        !            54:        /** connection ID to send messages to */
        !            55:        u_int id;
        !            56:        /** loglevel */
        !            57:        level_t level;
        !            58:        /** prevent recursive log */
        !            59:        u_int recursive;
        !            60: } log_info_t;
        !            61: 
        !            62: /**
        !            63:  * Log using vici event messages
        !            64:  */
        !            65: static bool log_vici(log_info_t *info, debug_t group, level_t level,
        !            66:                                         ike_sa_t *ike_sa, char *text)
        !            67: {
        !            68:        if (level <= info->level)
        !            69:        {
        !            70:                if (info->recursive++ == 0)
        !            71:                {
        !            72:                        vici_message_t *message;
        !            73:                        vici_builder_t *builder;
        !            74: 
        !            75:                        builder = vici_builder_create();
        !            76:                        builder->add_kv(builder, "group", "%N", debug_names, group);
        !            77:                        builder->add_kv(builder, "level", "%d", level);
        !            78:                        if (ike_sa)
        !            79:                        {
        !            80:                                builder->add_kv(builder, "ikesa-name", "%s",
        !            81:                                                                ike_sa->get_name(ike_sa));
        !            82:                                builder->add_kv(builder, "ikesa-uniqueid", "%u",
        !            83:                                                                ike_sa->get_unique_id(ike_sa));
        !            84:                        }
        !            85:                        builder->add_kv(builder, "msg", "%s", text);
        !            86: 
        !            87:                        message = builder->finalize(builder);
        !            88:                        if (message)
        !            89:                        {
        !            90:                                info->dispatcher->raise_event(info->dispatcher, "control-log",
        !            91:                                                                                          info->id, message);
        !            92:                        }
        !            93:                }
        !            94:                info->recursive--;
        !            95:        }
        !            96:        return TRUE;
        !            97: }
        !            98: 
        !            99: /**
        !           100:  * Send a (error) reply message
        !           101:  */
        !           102: static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
        !           103: {
        !           104:        vici_builder_t *builder;
        !           105:        va_list args;
        !           106: 
        !           107:        builder = vici_builder_create();
        !           108:        builder->add_kv(builder, "success", fmt ? "no" : "yes");
        !           109:        if (fmt)
        !           110:        {
        !           111:                va_start(args, fmt);
        !           112:                builder->vadd_kv(builder, "errmsg", fmt, args);
        !           113:                va_end(args);
        !           114:        }
        !           115:        return builder->finalize(builder);
        !           116: }
        !           117: 
        !           118: /**
        !           119:  * Get the child_cfg having name from peer_cfg
        !           120:  */
        !           121: static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
        !           122: {
        !           123:        child_cfg_t *current, *found = NULL;
        !           124:        enumerator_t *enumerator;
        !           125: 
        !           126:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
        !           127:        while (enumerator->enumerate(enumerator, &current))
        !           128:        {
        !           129:                if (streq(current->get_name(current), name))
        !           130:                {
        !           131:                        found = current;
        !           132:                        found->get_ref(found);
        !           133:                        break;
        !           134:                }
        !           135:        }
        !           136:        enumerator->destroy(enumerator);
        !           137:        return found;
        !           138: }
        !           139: 
        !           140: /**
        !           141:  * Find a peer/child config from a config name
        !           142:  */
        !           143: static child_cfg_t* find_child_cfg(char *name, char *pname, peer_cfg_t **out)
        !           144: {
        !           145:        enumerator_t *enumerator;
        !           146:        peer_cfg_t *peer_cfg;
        !           147:        child_cfg_t *child_cfg = NULL;
        !           148: 
        !           149:        enumerator = charon->backends->create_peer_cfg_enumerator(
        !           150:                                                        charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
        !           151:        while (enumerator->enumerate(enumerator, &peer_cfg))
        !           152:        {
        !           153:                if (pname && !streq(pname, peer_cfg->get_name(peer_cfg)))
        !           154:                {
        !           155:                        continue;
        !           156:                }
        !           157:                if (!name)
        !           158:                {
        !           159:                        *out = peer_cfg->get_ref(peer_cfg);
        !           160:                        break;
        !           161:                }
        !           162:                child_cfg = get_child_from_peer(peer_cfg, name);
        !           163:                if (child_cfg)
        !           164:                {
        !           165:                        *out = peer_cfg->get_ref(peer_cfg);
        !           166:                        break;
        !           167:                }
        !           168:        }
        !           169:        enumerator->destroy(enumerator);
        !           170: 
        !           171:        return child_cfg;
        !           172: }
        !           173: 
        !           174: CALLBACK(initiate, vici_message_t*,
        !           175:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           176: {
        !           177:        peer_cfg_t *peer_cfg = NULL;
        !           178:        child_cfg_t *child_cfg;
        !           179:        char *child, *ike, *type, *sa;
        !           180:        int timeout;
        !           181:        bool limits;
        !           182:        controller_cb_t log_cb = NULL;
        !           183:        log_info_t log = {
        !           184:                .dispatcher = this->dispatcher,
        !           185:                .id = id,
        !           186:        };
        !           187: 
        !           188:        child = request->get_str(request, NULL, "child");
        !           189:        ike = request->get_str(request, NULL, "ike");
        !           190:        timeout = request->get_int(request, 0, "timeout");
        !           191:        limits = request->get_bool(request, FALSE, "init-limits");
        !           192:        log.level = request->get_int(request, 1, "loglevel");
        !           193: 
        !           194:        if (!child && !ike)
        !           195:        {
        !           196:                return send_reply(this, "missing configuration name");
        !           197:        }
        !           198:        if (timeout >= 0)
        !           199:        {
        !           200:                log_cb = (controller_cb_t)log_vici;
        !           201:        }
        !           202: 
        !           203:        type = child ? "CHILD_SA" : "IKE_SA";
        !           204:        sa = child ?: ike;
        !           205: 
        !           206:        child_cfg = find_child_cfg(child, ike, &peer_cfg);
        !           207: 
        !           208:        DBG1(DBG_CFG, "vici initiate %s '%s'", type, sa);
        !           209:        if (!peer_cfg)
        !           210:        {
        !           211:                return send_reply(this, "%s config '%s' not found", type, sa);
        !           212:        }
        !           213:        switch (charon->controller->initiate(charon->controller, peer_cfg,
        !           214:                                                                        child_cfg, log_cb, &log, timeout, limits))
        !           215:        {
        !           216:                case SUCCESS:
        !           217:                        return send_reply(this, NULL);
        !           218:                case OUT_OF_RES:
        !           219:                        return send_reply(this, "%s '%s' not established after %dms", type,
        !           220:                                                          sa, timeout);
        !           221:                case INVALID_STATE:
        !           222:                        return send_reply(this, "establishing %s '%s' not possible at the "
        !           223:                                                          "moment due to limits", type, sa);
        !           224:                case FAILED:
        !           225:                default:
        !           226:                        return send_reply(this, "establishing %s '%s' failed", type, sa);
        !           227:        }
        !           228: }
        !           229: 
        !           230: CALLBACK(terminate, vici_message_t*,
        !           231:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           232: {
        !           233:        enumerator_t *enumerator, *isas, *csas;
        !           234:        char *child, *ike, *errmsg = NULL;
        !           235:        u_int child_id, ike_id, current, *del, done = 0;
        !           236:        bool force;
        !           237:        int timeout;
        !           238:        ike_sa_t *ike_sa;
        !           239:        child_sa_t *child_sa;
        !           240:        array_t *ids;
        !           241:        vici_builder_t *builder;
        !           242:        controller_cb_t log_cb = NULL;
        !           243:        log_info_t log = {
        !           244:                .dispatcher = this->dispatcher,
        !           245:                .id = id,
        !           246:        };
        !           247: 
        !           248:        child = request->get_str(request, NULL, "child");
        !           249:        ike = request->get_str(request, NULL, "ike");
        !           250:        child_id = request->get_int(request, 0, "child-id");
        !           251:        ike_id = request->get_int(request, 0, "ike-id");
        !           252:        force = request->get_bool(request, FALSE, "force");
        !           253:        timeout = request->get_int(request, 0, "timeout");
        !           254:        log.level = request->get_int(request, 1, "loglevel");
        !           255: 
        !           256:        if (!child && !ike && !ike_id && !child_id)
        !           257:        {
        !           258:                return send_reply(this, "missing terminate selector");
        !           259:        }
        !           260: 
        !           261:        if (ike_id)
        !           262:        {
        !           263:                DBG1(DBG_CFG, "vici terminate IKE_SA #%d", ike_id);
        !           264:        }
        !           265:        if (child_id)
        !           266:        {
        !           267:                DBG1(DBG_CFG, "vici terminate CHILD_SA #%d", child_id);
        !           268:        }
        !           269:        if (ike)
        !           270:        {
        !           271:                DBG1(DBG_CFG, "vici terminate IKE_SA '%s'", ike);
        !           272:        }
        !           273:        if (child)
        !           274:        {
        !           275:                DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
        !           276:        }
        !           277: 
        !           278:        if (timeout >= 0)
        !           279:        {
        !           280:                log_cb = (controller_cb_t)log_vici;
        !           281:        }
        !           282: 
        !           283:        ids = array_create(sizeof(u_int), 0);
        !           284: 
        !           285:        isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
        !           286:        while (isas->enumerate(isas, &ike_sa))
        !           287:        {
        !           288:                if (child || child_id)
        !           289:                {
        !           290:                        if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
        !           291:                        {
        !           292:                                continue;
        !           293:                        }
        !           294:                        if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
        !           295:                        {
        !           296:                                continue;
        !           297:                        }
        !           298:                        csas = ike_sa->create_child_sa_enumerator(ike_sa);
        !           299:                        while (csas->enumerate(csas, &child_sa))
        !           300:                        {
        !           301:                                if (child && !streq(child, child_sa->get_name(child_sa)))
        !           302:                                {
        !           303:                                        continue;
        !           304:                                }
        !           305:                                if (child_id && child_sa->get_unique_id(child_sa) != child_id)
        !           306:                                {
        !           307:                                        continue;
        !           308:                                }
        !           309:                                current = child_sa->get_unique_id(child_sa);
        !           310:                                array_insert(ids, ARRAY_TAIL, &current);
        !           311:                        }
        !           312:                        csas->destroy(csas);
        !           313:                }
        !           314:                else if (ike && streq(ike, ike_sa->get_name(ike_sa)))
        !           315:                {
        !           316:                        current = ike_sa->get_unique_id(ike_sa);
        !           317:                        array_insert(ids, ARRAY_TAIL, &current);
        !           318:                }
        !           319:                else if (ike_id && ike_id == ike_sa->get_unique_id(ike_sa))
        !           320:                {
        !           321:                        array_insert(ids, ARRAY_TAIL, &ike_id);
        !           322:                }
        !           323:        }
        !           324:        isas->destroy(isas);
        !           325: 
        !           326:        enumerator = array_create_enumerator(ids);
        !           327:        while (enumerator->enumerate(enumerator, &del))
        !           328:        {
        !           329:                if (child || child_id)
        !           330:                {
        !           331:                        if (charon->controller->terminate_child(charon->controller, *del,
        !           332:                                                                                        log_cb, &log, timeout) == SUCCESS)
        !           333:                        {
        !           334:                                done++;
        !           335:                        }
        !           336:                }
        !           337:                else
        !           338:                {
        !           339:                        if (charon->controller->terminate_ike(charon->controller, *del, force,
        !           340:                                                                                        log_cb, &log, timeout) == SUCCESS)
        !           341:                        {
        !           342:                                done++;
        !           343:                        }
        !           344:                }
        !           345:        }
        !           346:        enumerator->destroy(enumerator);
        !           347: 
        !           348:        builder = vici_builder_create();
        !           349:        if (array_count(ids) == 0)
        !           350:        {
        !           351:                errmsg = "no matching SAs to terminate found";
        !           352:        }
        !           353:        else if (done < array_count(ids))
        !           354:        {
        !           355:                if (array_count(ids) == 1)
        !           356:                {
        !           357:                        errmsg = "terminating SA failed";
        !           358:                }
        !           359:                else
        !           360:                {
        !           361:                        errmsg = "not all matching SAs could be terminated";
        !           362:                }
        !           363:        }
        !           364:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
        !           365:        builder->add_kv(builder, "matches", "%u", array_count(ids));
        !           366:        builder->add_kv(builder, "terminated", "%u", done);
        !           367:        if (errmsg)
        !           368:        {
        !           369:                builder->add_kv(builder, "errmsg", "%s", errmsg);
        !           370:        }
        !           371:        array_destroy(ids);
        !           372:        return builder->finalize(builder);
        !           373: }
        !           374: 
        !           375: CALLBACK(rekey, vici_message_t*,
        !           376:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           377: {
        !           378:        enumerator_t *isas, *csas;
        !           379:        char *child, *ike, *errmsg = NULL;
        !           380:        u_int child_id, ike_id, found = 0;
        !           381:        ike_sa_t *ike_sa;
        !           382:        child_sa_t *child_sa;
        !           383:        vici_builder_t *builder;
        !           384:        bool reauth;
        !           385: 
        !           386:        child = request->get_str(request, NULL, "child");
        !           387:        ike = request->get_str(request, NULL, "ike");
        !           388:        child_id = request->get_int(request, 0, "child-id");
        !           389:        ike_id = request->get_int(request, 0, "ike-id");
        !           390:        reauth = request->get_bool(request, FALSE, "reauth");
        !           391: 
        !           392:        if (!child && !ike && !ike_id && !child_id)
        !           393:        {
        !           394:                return send_reply(this, "missing rekey selector");
        !           395:        }
        !           396: 
        !           397:        if (ike_id)
        !           398:        {
        !           399:                DBG1(DBG_CFG, "vici rekey IKE_SA #%d", ike_id);
        !           400:        }
        !           401:        if (child_id)
        !           402:        {
        !           403:                DBG1(DBG_CFG, "vici rekey CHILD_SA #%d", child_id);
        !           404:        }
        !           405:        if (ike)
        !           406:        {
        !           407:                DBG1(DBG_CFG, "vici rekey IKE_SA '%s'", ike);
        !           408:        }
        !           409:        if (child)
        !           410:        {
        !           411:                DBG1(DBG_CFG, "vici rekey CHILD_SA '%s'", child);
        !           412:        }
        !           413: 
        !           414:        isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
        !           415:        while (isas->enumerate(isas, &ike_sa))
        !           416:        {
        !           417:                if (child || child_id)
        !           418:                {
        !           419:                        if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
        !           420:                        {
        !           421:                                continue;
        !           422:                        }
        !           423:                        if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
        !           424:                        {
        !           425:                                continue;
        !           426:                        }
        !           427:                        csas = ike_sa->create_child_sa_enumerator(ike_sa);
        !           428:                        while (csas->enumerate(csas, &child_sa))
        !           429:                        {
        !           430:                                if (child && !streq(child, child_sa->get_name(child_sa)))
        !           431:                                {
        !           432:                                        continue;
        !           433:                                }
        !           434:                                if (child_id && child_sa->get_unique_id(child_sa) != child_id)
        !           435:                                {
        !           436:                                        continue;
        !           437:                                }
        !           438:                                lib->processor->queue_job(lib->processor,
        !           439:                                                (job_t*)rekey_child_sa_job_create(
        !           440:                                                                                        child_sa->get_protocol(child_sa),
        !           441:                                                                                        child_sa->get_spi(child_sa, TRUE),
        !           442:                                                                                        ike_sa->get_my_host(ike_sa)));
        !           443:                                found++;
        !           444:                        }
        !           445:                        csas->destroy(csas);
        !           446:                }
        !           447:                else if ((ike && streq(ike, ike_sa->get_name(ike_sa))) ||
        !           448:                                 (ike_id && ike_id == ike_sa->get_unique_id(ike_sa)))
        !           449:                {
        !           450:                        lib->processor->queue_job(lib->processor,
        !           451:                                (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), reauth));
        !           452:                        found++;
        !           453:                }
        !           454:        }
        !           455:        isas->destroy(isas);
        !           456: 
        !           457:        builder = vici_builder_create();
        !           458:        if (!found)
        !           459:        {
        !           460:                errmsg = "no matching SAs to rekey found";
        !           461:        }
        !           462:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
        !           463:        builder->add_kv(builder, "matches", "%u", found);
        !           464:        if (errmsg)
        !           465:        {
        !           466:                builder->add_kv(builder, "errmsg", "%s", errmsg);
        !           467:        }
        !           468:        return builder->finalize(builder);
        !           469: }
        !           470: 
        !           471: /**
        !           472:  * Parse a peer-ip specified, which can be a subnet in CIDR notation, a range
        !           473:  * or a single IP address.
        !           474:  */
        !           475: static traffic_selector_t *parse_peer_ip(char *ip)
        !           476: {
        !           477:        traffic_selector_t *ts;
        !           478:        host_t *from, *to;
        !           479:        ts_type_t type;
        !           480: 
        !           481:        if (host_create_from_range(ip, &from, &to))
        !           482:        {
        !           483:                if (to->get_family(to) == AF_INET)
        !           484:                {
        !           485:                        type = TS_IPV4_ADDR_RANGE;
        !           486:                }
        !           487:                else
        !           488:                {
        !           489:                        type = TS_IPV6_ADDR_RANGE;
        !           490:                }
        !           491:                ts = traffic_selector_create_from_bytes(0, type,
        !           492:                                                                                                from->get_address(from), 0,
        !           493:                                                                                                to->get_address(to), 0xFFFF);
        !           494:                from->destroy(from);
        !           495:                to->destroy(to);
        !           496:                return ts;
        !           497:        }
        !           498:        return traffic_selector_create_from_cidr(ip, 0, 0, 0xFFFF);
        !           499: }
        !           500: 
        !           501: CALLBACK(redirect, vici_message_t*,
        !           502:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           503: {
        !           504:        enumerator_t *sas;
        !           505:        char *ike, *peer_ip, *peer_id, *gw, *errmsg = NULL;
        !           506:        u_int ike_id, current, found = 0;
        !           507:        identification_t *gateway, *identity = NULL, *other_id;
        !           508:        traffic_selector_t *ts = NULL;
        !           509:        ike_sa_t *ike_sa;
        !           510:        vici_builder_t *builder;
        !           511: 
        !           512:        ike = request->get_str(request, NULL, "ike");
        !           513:        ike_id = request->get_int(request, 0, "ike-id");
        !           514:        peer_ip = request->get_str(request, NULL, "peer-ip");
        !           515:        peer_id = request->get_str(request, NULL, "peer-id");
        !           516:        gw = request->get_str(request, NULL, "gateway");
        !           517: 
        !           518:        if (!gw || !(gateway = identification_create_from_string(gw)))
        !           519:        {
        !           520:                return send_reply(this, "missing target gateway");
        !           521:        }
        !           522:        switch (gateway->get_type(gateway))
        !           523:        {
        !           524:                case ID_IPV4_ADDR:
        !           525:                case ID_IPV6_ADDR:
        !           526:                case ID_FQDN:
        !           527:                        break;
        !           528:                default:
        !           529:                        return send_reply(this, "unsupported gateway identity");
        !           530:        }
        !           531:        if (peer_ip)
        !           532:        {
        !           533:                ts = parse_peer_ip(peer_ip);
        !           534:                if (!ts)
        !           535:                {
        !           536:                        return send_reply(this, "invalid peer IP selector");
        !           537:                }
        !           538:                DBG1(DBG_CFG, "vici redirect IKE_SAs with src %R to %Y", ts,
        !           539:                         gateway);
        !           540:        }
        !           541:        if (peer_id)
        !           542:        {
        !           543:                identity = identification_create_from_string(peer_id);
        !           544:                if (!identity)
        !           545:                {
        !           546:                        DESTROY_IF(ts);
        !           547:                        return send_reply(this, "invalid peer identity selector");
        !           548:                }
        !           549:                DBG1(DBG_CFG, "vici redirect IKE_SAs with ID '%Y' to %Y", identity,
        !           550:                         gateway);
        !           551:        }
        !           552:        if (ike_id)
        !           553:        {
        !           554:                DBG1(DBG_CFG, "vici redirect IKE_SA #%d to '%Y'", ike_id, gateway);
        !           555:        }
        !           556:        if (ike)
        !           557:        {
        !           558:                DBG1(DBG_CFG, "vici redirect IKE_SA '%s' to '%Y'", ike, gateway);
        !           559:        }
        !           560:        if (!peer_ip && !peer_id && !ike && !ike_id)
        !           561:        {
        !           562:                return send_reply(this, "missing redirect selector");
        !           563:        }
        !           564: 
        !           565:        sas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
        !           566:        while (sas->enumerate(sas, &ike_sa))
        !           567:        {
        !           568:                if (ike_sa->get_version(ike_sa) != IKEV2)
        !           569:                {
        !           570:                        continue;
        !           571:                }
        !           572:                current = ike_sa->get_unique_id(ike_sa);
        !           573:                if (ike_id && ike_id != current)
        !           574:                {
        !           575:                        continue;
        !           576:                }
        !           577:                if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
        !           578:                {
        !           579:                        continue;
        !           580:                }
        !           581:                if (ts && !ts->includes(ts, ike_sa->get_other_host(ike_sa)))
        !           582:                {
        !           583:                        continue;
        !           584:                }
        !           585:                if (identity)
        !           586:                {
        !           587:                        other_id = ike_sa->get_other_eap_id(ike_sa);
        !           588:                        if (!other_id->matches(other_id, identity))
        !           589:                        {
        !           590:                                continue;
        !           591:                        }
        !           592:                }
        !           593:                lib->processor->queue_job(lib->processor,
        !           594:                                (job_t*)redirect_job_create(ike_sa->get_id(ike_sa), gateway));
        !           595:                found++;
        !           596:        }
        !           597:        sas->destroy(sas);
        !           598: 
        !           599:        builder = vici_builder_create();
        !           600:        if (!found)
        !           601:        {
        !           602:                errmsg = "no matching SAs to redirect found";
        !           603:        }
        !           604:        builder->add_kv(builder, "success", errmsg ? "no" : "yes");
        !           605:        builder->add_kv(builder, "matches", "%u", found);
        !           606:        if (errmsg)
        !           607:        {
        !           608:                builder->add_kv(builder, "errmsg", "%s", errmsg);
        !           609:        }
        !           610:        gateway->destroy(gateway);
        !           611:        DESTROY_IF(identity);
        !           612:        DESTROY_IF(ts);
        !           613:        return builder->finalize(builder);
        !           614: }
        !           615: 
        !           616: CALLBACK(install, vici_message_t*,
        !           617:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           618: {
        !           619:        child_cfg_t *child_cfg = NULL;
        !           620:        peer_cfg_t *peer_cfg;
        !           621:        char *child, *ike;
        !           622:        bool ok;
        !           623: 
        !           624:        child = request->get_str(request, NULL, "child");
        !           625:        ike = request->get_str(request, NULL, "ike");
        !           626:        if (!child)
        !           627:        {
        !           628:                return send_reply(this, "missing configuration name");
        !           629:        }
        !           630: 
        !           631:        DBG1(DBG_CFG, "vici install '%s'", child);
        !           632: 
        !           633:        child_cfg = find_child_cfg(child, ike, &peer_cfg);
        !           634:        if (!child_cfg)
        !           635:        {
        !           636:                return send_reply(this, "configuration name not found");
        !           637:        }
        !           638:        switch (child_cfg->get_mode(child_cfg))
        !           639:        {
        !           640:                case MODE_PASS:
        !           641:                case MODE_DROP:
        !           642:                        ok = charon->shunts->install(charon->shunts,
        !           643:                                                                        peer_cfg->get_name(peer_cfg), child_cfg);
        !           644:                        break;
        !           645:                default:
        !           646:                        ok = charon->traps->install(charon->traps, peer_cfg, child_cfg);
        !           647:                        break;
        !           648:        }
        !           649:        peer_cfg->destroy(peer_cfg);
        !           650:        child_cfg->destroy(child_cfg);
        !           651: 
        !           652:        return send_reply(this, ok ? NULL : "installing policy '%s' failed", child);
        !           653: }
        !           654: 
        !           655: CALLBACK(uninstall, vici_message_t*,
        !           656:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           657: {
        !           658:        char *child, *ike;
        !           659: 
        !           660:        child = request->get_str(request, NULL, "child");
        !           661:        ike = request->get_str(request, NULL, "ike");
        !           662:        if (!child)
        !           663:        {
        !           664:                return send_reply(this, "missing configuration name");
        !           665:        }
        !           666: 
        !           667:        DBG1(DBG_CFG, "vici uninstall '%s'", child);
        !           668: 
        !           669:        if (charon->shunts->uninstall(charon->shunts, ike, child))
        !           670:        {
        !           671:                return send_reply(this, NULL);
        !           672:        }
        !           673:        else if (charon->traps->uninstall(charon->traps, ike, child))
        !           674:        {
        !           675:                return send_reply(this, NULL);
        !           676:        }
        !           677:        return send_reply(this, "policy '%s' not found", child);
        !           678: }
        !           679: 
        !           680: CALLBACK(reload_settings, vici_message_t*,
        !           681:        private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
        !           682: {
        !           683:        if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
        !           684:        {
        !           685:                charon->load_loggers(charon);
        !           686:                lib->plugins->reload(lib->plugins, NULL);
        !           687:                return send_reply(this, NULL);
        !           688:        }
        !           689:        return send_reply(this, "reloading '%s' failed", lib->conf);
        !           690: }
        !           691: 
        !           692: static void manage_command(private_vici_control_t *this,
        !           693:                                                   char *name, vici_command_cb_t cb, bool reg)
        !           694: {
        !           695:        this->dispatcher->manage_command(this->dispatcher, name,
        !           696:                                                                         reg ? cb : NULL, this);
        !           697: }
        !           698: 
        !           699: /**
        !           700:  * (Un-)register dispatcher functions
        !           701:  */
        !           702: static void manage_commands(private_vici_control_t *this, bool reg)
        !           703: {
        !           704:        manage_command(this, "initiate", initiate, reg);
        !           705:        manage_command(this, "terminate", terminate, reg);
        !           706:        manage_command(this, "rekey", rekey, reg);
        !           707:        manage_command(this, "redirect", redirect, reg);
        !           708:        manage_command(this, "install", install, reg);
        !           709:        manage_command(this, "uninstall", uninstall, reg);
        !           710:        manage_command(this, "reload-settings", reload_settings, reg);
        !           711:        this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
        !           712: }
        !           713: 
        !           714: METHOD(vici_control_t, destroy, void,
        !           715:        private_vici_control_t *this)
        !           716: {
        !           717:        manage_commands(this, FALSE);
        !           718:        free(this);
        !           719: }
        !           720: 
        !           721: /**
        !           722:  * See header
        !           723:  */
        !           724: vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
        !           725: {
        !           726:        private_vici_control_t *this;
        !           727: 
        !           728:        INIT(this,
        !           729:                .public = {
        !           730:                        .destroy = _destroy,
        !           731:                },
        !           732:                .dispatcher = dispatcher,
        !           733:        );
        !           734: 
        !           735:        manage_commands(this, TRUE);
        !           736: 
        !           737:        return &this->public;
        !           738: }

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