Annotation of embedaddon/strongswan/src/libcharon/plugins/unity/unity_narrow.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2014 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2012 Martin Willi
                      6:  * Copyright (C) 2012 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "unity_narrow.h"
                     20: 
                     21: #include <daemon.h>
                     22: #include <encoding/payloads/id_payload.h>
                     23: #include <collections/hashtable.h>
                     24: 
                     25: typedef struct private_unity_narrow_t private_unity_narrow_t;
                     26: 
                     27: /**
                     28:  * Private data of an unity_narrow_t object.
                     29:  */
                     30: struct private_unity_narrow_t {
                     31: 
                     32:        /**
                     33:         * Public unity_narrow_t interface.
                     34:         */
                     35:        unity_narrow_t public;
                     36: 
                     37:        /**
                     38:         * Unity attribute handler
                     39:         */
                     40:        unity_handler_t *handler;
                     41: 
                     42:        /**
                     43:         * IKE_SAs for which we received 0.0.0.0/0 as remote traffic selector
                     44:         */
                     45:        hashtable_t *wildcard_ts;
                     46: };
                     47: 
                     48: /**
                     49:  * Narrow the given received traffic selector with the child configuration and
                     50:  * put them into the given list of TS
                     51:  */
                     52: static void narrow_ts(child_cfg_t *cfg, traffic_selector_t *ts,
                     53:                                          linked_list_t *list)
                     54: {
                     55:        linked_list_t *received, *selected;
                     56: 
                     57:        received = linked_list_create();
                     58:        received->insert_last(received, ts);
                     59:        selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL, FALSE);
                     60:        while (selected->remove_first(selected, (void**)&ts) == SUCCESS)
                     61:        {
                     62:                list->insert_last(list, ts);
                     63:        }
                     64:        selected->destroy(selected);
                     65:        received->destroy(received);
                     66: }
                     67: 
                     68: /**
                     69:  * Narrow TS as initiator to Unity Split-Include/Local-LAN
                     70:  */
                     71: static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
                     72:                                                         child_cfg_t *cfg, linked_list_t *remote)
                     73: {
                     74:        traffic_selector_t *current, *orig = NULL;
                     75:        enumerator_t *enumerator;
                     76: 
                     77:        enumerator = this->handler->create_include_enumerator(this->handler,
                     78:                                                                                        ike_sa->get_id(ike_sa));
                     79:        while (enumerator->enumerate(enumerator, &current))
                     80:        {
                     81:                if (orig == NULL)
                     82:                {       /* got one, replace original TS */
                     83:                        if (remote->remove_first(remote, (void**)&orig) != SUCCESS)
                     84:                        {
                     85:                                break;
                     86:                        }
                     87:                }
                     88:                narrow_ts(cfg, current, remote);
                     89:        }
                     90:        enumerator->destroy(enumerator);
                     91:        if (orig)
                     92:        {
                     93:                DBG1(DBG_CFG, "narrowed CHILD_SA to %N %#R",
                     94:                         configuration_attribute_type_names,
                     95:                         UNITY_SPLIT_INCLUDE, remote);
                     96:                orig->destroy(orig);
                     97:        }
                     98:        else
                     99:        {       /* since we originally changed the traffic selector to 0.0.0.0/0 local
                    100:                 * narrowing is not applied if no Split-Include attrs are received */
                    101:                if (remote->remove_first(remote, (void**)&orig) == SUCCESS)
                    102:                {
                    103:                        narrow_ts(cfg, orig, remote);
                    104:                        orig->destroy(orig);
                    105:                }
                    106:        }
                    107: }
                    108: 
                    109: /**
                    110:  * As initiator and responder, bump up TS to 0.0.0.0/0 for on-the-wire bits
                    111:  */
                    112: static void narrow_pre(linked_list_t *list, char *side)
                    113: {
                    114:        traffic_selector_t *ts;
                    115: 
                    116:        while (list->remove_first(list, (void**)&ts) == SUCCESS)
                    117:        {
                    118:                ts->destroy(ts);
                    119:        }
                    120:        ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
                    121:                                                                                         "0.0.0.0", 0,
                    122:                                                                                         "255.255.255.255", 65535);
                    123:        if (ts)
                    124:        {
                    125:                DBG2(DBG_CFG, "changing proposed traffic selectors for %s:", side);
                    126:                DBG2(DBG_CFG, " %R", ts);
                    127:                list->insert_last(list, ts);
                    128:        }
                    129: }
                    130: 
                    131: /**
                    132:  * As responder, narrow down TS to configuration for installation
                    133:  */
                    134: static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local)
                    135: {
                    136:        traffic_selector_t *ts;
                    137:        linked_list_t *configured;
                    138: 
                    139:        while (local->remove_first(local, (void**)&ts) == SUCCESS)
                    140:        {
                    141:                ts->destroy(ts);
                    142:        }
                    143:        configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL,
                    144:                                                                                                  FALSE);
                    145: 
                    146:        while (configured->remove_first(configured, (void**)&ts) == SUCCESS)
                    147:        {
                    148:                local->insert_last(local, ts);
                    149:        }
                    150:        configured->destroy(configured);
                    151: }
                    152: 
                    153: /**
                    154:  * Check if any Split-Include attributes are active on this IKE_SA
                    155:  */
                    156: static bool has_split_includes(private_unity_narrow_t *this, ike_sa_t *ike_sa)
                    157: {
                    158:        enumerator_t *enumerator;
                    159:        traffic_selector_t *ts;
                    160:        bool has;
                    161: 
                    162:        enumerator = this->handler->create_include_enumerator(this->handler,
                    163:                                                                                                ike_sa->get_id(ike_sa));
                    164:        has = enumerator->enumerate(enumerator, &ts);
                    165:        enumerator->destroy(enumerator);
                    166: 
                    167:        return has;
                    168: }
                    169: 
                    170: METHOD(listener_t, narrow, bool,
                    171:        private_unity_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
                    172:        narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
                    173: {
                    174:        if (ike_sa->get_version(ike_sa) == IKEV1 &&
                    175:                ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
                    176:        {
                    177:                /* depending on who initiates a rekeying the hooks will not match the
                    178:                 * roles in the IKE_SA */
                    179:                if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
                    180:                {
                    181:                        switch (type)
                    182:                        {
                    183:                                case NARROW_INITIATOR_PRE_AUTH:
                    184:                                case NARROW_RESPONDER:
                    185:                                        if (has_split_includes(this, ike_sa))
                    186:                                        {
                    187:                                                narrow_pre(remote, "other");
                    188:                                        }
                    189:                                        break;
                    190:                                case NARROW_INITIATOR_POST_AUTH:
                    191:                                case NARROW_RESPONDER_POST:
                    192:                                        narrow_initiator(this, ike_sa,
                    193:                                                                         child_sa->get_config(child_sa), remote);
                    194:                                        break;
                    195:                                default:
                    196:                                        break;
                    197:                        }
                    198:                }
                    199:                else
                    200:                {
                    201:                        switch (type)
                    202:                        {
                    203:                                case NARROW_INITIATOR_PRE_AUTH:
                    204:                                case NARROW_RESPONDER:
                    205:                                        if (this->wildcard_ts->get(this->wildcard_ts, ike_sa))
                    206:                                        {
                    207:                                                narrow_pre(local, "us");
                    208: 
                    209:                                        }
                    210:                                        break;
                    211:                                case NARROW_INITIATOR_POST_AUTH:
                    212:                                case NARROW_RESPONDER_POST:
                    213:                                        if (this->wildcard_ts->get(this->wildcard_ts, ike_sa))
                    214:                                        {
                    215:                                                narrow_responder_post(child_sa->get_config(child_sa),
                    216:                                                                                          local);
                    217:                                        }
                    218:                                        break;
                    219:                                default:
                    220:                                        break;
                    221:                        }
                    222:                }
                    223:        }
                    224:        return TRUE;
                    225: }
                    226: 
                    227: METHOD(listener_t, message, bool,
                    228:        private_unity_narrow_t *this, ike_sa_t *ike_sa, message_t *message,
                    229:        bool incoming, bool plain)
                    230: {
                    231:        traffic_selector_t *tsr = NULL, *wildcard;
                    232:        enumerator_t *enumerator;
                    233:        id_payload_t *id_payload;
                    234:        payload_t *payload;
                    235:        bool first = TRUE;
                    236: 
                    237:        if (!incoming || !plain ||
                    238:                message->get_exchange_type(message) != QUICK_MODE ||
                    239:                !ike_sa || !ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
                    240:        {
                    241:                return TRUE;
                    242:        }
                    243:        enumerator = message->create_payload_enumerator(message);
                    244:        while (enumerator->enumerate(enumerator, &payload))
                    245:        {
                    246:                if (payload->get_type(payload) == PLV1_ID)
                    247:                {
                    248:                        if (!first)
                    249:                        {
                    250:                                id_payload = (id_payload_t*)payload;
                    251:                                tsr = id_payload->get_ts(id_payload);
                    252:                                break;
                    253:                        }
                    254:                        first = FALSE;
                    255:                }
                    256:        }
                    257:        enumerator->destroy(enumerator);
                    258:        if (!tsr)
                    259:        {
                    260:                return TRUE;
                    261:        }
                    262:        wildcard = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535);
                    263:        if (tsr->equals(tsr, wildcard))
                    264:        {
                    265:                this->wildcard_ts->put(this->wildcard_ts, ike_sa, ike_sa);
                    266:        }
                    267:        else
                    268:        {
                    269:                this->wildcard_ts->remove(this->wildcard_ts, ike_sa);
                    270:        }
                    271:        wildcard->destroy(wildcard);
                    272:        tsr->destroy(tsr);
                    273:        return TRUE;
                    274: }
                    275: 
                    276: METHOD(listener_t, ike_updown, bool,
                    277:        private_unity_narrow_t *this, ike_sa_t *ike_sa, bool up)
                    278: {
                    279:        if (!up)
                    280:        {
                    281:                this->wildcard_ts->remove(this->wildcard_ts, ike_sa);
                    282:        }
                    283:        return TRUE;
                    284: }
                    285: 
                    286: METHOD(unity_narrow_t, destroy, void,
                    287:        private_unity_narrow_t *this)
                    288: {
                    289:        this->wildcard_ts->destroy(this->wildcard_ts);
                    290:        free(this);
                    291: }
                    292: 
                    293: /**
                    294:  * See header
                    295:  */
                    296: unity_narrow_t *unity_narrow_create(unity_handler_t *handler)
                    297: {
                    298:        private_unity_narrow_t *this;
                    299: 
                    300:        INIT(this,
                    301:                .public = {
                    302:                        .listener = {
                    303:                                .narrow = _narrow,
                    304:                                .message = _message,
                    305:                                .ike_updown = _ike_updown,
                    306:                        },
                    307:                        .destroy = _destroy,
                    308:                },
                    309:                .handler = handler,
                    310:                .wildcard_ts = hashtable_create(hashtable_hash_ptr,
                    311:                                                                                hashtable_equals_ptr, 4),
                    312:        );
                    313: 
                    314:        return &this->public;
                    315: }

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