Annotation of embedaddon/strongswan/src/libcharon/config/ike_cfg.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012-2019 Tobias Brunner
        !             3:  * Copyright (C) 2005-2007 Martin Willi
        !             4:  * Copyright (C) 2005 Jan Hutter
        !             5:  * HSR Hochschule fuer Technik Rapperswil
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2 of the License, or (at your
        !            10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            15:  * for more details.
        !            16:  */
        !            17: 
        !            18: #define _GNU_SOURCE /* for stdndup() */
        !            19: #include <string.h>
        !            20: 
        !            21: #include "ike_cfg.h"
        !            22: 
        !            23: #include <daemon.h>
        !            24: 
        !            25: ENUM(ike_version_names, IKE_ANY, IKEV2,
        !            26:        "IKEv1/2",
        !            27:        "IKEv1",
        !            28:        "IKEv2",
        !            29: );
        !            30: 
        !            31: typedef struct private_ike_cfg_t private_ike_cfg_t;
        !            32: 
        !            33: /**
        !            34:  * Private data of an ike_cfg_t object
        !            35:  */
        !            36: struct private_ike_cfg_t {
        !            37: 
        !            38:        /**
        !            39:         * Public part
        !            40:         */
        !            41:        ike_cfg_t public;
        !            42: 
        !            43:        /**
        !            44:         * Number of references hold by others to this ike_cfg
        !            45:         */
        !            46:        refcount_t refcount;
        !            47: 
        !            48:        /**
        !            49:         * IKE version to use
        !            50:         */
        !            51:        ike_version_t version;
        !            52: 
        !            53:        /**
        !            54:         * Address list string for local host
        !            55:         */
        !            56:        char *me;
        !            57: 
        !            58:        /**
        !            59:         * Address list string for remote host
        !            60:         */
        !            61:        char *other;
        !            62: 
        !            63:        /**
        !            64:         * Local single host or DNS names, as allocated char*
        !            65:         */
        !            66:        linked_list_t *my_hosts;
        !            67: 
        !            68:        /**
        !            69:         * Remote single host or DNS names, as allocated char*
        !            70:         */
        !            71:        linked_list_t *other_hosts;
        !            72: 
        !            73:        /**
        !            74:         * Local ranges/subnets this config matches to, as traffic_selector_t*
        !            75:         */
        !            76:        linked_list_t *my_ranges;
        !            77: 
        !            78:        /**
        !            79:         * Remote ranges/subnets this config matches to, as traffic_selector_t*
        !            80:         */
        !            81:        linked_list_t *other_ranges;
        !            82: 
        !            83:        /**
        !            84:         * our source port
        !            85:         */
        !            86:        uint16_t my_port;
        !            87: 
        !            88:        /**
        !            89:         * destination port
        !            90:         */
        !            91:        uint16_t other_port;
        !            92: 
        !            93:        /**
        !            94:         * should we send a certificate request?
        !            95:         */
        !            96:        bool certreq;
        !            97: 
        !            98:        /**
        !            99:         * enforce UDP encapsulation
        !           100:         */
        !           101:        bool force_encap;
        !           102: 
        !           103:        /**
        !           104:         * use IKE fragmentation
        !           105:         */
        !           106:        fragmentation_t fragmentation;
        !           107: 
        !           108:        /**
        !           109:         * childless IKE_SAs
        !           110:         */
        !           111:        childless_t childless;
        !           112: 
        !           113:        /**
        !           114:         * DSCP value to use on sent IKE packets
        !           115:         */
        !           116:        uint8_t dscp;
        !           117: 
        !           118:        /**
        !           119:         * List of proposals to use
        !           120:         */
        !           121:        linked_list_t *proposals;
        !           122: };
        !           123: 
        !           124: METHOD(ike_cfg_t, get_version, ike_version_t,
        !           125:        private_ike_cfg_t *this)
        !           126: {
        !           127:        return this->version;
        !           128: }
        !           129: 
        !           130: METHOD(ike_cfg_t, send_certreq, bool,
        !           131:        private_ike_cfg_t *this)
        !           132: {
        !           133:        return this->certreq;
        !           134: }
        !           135: 
        !           136: METHOD(ike_cfg_t, force_encap_, bool,
        !           137:        private_ike_cfg_t *this)
        !           138: {
        !           139:        return this->force_encap;
        !           140: }
        !           141: 
        !           142: METHOD(ike_cfg_t, fragmentation, fragmentation_t,
        !           143:        private_ike_cfg_t *this)
        !           144: {
        !           145:        return this->fragmentation;
        !           146: }
        !           147: 
        !           148: METHOD(ike_cfg_t, childless, childless_t,
        !           149:        private_ike_cfg_t *this)
        !           150: {
        !           151:        return this->childless;
        !           152: }
        !           153: 
        !           154: /**
        !           155:  * Common function for resolve_me/other
        !           156:  */
        !           157: static host_t* resolve(linked_list_t *hosts, int family, uint16_t port)
        !           158: {
        !           159:        enumerator_t *enumerator;
        !           160:        host_t *host = NULL;
        !           161:        bool tried = FALSE;
        !           162:        char *str;
        !           163: 
        !           164:        enumerator = hosts->create_enumerator(hosts);
        !           165:        while (enumerator->enumerate(enumerator, &str))
        !           166:        {
        !           167:                host = host_create_from_dns(str, family, port);
        !           168:                if (host)
        !           169:                {
        !           170:                        break;
        !           171:                }
        !           172:                tried = TRUE;
        !           173:        }
        !           174:        enumerator->destroy(enumerator);
        !           175: 
        !           176:        if (!host && !tried)
        !           177:        {
        !           178:                /* we have no single host configured, return %any */
        !           179:                host = host_create_any(family ?: AF_INET);
        !           180:                host->set_port(host, port);
        !           181:        }
        !           182:        return host;
        !           183: }
        !           184: 
        !           185: METHOD(ike_cfg_t, resolve_me, host_t*,
        !           186:        private_ike_cfg_t *this, int family)
        !           187: {
        !           188:        return resolve(this->my_hosts, family, this->my_port);
        !           189: }
        !           190: 
        !           191: METHOD(ike_cfg_t, resolve_other, host_t*,
        !           192:        private_ike_cfg_t *this, int family)
        !           193: {
        !           194:        return resolve(this->other_hosts, family, this->other_port);
        !           195: }
        !           196: 
        !           197: /**
        !           198:  * Common function for match_me/other
        !           199:  */
        !           200: static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand)
        !           201: {
        !           202:        enumerator_t *enumerator;
        !           203:        traffic_selector_t *ts;
        !           204:        char *str;
        !           205:        host_t *host;
        !           206:        uint8_t mask;
        !           207:        u_int quality = 0;
        !           208: 
        !           209:        /* try single hosts first */
        !           210:        enumerator = hosts->create_enumerator(hosts);
        !           211:        while (enumerator->enumerate(enumerator, &str))
        !           212:        {
        !           213:                host = host_create_from_dns(str, cand->get_family(cand), 0);
        !           214:                if (host)
        !           215:                {
        !           216:                        if (host->ip_equals(host, cand))
        !           217:                        {
        !           218:                                quality = max(quality, 128 + 1);
        !           219:                        }
        !           220:                        if (host->is_anyaddr(host))
        !           221:                        {
        !           222:                                quality = max(quality, 1);
        !           223:                        }
        !           224:                        host->destroy(host);
        !           225:                }
        !           226:        }
        !           227:        enumerator->destroy(enumerator);
        !           228: 
        !           229:        /* then ranges/subnets */
        !           230:        enumerator = ranges->create_enumerator(ranges);
        !           231:        while (enumerator->enumerate(enumerator, &ts))
        !           232:        {
        !           233:                if (ts->includes(ts, cand))
        !           234:                {
        !           235:                        if (ts->to_subnet(ts, &host, &mask))
        !           236:                        {
        !           237:                                quality = max(quality, mask + 1);
        !           238:                        }
        !           239:                        else
        !           240:                        {
        !           241:                                quality = max(quality, 1);
        !           242:                        }
        !           243:                        host->destroy(host);
        !           244:                }
        !           245:        }
        !           246:        enumerator->destroy(enumerator);
        !           247: 
        !           248:        return quality;
        !           249: }
        !           250: 
        !           251: METHOD(ike_cfg_t, match_me, u_int,
        !           252:        private_ike_cfg_t *this, host_t *host)
        !           253: {
        !           254:        return match(this->my_hosts, this->my_ranges, host);
        !           255: }
        !           256: 
        !           257: METHOD(ike_cfg_t, match_other, u_int,
        !           258:        private_ike_cfg_t *this, host_t *host)
        !           259: {
        !           260:        return match(this->other_hosts, this->other_ranges, host);
        !           261: }
        !           262: 
        !           263: METHOD(ike_cfg_t, get_my_addr, char*,
        !           264:        private_ike_cfg_t *this)
        !           265: {
        !           266:        return this->me;
        !           267: }
        !           268: 
        !           269: METHOD(ike_cfg_t, get_other_addr, char*,
        !           270:        private_ike_cfg_t *this)
        !           271: {
        !           272:        return this->other;
        !           273: }
        !           274: 
        !           275: METHOD(ike_cfg_t, get_my_port, uint16_t,
        !           276:        private_ike_cfg_t *this)
        !           277: {
        !           278:        return this->my_port;
        !           279: }
        !           280: 
        !           281: METHOD(ike_cfg_t, get_other_port, uint16_t,
        !           282:        private_ike_cfg_t *this)
        !           283: {
        !           284:        return this->other_port;
        !           285: }
        !           286: 
        !           287: METHOD(ike_cfg_t, get_dscp, uint8_t,
        !           288:        private_ike_cfg_t *this)
        !           289: {
        !           290:        return this->dscp;
        !           291: }
        !           292: 
        !           293: METHOD(ike_cfg_t, add_proposal, void,
        !           294:        private_ike_cfg_t *this, proposal_t *proposal)
        !           295: {
        !           296:        if (proposal)
        !           297:        {
        !           298:                this->proposals->insert_last(this->proposals, proposal);
        !           299:        }
        !           300: }
        !           301: 
        !           302: METHOD(ike_cfg_t, get_proposals, linked_list_t*,
        !           303:        private_ike_cfg_t *this)
        !           304: {
        !           305:        enumerator_t *enumerator;
        !           306:        proposal_t *current;
        !           307:        linked_list_t *proposals;
        !           308: 
        !           309:        proposals = linked_list_create();
        !           310:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           311:        while (enumerator->enumerate(enumerator, &current))
        !           312:        {
        !           313:                current = current->clone(current, 0);
        !           314:                proposals->insert_last(proposals, current);
        !           315:        }
        !           316:        enumerator->destroy(enumerator);
        !           317: 
        !           318:        DBG2(DBG_CFG, "configured proposals: %#P", proposals);
        !           319: 
        !           320:        return proposals;
        !           321: }
        !           322: 
        !           323: METHOD(ike_cfg_t, has_proposal, bool,
        !           324:        private_ike_cfg_t *this, proposal_t *match, bool private)
        !           325: {
        !           326:        enumerator_t *enumerator;
        !           327:        proposal_t *proposal;
        !           328: 
        !           329:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           330:        while (enumerator->enumerate(enumerator, &proposal))
        !           331:        {
        !           332:                if (proposal->matches(proposal, match,
        !           333:                                                          private ? 0 : PROPOSAL_SKIP_PRIVATE))
        !           334:                {
        !           335:                        enumerator->destroy(enumerator);
        !           336:                        return TRUE;
        !           337:                }
        !           338:        }
        !           339:        enumerator->destroy(enumerator);
        !           340:        return FALSE;
        !           341: }
        !           342: 
        !           343: METHOD(ike_cfg_t, select_proposal, proposal_t*,
        !           344:        private_ike_cfg_t *this, linked_list_t *proposals,
        !           345:        proposal_selection_flag_t flags)
        !           346: {
        !           347:        return proposal_select(this->proposals, proposals, flags);
        !           348: }
        !           349: 
        !           350: METHOD(ike_cfg_t, get_dh_group, diffie_hellman_group_t,
        !           351:        private_ike_cfg_t *this)
        !           352: {
        !           353:        enumerator_t *enumerator;
        !           354:        proposal_t *proposal;
        !           355:        uint16_t dh_group = MODP_NONE;
        !           356: 
        !           357:        enumerator = this->proposals->create_enumerator(this->proposals);
        !           358:        while (enumerator->enumerate(enumerator, &proposal))
        !           359:        {
        !           360:                if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &dh_group, NULL))
        !           361:                {
        !           362:                        break;
        !           363:                }
        !           364:        }
        !           365:        enumerator->destroy(enumerator);
        !           366:        return dh_group;
        !           367: }
        !           368: 
        !           369: METHOD(ike_cfg_t, equals, bool,
        !           370:        private_ike_cfg_t *this, ike_cfg_t *other_public)
        !           371: {
        !           372:        private_ike_cfg_t *other = (private_ike_cfg_t*)other_public;
        !           373: 
        !           374:        if (this == other)
        !           375:        {
        !           376:                return TRUE;
        !           377:        }
        !           378:        if (this->public.equals != other->public.equals)
        !           379:        {
        !           380:                return FALSE;
        !           381:        }
        !           382:        if (!this->proposals->equals_offset(this->proposals, other->proposals,
        !           383:                                                                                offsetof(proposal_t, equals)))
        !           384:        {
        !           385:                return FALSE;
        !           386:        }
        !           387:        return
        !           388:                this->version == other->version &&
        !           389:                this->certreq == other->certreq &&
        !           390:                this->force_encap == other->force_encap &&
        !           391:                this->fragmentation == other->fragmentation &&
        !           392:                this->childless == other->childless &&
        !           393:                streq(this->me, other->me) &&
        !           394:                streq(this->other, other->other) &&
        !           395:                this->my_port == other->my_port &&
        !           396:                this->other_port == other->other_port;
        !           397: }
        !           398: 
        !           399: METHOD(ike_cfg_t, get_ref, ike_cfg_t*,
        !           400:        private_ike_cfg_t *this)
        !           401: {
        !           402:        ref_get(&this->refcount);
        !           403:        return &this->public;
        !           404: }
        !           405: 
        !           406: METHOD(ike_cfg_t, destroy, void,
        !           407:        private_ike_cfg_t *this)
        !           408: {
        !           409:        if (ref_put(&this->refcount))
        !           410:        {
        !           411:                this->proposals->destroy_offset(this->proposals,
        !           412:                                                                                offsetof(proposal_t, destroy));
        !           413:                free(this->me);
        !           414:                free(this->other);
        !           415:                this->my_hosts->destroy_function(this->my_hosts, free);
        !           416:                this->other_hosts->destroy_function(this->other_hosts, free);
        !           417:                this->my_ranges->destroy_offset(this->my_ranges,
        !           418:                                                                                offsetof(traffic_selector_t, destroy));
        !           419:                this->other_ranges->destroy_offset(this->other_ranges,
        !           420:                                                                                offsetof(traffic_selector_t, destroy));
        !           421:                free(this);
        !           422:        }
        !           423: }
        !           424: 
        !           425: /**
        !           426:  * Try to parse a string as subnet
        !           427:  */
        !           428: static traffic_selector_t* make_subnet(char *str)
        !           429: {
        !           430:        char *pos;
        !           431: 
        !           432:        pos = strchr(str, '/');
        !           433:        if (!pos)
        !           434:        {
        !           435:                return NULL;
        !           436:        }
        !           437:        return traffic_selector_create_from_cidr(str, 0, 0, 0);
        !           438: }
        !           439: 
        !           440: /**
        !           441:  * Try to parse a string as an IP range
        !           442:  */
        !           443: static traffic_selector_t* make_range(char *str)
        !           444: {
        !           445:        traffic_selector_t *ts;
        !           446:        ts_type_t type;
        !           447:        host_t *from, *to;
        !           448: 
        !           449:        if (!host_create_from_range(str, &from, &to))
        !           450:        {
        !           451:                return NULL;
        !           452:        }
        !           453:        if (to->get_family(to) == AF_INET)
        !           454:        {
        !           455:                type = TS_IPV4_ADDR_RANGE;
        !           456:        }
        !           457:        else
        !           458:        {
        !           459:                type = TS_IPV6_ADDR_RANGE;
        !           460:        }
        !           461:        ts = traffic_selector_create_from_bytes(0, type,
        !           462:                                                                                        from->get_address(from), 0,
        !           463:                                                                                        to->get_address(to), 0);
        !           464:        from->destroy(from);
        !           465:        to->destroy(to);
        !           466:        return ts;
        !           467: }
        !           468: 
        !           469: /**
        !           470:  * Parse address string into lists of single hosts and ranges/subnets
        !           471:  */
        !           472: static void parse_addresses(char *str, linked_list_t *hosts,
        !           473:                                                        linked_list_t *ranges)
        !           474: {
        !           475:        enumerator_t *enumerator;
        !           476:        traffic_selector_t *ts;
        !           477: 
        !           478:        enumerator = enumerator_create_token(str, ",", " ");
        !           479:        while (enumerator->enumerate(enumerator, &str))
        !           480:        {
        !           481:                ts = make_subnet(str);
        !           482:                if (ts)
        !           483:                {
        !           484:                        ranges->insert_last(ranges, ts);
        !           485:                        continue;
        !           486:                }
        !           487:                ts = make_range(str);
        !           488:                if (ts)
        !           489:                {
        !           490:                        ranges->insert_last(ranges, ts);
        !           491:                        continue;
        !           492:                }
        !           493:                hosts->insert_last(hosts, strdup(str));
        !           494:        }
        !           495:        enumerator->destroy(enumerator);
        !           496: }
        !           497: 
        !           498: /**
        !           499:  * Described in header.
        !           500:  */
        !           501: int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
        !           502: {
        !           503:        private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
        !           504:        enumerator_t *enumerator;
        !           505:        host_t *host;
        !           506:        char *str;
        !           507:        int family = AF_UNSPEC;
        !           508: 
        !           509:        if (local)
        !           510:        {
        !           511:                enumerator = this->my_hosts->create_enumerator(this->my_hosts);
        !           512:        }
        !           513:        else
        !           514:        {
        !           515:                enumerator = this->other_hosts->create_enumerator(this->other_hosts);
        !           516:        }
        !           517:        while (enumerator->enumerate(enumerator, &str))
        !           518:        {
        !           519:                if (streq(str, "%any"))
        !           520:                {       /* ignore %any as its family is undetermined */
        !           521:                        continue;
        !           522:                }
        !           523:                host = host_create_from_string(str, 0);
        !           524:                if (host)
        !           525:                {
        !           526:                        if (family == AF_UNSPEC)
        !           527:                        {
        !           528:                                family = host->get_family(host);
        !           529:                        }
        !           530:                        else if (family != host->get_family(host))
        !           531:                        {
        !           532:                                /* more than one address family defined */
        !           533:                                family = AF_UNSPEC;
        !           534:                                host->destroy(host);
        !           535:                                break;
        !           536:                        }
        !           537:                }
        !           538:                DESTROY_IF(host);
        !           539:        }
        !           540:        enumerator->destroy(enumerator);
        !           541:        return family;
        !           542: }
        !           543: 
        !           544: /**
        !           545:  * Described in header.
        !           546:  */
        !           547: bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local)
        !           548: {
        !           549:        private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
        !           550:        enumerator_t *enumerator;
        !           551:        host_t *host;
        !           552:        char *str;
        !           553:        bool found = FALSE;
        !           554: 
        !           555:        if (local)
        !           556:        {
        !           557:                enumerator = this->my_hosts->create_enumerator(this->my_hosts);
        !           558:        }
        !           559:        else
        !           560:        {
        !           561:                enumerator = this->other_hosts->create_enumerator(this->other_hosts);
        !           562:        }
        !           563:        while (enumerator->enumerate(enumerator, &str))
        !           564:        {
        !           565:                host = host_create_from_string(str, 0);
        !           566:                if (host && addr->ip_equals(addr, host))
        !           567:                {
        !           568:                        host->destroy(host);
        !           569:                        found = TRUE;
        !           570:                        break;
        !           571:                }
        !           572:                DESTROY_IF(host);
        !           573:        }
        !           574:        enumerator->destroy(enumerator);
        !           575:        return found;
        !           576: }
        !           577: 
        !           578: /*
        !           579:  * Described in header
        !           580:  */
        !           581: ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data)
        !           582: {
        !           583:        private_ike_cfg_t *this;
        !           584: 
        !           585:        INIT(this,
        !           586:                .public = {
        !           587:                        .get_version = _get_version,
        !           588:                        .send_certreq = _send_certreq,
        !           589:                        .force_encap = _force_encap_,
        !           590:                        .fragmentation = _fragmentation,
        !           591:                        .childless = _childless,
        !           592:                        .resolve_me = _resolve_me,
        !           593:                        .resolve_other = _resolve_other,
        !           594:                        .match_me = _match_me,
        !           595:                        .match_other = _match_other,
        !           596:                        .get_my_addr = _get_my_addr,
        !           597:                        .get_other_addr = _get_other_addr,
        !           598:                        .get_my_port = _get_my_port,
        !           599:                        .get_other_port = _get_other_port,
        !           600:                        .get_dscp = _get_dscp,
        !           601:                        .add_proposal = _add_proposal,
        !           602:                        .get_proposals = _get_proposals,
        !           603:                        .select_proposal = _select_proposal,
        !           604:                        .has_proposal = _has_proposal,
        !           605:                        .get_dh_group = _get_dh_group,
        !           606:                        .equals = _equals,
        !           607:                        .get_ref = _get_ref,
        !           608:                        .destroy = _destroy,
        !           609:                },
        !           610:                .refcount = 1,
        !           611:                .version = data->version,
        !           612:                .certreq = !data->no_certreq,
        !           613:                .force_encap = data->force_encap,
        !           614:                .fragmentation = data->fragmentation,
        !           615:                .childless = data->childless,
        !           616:                .me = strdup(data->local),
        !           617:                .my_ranges = linked_list_create(),
        !           618:                .my_hosts = linked_list_create(),
        !           619:                .other = strdup(data->remote),
        !           620:                .other_ranges = linked_list_create(),
        !           621:                .other_hosts = linked_list_create(),
        !           622:                .my_port = data->local_port,
        !           623:                .other_port = data->remote_port,
        !           624:                .dscp = data->dscp,
        !           625:                .proposals = linked_list_create(),
        !           626:        );
        !           627: 
        !           628:        parse_addresses(data->local, this->my_hosts, this->my_ranges);
        !           629:        parse_addresses(data->remote, this->other_hosts, this->other_ranges);
        !           630: 
        !           631:        return &this->public;
        !           632: }

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