Annotation of embedaddon/strongswan/src/libcharon/plugins/medcli/medcli_config.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008 Martin Willi
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #define _GNU_SOURCE
        !            17: #include <string.h>
        !            18: 
        !            19: #include "medcli_config.h"
        !            20: 
        !            21: #include <daemon.h>
        !            22: #include <processing/jobs/callback_job.h>
        !            23: 
        !            24: typedef struct private_medcli_config_t private_medcli_config_t;
        !            25: 
        !            26: /**
        !            27:  * Name of the mediation connection
        !            28:  */
        !            29: #define MEDIATION_CONN_NAME "medcli-mediation"
        !            30: 
        !            31: /**
        !            32:  * Private data of an medcli_config_t object
        !            33:  */
        !            34: struct private_medcli_config_t {
        !            35: 
        !            36:        /**
        !            37:         * Public part
        !            38:         */
        !            39:        medcli_config_t public;
        !            40: 
        !            41:        /**
        !            42:         * database connection
        !            43:         */
        !            44:        database_t *db;
        !            45: 
        !            46:        /**
        !            47:         * rekey time
        !            48:         */
        !            49:        int rekey;
        !            50: 
        !            51:        /**
        !            52:         * dpd delay
        !            53:         */
        !            54:        int dpd;
        !            55: 
        !            56:        /**
        !            57:         * default ike config
        !            58:         */
        !            59:        ike_cfg_t *ike;
        !            60: };
        !            61: 
        !            62: /**
        !            63:  * create a traffic selector from a CIDR notation string
        !            64:  */
        !            65: static traffic_selector_t *ts_from_string(char *str)
        !            66: {
        !            67:        if (str)
        !            68:        {
        !            69:                traffic_selector_t *ts;
        !            70: 
        !            71:                ts = traffic_selector_create_from_cidr(str, 0, 0, 65535);
        !            72:                if (ts)
        !            73:                {
        !            74:                        return ts;
        !            75:                }
        !            76:        }
        !            77:        return traffic_selector_create_dynamic(0, 0, 65535);
        !            78: }
        !            79: 
        !            80: /**
        !            81:  * Build a mediation config
        !            82:  */
        !            83: static peer_cfg_t *build_mediation_config(private_medcli_config_t *this,
        !            84:                                                                                  peer_cfg_create_t *defaults)
        !            85: {
        !            86:        enumerator_t *e;
        !            87:        auth_cfg_t *auth;
        !            88:        ike_cfg_t *ike_cfg;
        !            89:        peer_cfg_t *med_cfg;
        !            90:        ike_cfg_create_t ike = {
        !            91:                .version = IKEV2,
        !            92:                .local = "0.0.0.0",
        !            93:                .local_port = charon->socket->get_port(charon->socket, FALSE),
        !            94:                .remote_port = IKEV2_UDP_PORT,
        !            95:                .no_certreq = TRUE,
        !            96:        };
        !            97:        peer_cfg_create_t peer = *defaults;
        !            98:        chunk_t me, other;
        !            99: 
        !           100:        /* query mediation server config:
        !           101:         * - build ike_cfg/peer_cfg for mediation connection on-the-fly
        !           102:         */
        !           103:        e = this->db->query(this->db,
        !           104:                        "SELECT Address, ClientConfig.KeyId, MediationServerConfig.KeyId "
        !           105:                        "FROM MediationServerConfig JOIN ClientConfig",
        !           106:                        DB_TEXT, DB_BLOB, DB_BLOB);
        !           107:        if (!e || !e->enumerate(e, &ike.remote, &me, &other))
        !           108:        {
        !           109:                DESTROY_IF(e);
        !           110:                return NULL;
        !           111:        }
        !           112:        ike_cfg = ike_cfg_create(&ike);
        !           113:        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        !           114:        ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
        !           115: 
        !           116:        peer.mediation = TRUE;
        !           117:        med_cfg = peer_cfg_create(MEDIATION_CONN_NAME, ike_cfg, &peer);
        !           118:        e->destroy(e);
        !           119: 
        !           120:        auth = auth_cfg_create();
        !           121:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           122:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           123:                          identification_create_from_encoding(ID_KEY_ID, me));
        !           124:        med_cfg->add_auth_cfg(med_cfg, auth, TRUE);
        !           125:        auth = auth_cfg_create();
        !           126:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           127:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           128:                          identification_create_from_encoding(ID_KEY_ID, other));
        !           129:        med_cfg->add_auth_cfg(med_cfg, auth, FALSE);
        !           130:        return med_cfg;
        !           131: }
        !           132: 
        !           133: METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
        !           134:        private_medcli_config_t *this, char *name)
        !           135: {
        !           136:        enumerator_t *e;
        !           137:        auth_cfg_t *auth;
        !           138:        peer_cfg_t *peer_cfg;
        !           139:        child_cfg_t *child_cfg;
        !           140:        chunk_t me, other;
        !           141:        char *local_net, *remote_net;
        !           142:        peer_cfg_create_t peer = {
        !           143:                .cert_policy = CERT_NEVER_SEND,
        !           144:                .unique = UNIQUE_REPLACE,
        !           145:                .keyingtries = 1,
        !           146:                .rekey_time = this->rekey * 60,
        !           147:                .jitter_time = this->rekey * 5,
        !           148:                .over_time = this->rekey * 3,
        !           149:                .dpd = this->dpd,
        !           150:        };
        !           151:        child_cfg_create_t child = {
        !           152:                .lifetime = {
        !           153:                        .time = {
        !           154:                                .life = this->rekey * 60 + this->rekey,
        !           155:                                .rekey = this->rekey,
        !           156:                                .jitter = this->rekey
        !           157:                        },
        !           158:                },
        !           159:                .mode = MODE_TUNNEL,
        !           160:        };
        !           161: 
        !           162:        if (streq(name, "medcli-mediation"))
        !           163:        {
        !           164:                return build_mediation_config(this, &peer);
        !           165:        }
        !           166: 
        !           167:        /* query mediated config:
        !           168:         * - use any-any ike_cfg
        !           169:         * - build peer_cfg on-the-fly using med_cfg
        !           170:         * - add a child_cfg
        !           171:         */
        !           172:        e = this->db->query(this->db,
        !           173:                        "SELECT ClientConfig.KeyId, Connection.KeyId, "
        !           174:                        "Connection.LocalSubnet, Connection.RemoteSubnet "
        !           175:                        "FROM ClientConfig JOIN Connection "
        !           176:                        "WHERE Active AND Alias = ?", DB_TEXT, name,
        !           177:                        DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT);
        !           178:        if (!e || !e->enumerate(e, &me, &other, &local_net, &remote_net))
        !           179:        {
        !           180:                DESTROY_IF(e);
        !           181:                return NULL;
        !           182:        }
        !           183:        peer.mediated_by = MEDIATION_CONN_NAME;
        !           184:        peer.peer_id = identification_create_from_encoding(ID_KEY_ID, other);
        !           185:        peer_cfg = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
        !           186: 
        !           187:        auth = auth_cfg_create();
        !           188:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           189:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           190:                          identification_create_from_encoding(ID_KEY_ID, me));
        !           191:        peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
        !           192:        auth = auth_cfg_create();
        !           193:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           194:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           195:                          identification_create_from_encoding(ID_KEY_ID, other));
        !           196:        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
        !           197: 
        !           198:        child_cfg = child_cfg_create(name, &child);
        !           199:        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        !           200:        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        !           201:        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
        !           202:        child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
        !           203:        peer_cfg->add_child_cfg(peer_cfg, child_cfg);
        !           204:        e->destroy(e);
        !           205:        return peer_cfg;
        !           206: }
        !           207: 
        !           208: METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
        !           209:        private_medcli_config_t *this, host_t *me, host_t *other)
        !           210: {
        !           211:        return enumerator_create_single(this->ike, NULL);
        !           212: }
        !           213: 
        !           214: typedef struct {
        !           215:        /** implements enumerator */
        !           216:        enumerator_t public;
        !           217:        /** inner SQL enumerator */
        !           218:        enumerator_t *inner;
        !           219:        /** currently enumerated peer config */
        !           220:        peer_cfg_t *current;
        !           221:        /** ike cfg to use in peer cfg */
        !           222:        ike_cfg_t *ike;
        !           223:        /** rekey time */
        !           224:        int rekey;
        !           225:        /** dpd time */
        !           226:        int dpd;
        !           227: } peer_enumerator_t;
        !           228: 
        !           229: METHOD(enumerator_t, peer_enumerator_enumerate, bool,
        !           230:        peer_enumerator_t *this, va_list args)
        !           231: {
        !           232:        char *name, *local_net, *remote_net;
        !           233:        chunk_t me, other;
        !           234:        peer_cfg_t **cfg;
        !           235:        child_cfg_t *child_cfg;
        !           236:        auth_cfg_t *auth;
        !           237:        peer_cfg_create_t peer = {
        !           238:                .cert_policy = CERT_NEVER_SEND,
        !           239:                .unique = UNIQUE_REPLACE,
        !           240:                .keyingtries = 1,
        !           241:                .rekey_time = this->rekey * 60,
        !           242:                .jitter_time = this->rekey * 5,
        !           243:                .over_time = this->rekey * 3,
        !           244:                .dpd = this->dpd,
        !           245:        };
        !           246:        child_cfg_create_t child = {
        !           247:                .lifetime = {
        !           248:                        .time = {
        !           249:                                .life = this->rekey * 60 + this->rekey,
        !           250:                                .rekey = this->rekey,
        !           251:                                .jitter = this->rekey
        !           252:                        },
        !           253:                },
        !           254:                .mode = MODE_TUNNEL,
        !           255:        };
        !           256: 
        !           257:        VA_ARGS_VGET(args, cfg);
        !           258: 
        !           259:        DESTROY_IF(this->current);
        !           260:        if (!this->inner->enumerate(this->inner, &name, &me, &other,
        !           261:                                                                &local_net, &remote_net))
        !           262:        {
        !           263:                this->current = NULL;
        !           264:                return FALSE;
        !           265:        }
        !           266:        this->current = peer_cfg_create(name, this->ike->get_ref(this->ike), &peer);
        !           267: 
        !           268:        auth = auth_cfg_create();
        !           269:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           270:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           271:                          identification_create_from_encoding(ID_KEY_ID, me));
        !           272:        this->current->add_auth_cfg(this->current, auth, TRUE);
        !           273:        auth = auth_cfg_create();
        !           274:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           275:        auth->add(auth, AUTH_RULE_IDENTITY,
        !           276:                          identification_create_from_encoding(ID_KEY_ID, other));
        !           277:        this->current->add_auth_cfg(this->current, auth, FALSE);
        !           278: 
        !           279:        child_cfg = child_cfg_create(name, &child);
        !           280:        child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        !           281:        child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        !           282:        child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
        !           283:        child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
        !           284:        this->current->add_child_cfg(this->current, child_cfg);
        !           285:        *cfg = this->current;
        !           286:        return TRUE;
        !           287: }
        !           288: 
        !           289: METHOD(enumerator_t, peer_enumerator_destroy, void,
        !           290:        peer_enumerator_t *this)
        !           291: {
        !           292:        DESTROY_IF(this->current);
        !           293:        this->inner->destroy(this->inner);
        !           294:        free(this);
        !           295: }
        !           296: 
        !           297: METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
        !           298:        private_medcli_config_t *this, identification_t *me,
        !           299:        identification_t *other)
        !           300: {
        !           301:        peer_enumerator_t *e;
        !           302: 
        !           303:        INIT(e,
        !           304:                .public = {
        !           305:                        .enumerate = enumerator_enumerate_default,
        !           306:                        .venumerate = _peer_enumerator_enumerate,
        !           307:                        .destroy = _peer_enumerator_destroy,
        !           308:                },
        !           309:                .ike = this->ike,
        !           310:                .rekey = this->rekey,
        !           311:                .dpd = this->dpd,
        !           312:        );
        !           313: 
        !           314:        /* filter on IDs: NULL or ANY or matching KEY_ID */
        !           315:        e->inner = this->db->query(this->db,
        !           316:                        "SELECT Alias, ClientConfig.KeyId, Connection.KeyId, "
        !           317:                        "Connection.LocalSubnet, Connection.RemoteSubnet "
        !           318:                        "FROM ClientConfig JOIN Connection "
        !           319:                        "WHERE Active AND "
        !           320:                        "(? OR ClientConfig.KeyId = ?) AND (? OR Connection.KeyId = ?)",
        !           321:                        DB_INT, me == NULL || me->get_type(me) == ID_ANY,
        !           322:                        DB_BLOB, me && me->get_type(me) == ID_KEY_ID ?
        !           323:                                me->get_encoding(me) : chunk_empty,
        !           324:                        DB_INT, other == NULL || other->get_type(other) == ID_ANY,
        !           325:                        DB_BLOB, other && other->get_type(other) == ID_KEY_ID ?
        !           326:                                other->get_encoding(other) : chunk_empty,
        !           327:                        DB_TEXT, DB_BLOB, DB_BLOB, DB_TEXT, DB_TEXT);
        !           328:        if (!e->inner)
        !           329:        {
        !           330:                free(e);
        !           331:                return NULL;
        !           332:        }
        !           333:        return &e->public;
        !           334: }
        !           335: 
        !           336: /**
        !           337:  * initiate a peer config
        !           338:  */
        !           339: static job_requeue_t initiate_config(peer_cfg_t *peer_cfg)
        !           340: {
        !           341:        enumerator_t *enumerator;
        !           342:        child_cfg_t *child_cfg = NULL;;
        !           343: 
        !           344:        enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
        !           345:        enumerator->enumerate(enumerator, &child_cfg);
        !           346:        if (child_cfg)
        !           347:        {
        !           348:                child_cfg->get_ref(child_cfg);
        !           349:                peer_cfg->get_ref(peer_cfg);
        !           350:                enumerator->destroy(enumerator);
        !           351:                charon->controller->initiate(charon->controller,
        !           352:                                                                         peer_cfg, child_cfg, NULL, NULL, 0, FALSE);
        !           353:        }
        !           354:        else
        !           355:        {
        !           356:                enumerator->destroy(enumerator);
        !           357:        }
        !           358:        return JOB_REQUEUE_NONE;
        !           359: }
        !           360: 
        !           361: /**
        !           362:  * schedule initiation of all "active" connections
        !           363:  */
        !           364: static void schedule_autoinit(private_medcli_config_t *this)
        !           365: {
        !           366:        enumerator_t *e;
        !           367:        char *name;
        !           368: 
        !           369:        e = this->db->query(this->db, "SELECT Alias FROM Connection WHERE Active",
        !           370:                                                DB_TEXT);
        !           371:        if (e)
        !           372:        {
        !           373:                while (e->enumerate(e, &name))
        !           374:                {
        !           375:                        peer_cfg_t *peer_cfg;
        !           376: 
        !           377:                        peer_cfg = get_peer_cfg_by_name(this, name);
        !           378:                        if (peer_cfg)
        !           379:                        {
        !           380:                                /* schedule asynchronous initiation job */
        !           381:                                lib->processor->queue_job(lib->processor,
        !           382:                                                (job_t*)callback_job_create(
        !           383:                                                                        (callback_job_cb_t)initiate_config,
        !           384:                                                                        peer_cfg, (void*)peer_cfg->destroy, NULL));
        !           385:                        }
        !           386:                }
        !           387:                e->destroy(e);
        !           388:        }
        !           389: }
        !           390: 
        !           391: METHOD(medcli_config_t, destroy, void,
        !           392:        private_medcli_config_t *this)
        !           393: {
        !           394:        this->ike->destroy(this->ike);
        !           395:        free(this);
        !           396: }
        !           397: 
        !           398: /**
        !           399:  * Described in header.
        !           400:  */
        !           401: medcli_config_t *medcli_config_create(database_t *db)
        !           402: {
        !           403:        private_medcli_config_t *this;
        !           404:        ike_cfg_create_t ike = {
        !           405:                .version = IKEV2,
        !           406:                .local = "0.0.0.0",
        !           407:                .local_port = charon->socket->get_port(charon->socket, FALSE),
        !           408:                .remote = "0.0.0.0",
        !           409:                .remote_port = IKEV2_UDP_PORT,
        !           410:                .no_certreq = TRUE,
        !           411:        };
        !           412: 
        !           413:        INIT(this,
        !           414:                .public = {
        !           415:                        .backend = {
        !           416:                                .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
        !           417:                                .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
        !           418:                                .get_peer_cfg_by_name = _get_peer_cfg_by_name,
        !           419:                        },
        !           420:                        .destroy = _destroy,
        !           421:                },
        !           422:                .db = db,
        !           423:                .rekey = lib->settings->get_time(lib->settings, "medcli.rekey", 1200),
        !           424:                .dpd = lib->settings->get_time(lib->settings, "medcli.dpd", 300),
        !           425:                .ike = ike_cfg_create(&ike),
        !           426:        );
        !           427:        this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
        !           428:        this->ike->add_proposal(this->ike, proposal_create_default_aead(PROTO_IKE));
        !           429: 
        !           430:        schedule_autoinit(this);
        !           431: 
        !           432:        return &this->public;
        !           433: }

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