Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_config.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2007 Martin Willi
                      3:  * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "ike_config.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <encoding/payloads/cp_payload.h>
                     21: 
                     22: typedef struct private_ike_config_t private_ike_config_t;
                     23: 
                     24: /**
                     25:  * Private members of a ike_config_t task.
                     26:  */
                     27: struct private_ike_config_t {
                     28: 
                     29:        /**
                     30:         * Public methods and task_t interface.
                     31:         */
                     32:        ike_config_t public;
                     33: 
                     34:        /**
                     35:         * Assigned IKE_SA.
                     36:         */
                     37:        ike_sa_t *ike_sa;
                     38: 
                     39:        /**
                     40:         * Are we the initiator?
                     41:         */
                     42:        bool initiator;
                     43: 
                     44:        /**
                     45:         * Did we request a virtual IP?
                     46:         */
                     47:        bool vip_requested;
                     48: 
                     49:        /**
                     50:         * Received list of virtual IPs, host_t*
                     51:         */
                     52:        linked_list_t *vips;
                     53: 
                     54:        /**
                     55:         * list of attributes requested and its handler, entry_t
                     56:         */
                     57:        linked_list_t *requested;
                     58: };
                     59: 
                     60: /**
                     61:  * Entry for a requested attribute and the requesting handler
                     62:  */
                     63: typedef struct {
                     64:        /** attribute requested */
                     65:        configuration_attribute_type_t type;
                     66:        /** handler requesting this attribute */
                     67:        attribute_handler_t *handler;
                     68: } entry_t;
                     69: 
                     70: /**
                     71:  * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
                     72:  */
                     73: static configuration_attribute_t *build_vip(host_t *vip)
                     74: {
                     75:        configuration_attribute_type_t type;
                     76:        chunk_t chunk, prefix;
                     77: 
                     78:        if (vip->get_family(vip) == AF_INET)
                     79:        {
                     80:                type = INTERNAL_IP4_ADDRESS;
                     81:                if (vip->is_anyaddr(vip))
                     82:                {
                     83:                        chunk = chunk_empty;
                     84:                }
                     85:                else
                     86:                {
                     87:                        chunk = vip->get_address(vip);
                     88:                }
                     89:        }
                     90:        else
                     91:        {
                     92:                type = INTERNAL_IP6_ADDRESS;
                     93:                if (vip->is_anyaddr(vip))
                     94:                {
                     95:                        chunk = chunk_empty;
                     96:                }
                     97:                else
                     98:                {
                     99:                        prefix = chunk_alloca(1);
                    100:                        *prefix.ptr = 64;
                    101:                        chunk = vip->get_address(vip);
                    102:                        chunk = chunk_cata("cc", chunk, prefix);
                    103:                }
                    104:        }
                    105:        return configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
                    106:                                                                                                type, chunk);
                    107: }
                    108: 
                    109: /**
                    110:  * Handle a received attribute as initiator
                    111:  */
                    112: static void handle_attribute(private_ike_config_t *this,
                    113:                                                         configuration_attribute_t *ca)
                    114: {
                    115:        attribute_handler_t *handler = NULL;
                    116:        enumerator_t *enumerator;
                    117:        entry_t *entry;
                    118: 
                    119:        /* find the handler which requested this attribute */
                    120:        enumerator = this->requested->create_enumerator(this->requested);
                    121:        while (enumerator->enumerate(enumerator, &entry))
                    122:        {
                    123:                if (entry->type == ca->get_type(ca))
                    124:                {
                    125:                        handler = entry->handler;
                    126:                        this->requested->remove_at(this->requested, enumerator);
                    127:                        free(entry);
                    128:                        break;
                    129:                }
                    130:        }
                    131:        enumerator->destroy(enumerator);
                    132: 
                    133:        /* and pass it to the handle function */
                    134:        handler = charon->attributes->handle(charon->attributes,
                    135:                                        this->ike_sa, handler, ca->get_type(ca), ca->get_chunk(ca));
                    136:        this->ike_sa->add_configuration_attribute(this->ike_sa,
                    137:                                                        handler, ca->get_type(ca), ca->get_chunk(ca));
                    138: }
                    139: 
                    140: /**
                    141:  * process a single configuration attribute
                    142:  */
                    143: static void process_attribute(private_ike_config_t *this,
                    144:                                                          configuration_attribute_t *ca)
                    145: {
                    146:        host_t *ip;
                    147:        chunk_t addr;
                    148:        int family = AF_INET6;
                    149: 
                    150:        switch (ca->get_type(ca))
                    151:        {
                    152:                case INTERNAL_IP4_ADDRESS:
                    153:                        family = AF_INET;
                    154:                        /* fall */
                    155:                case INTERNAL_IP6_ADDRESS:
                    156:                {
                    157:                        if (this->initiator && !this->vip_requested)
                    158:                        {
                    159:                                handle_attribute(this, ca);
                    160:                                return;
                    161:                        }
                    162: 
                    163:                        addr = ca->get_chunk(ca);
                    164:                        if (addr.len == 0)
                    165:                        {
                    166:                                ip = host_create_any(family);
                    167:                        }
                    168:                        else
                    169:                        {
                    170:                                /* skip prefix byte in IPv6 payload*/
                    171:                                if (family == AF_INET6)
                    172:                                {
                    173:                                        addr.len--;
                    174:                                }
                    175:                                ip = host_create_from_chunk(family, addr, 0);
                    176:                        }
                    177:                        if (ip)
                    178:                        {
                    179:                                this->vips->insert_last(this->vips, ip);
                    180:                        }
                    181:                        break;
                    182:                }
                    183:                case INTERNAL_IP4_SERVER:
                    184:                case INTERNAL_IP6_SERVER:
                    185:                        /* assume it's a Windows client if we see proprietary attributes */
                    186:                        this->ike_sa->enable_extension(this->ike_sa, EXT_MS_WINDOWS);
                    187:                        /* fall */
                    188:                default:
                    189:                {
                    190:                        if (this->initiator)
                    191:                        {
                    192:                                handle_attribute(this, ca);
                    193:                        }
                    194:                }
                    195:        }
                    196: }
                    197: 
                    198: /**
                    199:  * Scan for configuration payloads and attributes
                    200:  */
                    201: static void process_payloads(private_ike_config_t *this, message_t *message)
                    202: {
                    203:        enumerator_t *enumerator, *attributes;
                    204:        payload_t *payload;
                    205: 
                    206:        enumerator = message->create_payload_enumerator(message);
                    207:        while (enumerator->enumerate(enumerator, &payload))
                    208:        {
                    209:                if (payload->get_type(payload) == PLV2_CONFIGURATION)
                    210:                {
                    211:                        cp_payload_t *cp = (cp_payload_t*)payload;
                    212:                        configuration_attribute_t *ca;
                    213: 
                    214:                        switch (cp->get_type(cp))
                    215:                        {
                    216:                                case CFG_REQUEST:
                    217:                                case CFG_REPLY:
                    218:                                {
                    219:                                        attributes = cp->create_attribute_enumerator(cp);
                    220:                                        while (attributes->enumerate(attributes, &ca))
                    221:                                        {
                    222:                                                DBG2(DBG_IKE, "processing %N attribute",
                    223:                                                         configuration_attribute_type_names, ca->get_type(ca));
                    224:                                                process_attribute(this, ca);
                    225:                                        }
                    226:                                        attributes->destroy(attributes);
                    227:                                        break;
                    228:                                }
                    229:                                default:
                    230:                                        DBG1(DBG_IKE, "ignoring %N config payload",
                    231:                                                 config_type_names, cp->get_type(cp));
                    232:                                        break;
                    233:                        }
                    234:                }
                    235:        }
                    236:        enumerator->destroy(enumerator);
                    237: }
                    238: 
                    239: METHOD(task_t, build_i, status_t,
                    240:        private_ike_config_t *this, message_t *message)
                    241: {
                    242:        if (message->get_message_id(message) == 1)
                    243:        {       /* in first IKE_AUTH only */
                    244:                cp_payload_t *cp = NULL;
                    245:                enumerator_t *enumerator;
                    246:                attribute_handler_t *handler;
                    247:                peer_cfg_t *config;
                    248:                configuration_attribute_type_t type;
                    249:                chunk_t data;
                    250:                linked_list_t *vips;
                    251:                host_t *host;
                    252: 
                    253:                vips = linked_list_create();
                    254: 
                    255:                /* reuse virtual IP if we already have one */
                    256:                enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
                    257:                                                                                                                                TRUE);
                    258:                while (enumerator->enumerate(enumerator, &host))
                    259:                {
                    260:                        vips->insert_last(vips, host);
                    261:                }
                    262:                enumerator->destroy(enumerator);
                    263: 
                    264:                if (vips->get_count(vips) == 0)
                    265:                {
                    266:                        config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    267:                        enumerator = config->create_virtual_ip_enumerator(config);
                    268:                        while (enumerator->enumerate(enumerator, &host))
                    269:                        {
                    270:                                vips->insert_last(vips, host);
                    271:                        }
                    272:                        enumerator->destroy(enumerator);
                    273:                }
                    274: 
                    275:                if (vips->get_count(vips))
                    276:                {
                    277:                        cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
                    278:                        enumerator = vips->create_enumerator(vips);
                    279:                        while (enumerator->enumerate(enumerator, &host))
                    280:                        {
                    281:                                cp->add_attribute(cp, build_vip(host));
                    282:                        }
                    283:                        enumerator->destroy(enumerator);
                    284:                        this->vip_requested = TRUE;
                    285:                }
                    286: 
                    287:                enumerator = charon->attributes->create_initiator_enumerator(
                    288:                                                                                charon->attributes, this->ike_sa, vips);
                    289:                while (enumerator->enumerate(enumerator, &handler, &type, &data))
                    290:                {
                    291:                        configuration_attribute_t *ca;
                    292:                        entry_t *entry;
                    293: 
                    294:                        /* create configuration attribute */
                    295:                        DBG2(DBG_IKE, "building %N attribute",
                    296:                                 configuration_attribute_type_names, type);
                    297:                        ca = configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
                    298:                                                                                                          type, data);
                    299:                        if (!cp)
                    300:                        {
                    301:                                cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
                    302:                        }
                    303:                        cp->add_attribute(cp, ca);
                    304: 
                    305:                        /* save handler along with requested type */
                    306:                        entry = malloc_thing(entry_t);
                    307:                        entry->type = type;
                    308:                        entry->handler = handler;
                    309: 
                    310:                        this->requested->insert_last(this->requested, entry);
                    311:                }
                    312:                enumerator->destroy(enumerator);
                    313: 
                    314:                vips->destroy(vips);
                    315: 
                    316:                if (cp)
                    317:                {
                    318:                        message->add_payload(message, (payload_t*)cp);
                    319:                }
                    320:                else
                    321:                {       /* we don't expect a CFG_REPLY */
                    322:                        return SUCCESS;
                    323:                }
                    324:        }
                    325:        return NEED_MORE;
                    326: }
                    327: 
                    328: METHOD(task_t, process_r, status_t,
                    329:        private_ike_config_t *this, message_t *message)
                    330: {
                    331:        if (message->get_message_id(message) == 1)
                    332:        {       /* in first IKE_AUTH only */
                    333:                process_payloads(this, message);
                    334:        }
                    335:        return NEED_MORE;
                    336: }
                    337: 
                    338: METHOD(task_t, build_r, status_t,
                    339:        private_ike_config_t *this, message_t *message)
                    340: {
                    341:        if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
                    342:        {       /* in last IKE_AUTH exchange */
                    343:                enumerator_t *enumerator;
                    344:                configuration_attribute_type_t type;
                    345:                chunk_t value;
                    346:                cp_payload_t *cp = NULL;
                    347:                peer_cfg_t *config;
                    348:                identification_t *id;
                    349:                linked_list_t *vips, *pools;
                    350:                host_t *requested;
                    351: 
                    352:                if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
                    353:                {       /* don't assign attributes for redirected SAs */
                    354:                        return SUCCESS;
                    355:                }
                    356: 
                    357:                id = this->ike_sa->get_other_eap_id(this->ike_sa);
                    358:                config = this->ike_sa->get_peer_cfg(this->ike_sa);
                    359:                vips = linked_list_create();
                    360:                pools = linked_list_create_from_enumerator(
                    361:                                                                        config->create_pool_enumerator(config));
                    362: 
                    363:                this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
                    364: 
                    365:                enumerator = this->vips->create_enumerator(this->vips);
                    366:                while (enumerator->enumerate(enumerator, &requested))
                    367:                {
                    368:                        host_t *found = NULL;
                    369: 
                    370:                        /* query all pools until we get an address */
                    371:                        DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
                    372: 
                    373:                        found = charon->attributes->acquire_address(charon->attributes,
                    374:                                                                                                pools, this->ike_sa, requested);
                    375:                        if (found)
                    376:                        {
                    377:                                DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
                    378:                                this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
                    379:                                if (!cp)
                    380:                                {
                    381:                                        cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
                    382:                                }
                    383:                                cp->add_attribute(cp, build_vip(found));
                    384:                                vips->insert_last(vips, found);
                    385:                        }
                    386:                        else
                    387:                        {
                    388:                                DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
                    389:                                         requested, id);
                    390:                        }
                    391:                }
                    392:                enumerator->destroy(enumerator);
                    393: 
                    394:                if (this->vips->get_count(this->vips) && !vips->get_count(vips))
                    395:                {
                    396:                        DBG1(DBG_IKE, "no virtual IP found, sending %N",
                    397:                                 notify_type_names, INTERNAL_ADDRESS_FAILURE);
                    398:                        charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips);
                    399:                        message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE,
                    400:                                                                chunk_empty);
                    401:                        vips->destroy_offset(vips, offsetof(host_t, destroy));
                    402:                        pools->destroy(pools);
                    403:                        return SUCCESS;
                    404:                }
                    405:                charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
                    406: 
                    407:                if (pools->get_count(pools) && !this->vips->get_count(this->vips))
                    408:                {
                    409:                        DBG1(DBG_IKE, "expected a virtual IP request, sending %N",
                    410:                                 notify_type_names, FAILED_CP_REQUIRED);
                    411:                        charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips);
                    412:                        message->add_notify(message, FALSE, FAILED_CP_REQUIRED, chunk_empty);
                    413:                        vips->destroy_offset(vips, offsetof(host_t, destroy));
                    414:                        pools->destroy(pools);
                    415:                        return SUCCESS;
                    416:                }
                    417: 
                    418:                /* query registered providers for additional attributes to include */
                    419:                enumerator = charon->attributes->create_responder_enumerator(
                    420:                                                                charon->attributes, pools, this->ike_sa, vips);
                    421:                while (enumerator->enumerate(enumerator, &type, &value))
                    422:                {
                    423:                        if (!cp)
                    424:                        {
                    425:                                cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
                    426:                        }
                    427:                        DBG2(DBG_IKE, "building %N attribute",
                    428:                                 configuration_attribute_type_names, type);
                    429:                        cp->add_attribute(cp,
                    430:                                configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
                    431:                                                                                                         type, value));
                    432:                }
                    433:                enumerator->destroy(enumerator);
                    434:                vips->destroy_offset(vips, offsetof(host_t, destroy));
                    435:                pools->destroy(pools);
                    436: 
                    437:                if (cp)
                    438:                {
                    439:                        message->add_payload(message, (payload_t*)cp);
                    440:                }
                    441:                return SUCCESS;
                    442:        }
                    443:        return NEED_MORE;
                    444: }
                    445: 
                    446: METHOD(task_t, process_i, status_t,
                    447:        private_ike_config_t *this, message_t *message)
                    448: {
                    449:        if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
                    450:        {       /* in last IKE_AUTH exchange */
                    451:                enumerator_t *enumerator;
                    452:                host_t *host;
                    453: 
                    454:                process_payloads(this, message);
                    455: 
                    456:                this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
                    457: 
                    458:                enumerator = this->vips->create_enumerator(this->vips);
                    459:                while (enumerator->enumerate(enumerator, &host))
                    460:                {
                    461:                        if (!host->is_anyaddr(host))
                    462:                        {
                    463:                                this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
                    464:                        }
                    465:                }
                    466:                enumerator->destroy(enumerator);
                    467: 
                    468:                charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
                    469:                return SUCCESS;
                    470:        }
                    471:        return NEED_MORE;
                    472: }
                    473: 
                    474: METHOD(task_t, get_type, task_type_t,
                    475:        private_ike_config_t *this)
                    476: {
                    477:        return TASK_IKE_CONFIG;
                    478: }
                    479: 
                    480: METHOD(task_t, migrate, void,
                    481:        private_ike_config_t *this, ike_sa_t *ike_sa)
                    482: {
                    483:        this->ike_sa = ike_sa;
                    484:        this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
                    485:        this->vips = linked_list_create();
                    486:        this->requested->destroy_function(this->requested, free);
                    487:        this->requested = linked_list_create();
                    488: }
                    489: 
                    490: METHOD(task_t, destroy, void,
                    491:        private_ike_config_t *this)
                    492: {
                    493:        this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
                    494:        this->requested->destroy_function(this->requested, free);
                    495:        free(this);
                    496: }
                    497: 
                    498: /*
                    499:  * Described in header.
                    500:  */
                    501: ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
                    502: {
                    503:        private_ike_config_t *this;
                    504: 
                    505:        INIT(this,
                    506:                .public = {
                    507:                        .task = {
                    508:                                .get_type = _get_type,
                    509:                                .migrate = _migrate,
                    510:                                .destroy = _destroy,
                    511:                        },
                    512:                },
                    513:                .initiator = initiator,
                    514:                .ike_sa = ike_sa,
                    515:                .vips = linked_list_create(),
                    516:                .requested = linked_list_create(),
                    517:        );
                    518: 
                    519:        if (initiator)
                    520:        {
                    521:                this->public.task.build = _build_i;
                    522:                this->public.task.process = _process_i;
                    523:        }
                    524:        else
                    525:        {
                    526:                this->public.task.build = _build_r;
                    527:                this->public.task.process = _process_r;
                    528:        }
                    529: 
                    530:        return &this->public;
                    531: }

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