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

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2007 Martin Willi
                      3:  * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
                      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_natd.h"
                     18: 
                     19: #include <string.h>
                     20: 
                     21: #include <daemon.h>
                     22: #include <config/peer_cfg.h>
                     23: #include <crypto/hashers/hasher.h>
                     24: #include <encoding/payloads/notify_payload.h>
                     25: 
                     26: 
                     27: typedef struct private_ike_natd_t private_ike_natd_t;
                     28: 
                     29: /**
                     30:  * Private members of a ike_natd_t task.
                     31:  */
                     32: struct private_ike_natd_t {
                     33: 
                     34:        /**
                     35:         * Public methods and task_t interface.
                     36:         */
                     37:        ike_natd_t public;
                     38: 
                     39:        /**
                     40:         * Assigned IKE_SA.
                     41:         */
                     42:        ike_sa_t *ike_sa;
                     43: 
                     44:        /**
                     45:         * Are we the initiator?
                     46:         */
                     47:        bool initiator;
                     48: 
                     49:        /**
                     50:         * Hasher used to build NAT detection hashes
                     51:         */
                     52:        hasher_t *hasher;
                     53: 
                     54:        /**
                     55:         * Did we process any NAT detection notifys for a source address?
                     56:         */
                     57:        bool src_seen;
                     58: 
                     59:        /**
                     60:         * Did we process any NAT detection notifys for a destination address?
                     61:         */
                     62:        bool dst_seen;
                     63: 
                     64:        /**
                     65:         * Have we found a matching source address NAT hash?
                     66:         */
                     67:        bool src_matched;
                     68: 
                     69:        /**
                     70:         * Have we found a matching destination address NAT hash?
                     71:         */
                     72:        bool dst_matched;
                     73: 
                     74:        /**
                     75:         * whether NAT mappings for our NATed address has changed
                     76:         */
                     77:        bool mapping_changed;
                     78: };
                     79: 
                     80: /**
                     81:  * Check if UDP encapsulation has to be forced either by config or required
                     82:  * by the kernel interface
                     83:  */
                     84: static bool force_encap(ike_cfg_t *ike_cfg)
                     85: {
                     86:        if (!ike_cfg->force_encap(ike_cfg))
                     87:        {
                     88:                return charon->kernel->get_features(charon->kernel) &
                     89:                                        KERNEL_REQUIRE_UDP_ENCAPSULATION;
                     90:        }
                     91:        return TRUE;
                     92: }
                     93: 
                     94: /**
                     95:  * Build NAT detection hash for a host
                     96:  */
                     97: static chunk_t generate_natd_hash(private_ike_natd_t *this,
                     98:                                                                  ike_sa_id_t *ike_sa_id, host_t *host)
                     99: {
                    100:        chunk_t natd_chunk, spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk;
                    101:        chunk_t natd_hash;
                    102:        uint64_t spi_i, spi_r;
                    103:        uint16_t port;
                    104: 
                    105:        /* prepare all required chunks */
                    106:        spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
                    107:        spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
                    108:        spi_i_chunk.ptr = (void*)&spi_i;
                    109:        spi_i_chunk.len = sizeof(spi_i);
                    110:        spi_r_chunk.ptr = (void*)&spi_r;
                    111:        spi_r_chunk.len = sizeof(spi_r);
                    112:        port = htons(host->get_port(host));
                    113:        port_chunk.ptr = (void*)&port;
                    114:        port_chunk.len = sizeof(port);
                    115:        addr_chunk = host->get_address(host);
                    116: 
                    117:        /*  natd_hash = SHA1( spi_i | spi_r | address | port ) */
                    118:        natd_chunk = chunk_cat("cccc", spi_i_chunk, spi_r_chunk, addr_chunk, port_chunk);
                    119:        if (!this->hasher->allocate_hash(this->hasher, natd_chunk, &natd_hash))
                    120:        {
                    121:                natd_hash = chunk_empty;
                    122:        }
                    123:        DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
                    124:        DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
                    125: 
                    126:        chunk_free(&natd_chunk);
                    127:        return natd_hash;
                    128: }
                    129: 
                    130: /**
                    131:  * Build a NAT detection notify payload.
                    132:  */
                    133: static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
                    134:                                                                                        notify_type_t type, host_t *host)
                    135: {
                    136:        chunk_t hash;
                    137:        notify_payload_t *notify;
                    138:        ike_sa_id_t *ike_sa_id;
                    139:        ike_cfg_t *config;
                    140: 
                    141:        ike_sa_id = this->ike_sa->get_id(this->ike_sa);
                    142:        config = this->ike_sa->get_ike_cfg(this->ike_sa);
                    143:        if (force_encap(config) && type == NAT_DETECTION_SOURCE_IP)
                    144:        {
                    145:                uint32_t addr;
                    146: 
                    147:                /* chunk_hash() is randomly keyed so this produces a random IPv4 address
                    148:                 * that changes with every restart but otherwise stays the same */
                    149:                addr = chunk_hash(chunk_from_chars(0x00, 0x00, 0x00, 0x00));
                    150:                host = host_create_from_chunk(AF_INET, chunk_from_thing(addr), 0);
                    151:                hash = generate_natd_hash(this, ike_sa_id, host);
                    152:                host->destroy(host);
                    153:        }
                    154:        else
                    155:        {
                    156:                hash = generate_natd_hash(this, ike_sa_id, host);
                    157:        }
                    158:        if (!hash.len)
                    159:        {
                    160:                return NULL;
                    161:        }
                    162:        notify = notify_payload_create(PLV2_NOTIFY);
                    163:        notify->set_notify_type(notify, type);
                    164:        notify->set_notification_data(notify, hash);
                    165:        chunk_free(&hash);
                    166: 
                    167:        return notify;
                    168: }
                    169: 
                    170: /**
                    171:  * read notifys from message and evaluate them
                    172:  */
                    173: static void process_payloads(private_ike_natd_t *this, message_t *message)
                    174: {
                    175:        enumerator_t *enumerator;
                    176:        payload_t *payload;
                    177:        notify_payload_t *notify;
                    178:        chunk_t hash, src_hash, dst_hash;
                    179:        ike_sa_id_t *ike_sa_id;
                    180:        host_t *me, *other;
                    181:        ike_cfg_t *config;
                    182: 
                    183:        /* Precompute NAT-D hashes for incoming NAT notify comparison */
                    184:        ike_sa_id = message->get_ike_sa_id(message);
                    185:        me = message->get_destination(message);
                    186:        other = message->get_source(message);
                    187:        dst_hash = generate_natd_hash(this, ike_sa_id, me);
                    188:        src_hash = generate_natd_hash(this, ike_sa_id, other);
                    189: 
                    190:        DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
                    191:        DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
                    192: 
                    193:        enumerator = message->create_payload_enumerator(message);
                    194:        while (enumerator->enumerate(enumerator, &payload))
                    195:        {
                    196:                if (payload->get_type(payload) != PLV2_NOTIFY)
                    197:                {
                    198:                        continue;
                    199:                }
                    200:                notify = (notify_payload_t*)payload;
                    201:                switch (notify->get_notify_type(notify))
                    202:                {
                    203:                        case NAT_DETECTION_DESTINATION_IP:
                    204:                        {
                    205:                                this->dst_seen = TRUE;
                    206:                                hash = notify->get_notification_data(notify);
                    207:                                if (!this->dst_matched)
                    208:                                {
                    209:                                        DBG3(DBG_IKE, "received dst_hash %B", &hash);
                    210:                                        if (chunk_equals(hash, dst_hash))
                    211:                                        {
                    212:                                                this->dst_matched = TRUE;
                    213:                                        }
                    214:                                }
                    215:                                /* RFC4555 says we should also compare against IKE_SA_INIT
                    216:                                 * NATD payloads, but this does not work: We are running
                    217:                                 * there at port 500, but use 4500 afterwards... */
                    218:                                if (message->get_exchange_type(message) == INFORMATIONAL &&
                    219:                                        this->initiator && !this->dst_matched)
                    220:                                {
                    221:                                        this->mapping_changed = this->ike_sa->has_mapping_changed(
                    222:                                                                                                                        this->ike_sa, hash);
                    223:                                }
                    224:                                break;
                    225:                        }
                    226:                        case NAT_DETECTION_SOURCE_IP:
                    227:                        {
                    228:                                this->src_seen = TRUE;
                    229:                                if (!this->src_matched)
                    230:                                {
                    231:                                        hash = notify->get_notification_data(notify);
                    232:                                        DBG3(DBG_IKE, "received src_hash %B", &hash);
                    233:                                        if (chunk_equals(hash, src_hash))
                    234:                                        {
                    235:                                                this->src_matched = TRUE;
                    236:                                        }
                    237:                                }
                    238:                                break;
                    239:                        }
                    240:                        default:
                    241:                                break;
                    242:                }
                    243:        }
                    244:        enumerator->destroy(enumerator);
                    245: 
                    246:        chunk_free(&src_hash);
                    247:        chunk_free(&dst_hash);
                    248: 
                    249:        if (this->src_seen && this->dst_seen)
                    250:        {
                    251:                this->ike_sa->enable_extension(this->ike_sa, EXT_NATT);
                    252: 
                    253:                this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
                    254:                                                                        !this->dst_matched);
                    255:                this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
                    256:                                                                        !this->src_matched);
                    257:                config = this->ike_sa->get_ike_cfg(this->ike_sa);
                    258:                if (this->dst_matched && this->src_matched &&
                    259:                        force_encap(config))
                    260:                {
                    261:                        this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
                    262:                }
                    263:        }
                    264: }
                    265: 
                    266: METHOD(task_t, process_i, status_t,
                    267:        private_ike_natd_t *this, message_t *message)
                    268: {
                    269:        process_payloads(this, message);
                    270: 
                    271:        if (message->get_exchange_type(message) == IKE_SA_INIT)
                    272:        {
                    273:                peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
                    274:                if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY) ||
                    275:                        /* if peer supports NAT-T, we switch to port 4500 even
                    276:                         * if no NAT is detected. can't be done later (when we would know
                    277:                         * whether the peer supports MOBIKE) because there would be no
                    278:                         * exchange to actually do the switch (other than a forced DPD). */
                    279:                        (peer_cfg->use_mobike(peer_cfg) &&
                    280:                         this->ike_sa->supports_extension(this->ike_sa, EXT_NATT)))
                    281:                {
                    282:                        this->ike_sa->float_ports(this->ike_sa);
                    283:                }
                    284:        }
                    285: 
                    286:        return SUCCESS;
                    287: }
                    288: 
                    289: METHOD(task_t, build_i, status_t,
                    290:        private_ike_natd_t *this, message_t *message)
                    291: {
                    292:        notify_payload_t *notify;
                    293:        enumerator_t *enumerator;
                    294:        ike_cfg_t *ike_cfg;
                    295:        host_t *host;
                    296: 
                    297:        if (this->hasher == NULL)
                    298:        {
                    299:                DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
                    300:                return NEED_MORE;
                    301:        }
                    302: 
                    303:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
                    304: 
                    305:        /* destination is always set */
                    306:        host = message->get_destination(message);
                    307:        notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
                    308:        if (notify)
                    309:        {
                    310:                message->add_payload(message, (payload_t*)notify);
                    311:        }
                    312: 
                    313:        /* source may be any, we have 3 possibilities to get our source address:
                    314:         * 1. It is defined in the config => use the one of the IKE_SA
                    315:         * 2. We do a routing lookup in the kernel interface
                    316:         * 3. Include all possible addresses
                    317:         */
                    318:        host = message->get_source(message);
                    319:        if (!host->is_anyaddr(host) || force_encap(ike_cfg))
                    320:        {       /* 1. or if we force UDP encap, as it doesn't matter if it's %any */
                    321:                notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
                    322:                if (notify)
                    323:                {
                    324:                        message->add_payload(message, (payload_t*)notify);
                    325:                }
                    326:        }
                    327:        else
                    328:        {
                    329:                host = charon->kernel->get_source_addr(charon->kernel,
                    330:                                                        this->ike_sa->get_other_host(this->ike_sa), NULL);
                    331:                if (host)
                    332:                {       /* 2. */
                    333:                        host->set_port(host, ike_cfg->get_my_port(ike_cfg));
                    334:                        notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
                    335:                        if (notify)
                    336:                        {
                    337:                                message->add_payload(message, (payload_t*)notify);
                    338:                        }
                    339:                        host->destroy(host);
                    340:                }
                    341:                else
                    342:                {       /* 3. */
                    343:                        enumerator = charon->kernel->create_address_enumerator(
                    344:                                                                                        charon->kernel, ADDR_TYPE_REGULAR);
                    345:                        while (enumerator->enumerate(enumerator, (void**)&host))
                    346:                        {
                    347:                                /* apply port 500 to host, but work on a copy */
                    348:                                host = host->clone(host);
                    349:                                host->set_port(host, ike_cfg->get_my_port(ike_cfg));
                    350:                                notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
                    351:                                host->destroy(host);
                    352:                                if (notify)
                    353:                                {
                    354:                                        message->add_payload(message, (payload_t*)notify);
                    355:                                }
                    356:                        }
                    357:                        enumerator->destroy(enumerator);
                    358:                }
                    359:        }
                    360:        return NEED_MORE;
                    361: }
                    362: 
                    363: METHOD(task_t, build_r, status_t,
                    364:        private_ike_natd_t *this, message_t *message)
                    365: {
                    366:        notify_payload_t *notify;
                    367:        host_t *me, *other;
                    368: 
                    369:        /* only add notifies on successful responses. */
                    370:        if (message->get_exchange_type(message) == IKE_SA_INIT &&
                    371:                message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
                    372:        {
                    373:                return SUCCESS;
                    374:        }
                    375: 
                    376:        if (this->src_seen && this->dst_seen)
                    377:        {
                    378:                if (this->hasher == NULL)
                    379:                {
                    380:                        DBG1(DBG_IKE, "unable to build NATD payloads, SHA1 not supported");
                    381:                        return SUCCESS;
                    382:                }
                    383: 
                    384:                /* initiator seems to support NAT detection, add response */
                    385:                me = message->get_source(message);
                    386:                notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, me);
                    387:                if (notify)
                    388:                {
                    389:                        message->add_payload(message, (payload_t*)notify);
                    390:                }
                    391:                other = message->get_destination(message);
                    392:                notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, other);
                    393:                if (notify)
                    394:                {
                    395:                        message->add_payload(message, (payload_t*)notify);
                    396:                }
                    397:        }
                    398:        return SUCCESS;
                    399: }
                    400: 
                    401: METHOD(task_t, process_r, status_t,
                    402:        private_ike_natd_t *this, message_t *message)
                    403: {
                    404:        process_payloads(this, message);
                    405: 
                    406:        return NEED_MORE;
                    407: }
                    408: 
                    409: METHOD(task_t, get_type, task_type_t,
                    410:        private_ike_natd_t *this)
                    411: {
                    412:        return TASK_IKE_NATD;
                    413: }
                    414: 
                    415: METHOD(task_t, migrate, void,
                    416:        private_ike_natd_t *this, ike_sa_t *ike_sa)
                    417: {
                    418:        this->ike_sa = ike_sa;
                    419:        this->src_seen = FALSE;
                    420:        this->dst_seen = FALSE;
                    421:        this->src_matched = FALSE;
                    422:        this->dst_matched = FALSE;
                    423:        this->mapping_changed = FALSE;
                    424: }
                    425: 
                    426: METHOD(task_t, destroy, void,
                    427:        private_ike_natd_t *this)
                    428: {
                    429:        DESTROY_IF(this->hasher);
                    430:        free(this);
                    431: }
                    432: 
                    433: METHOD(ike_natd_t, has_mapping_changed, bool,
                    434:        private_ike_natd_t *this)
                    435: {
                    436:        return this->mapping_changed;
                    437: }
                    438: 
                    439: /*
                    440:  * Described in header.
                    441:  */
                    442: ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator)
                    443: {
                    444:        private_ike_natd_t *this;
                    445: 
                    446:        INIT(this,
                    447:                .public = {
                    448:                        .task = {
                    449:                                .get_type = _get_type,
                    450:                                .migrate = _migrate,
                    451:                                .destroy = _destroy,
                    452:                        },
                    453:                        .has_mapping_changed = _has_mapping_changed,
                    454:                },
                    455:                .ike_sa = ike_sa,
                    456:                .initiator = initiator,
                    457:                .hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1),
                    458:        );
                    459: 
                    460:        if (initiator)
                    461:        {
                    462:                this->public.task.build = _build_i;
                    463:                this->public.task.process = _process_i;
                    464:        }
                    465:        else
                    466:        {
                    467:                this->public.task.build = _build_r;
                    468:                this->public.task.process = _process_r;
                    469:        }
                    470: 
                    471:        return &this->public;
                    472: }

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