Annotation of embedaddon/strongswan/src/libcharon/config/ike_cfg.c, revision 1.1.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>