Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_natd.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2011 Tobias Brunner,
                      3:  * Copyright (C) 2006-2007 Martin Willi
                      4:  * Copyright (C) 2006 Daniel Roethlisberger
                      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: /*
                     19:  * Copyright (C) 2012 Volker RĂ¼melin
                     20:  *
                     21:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     22:  * of this software and associated documentation files (the "Software"), to deal
                     23:  * in the Software without restriction, including without limitation the rights
                     24:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     25:  * copies of the Software, and to permit persons to whom the Software is
                     26:  * furnished to do so, subject to the following conditions:
                     27:  *
                     28:  * The above copyright notice and this permission notice shall be included in
                     29:  * all copies or substantial portions of the Software.
                     30:  *
                     31:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     32:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     33:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     34:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     35:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     36:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     37:  * THE SOFTWARE.
                     38:  */
                     39: 
                     40: #include "isakmp_natd.h"
                     41: 
                     42: #include <string.h>
                     43: 
                     44: #include <daemon.h>
                     45: #include <sa/ikev1/keymat_v1.h>
                     46: #include <config/peer_cfg.h>
                     47: #include <crypto/hashers/hasher.h>
                     48: #include <encoding/payloads/hash_payload.h>
                     49: 
                     50: typedef struct private_isakmp_natd_t private_isakmp_natd_t;
                     51: 
                     52: /**
                     53:  * Private members of a ike_natt_t task.
                     54:  */
                     55: struct private_isakmp_natd_t {
                     56: 
                     57:        /**
                     58:         * Public interface.
                     59:         */
                     60:        isakmp_natd_t public;
                     61: 
                     62:        /**
                     63:         * Assigned IKE_SA.
                     64:         */
                     65:        ike_sa_t *ike_sa;
                     66: 
                     67:        /**
                     68:         * Are we the initiator?
                     69:         */
                     70:        bool initiator;
                     71: 
                     72:        /**
                     73:         * Keymat derivation (from SA)
                     74:         */
                     75:        keymat_v1_t *keymat;
                     76: 
                     77:        /**
                     78:         * Did we process any NAT detection payloads for a source address?
                     79:         */
                     80:        bool src_seen;
                     81: 
                     82:        /**
                     83:         * Did we process any NAT detection payloads for a destination address?
                     84:         */
                     85:        bool dst_seen;
                     86: 
                     87:        /**
                     88:         * Have we found a matching source address NAT hash?
                     89:         */
                     90:        bool src_matched;
                     91: 
                     92:        /**
                     93:         * Have we found a matching destination address NAT hash?
                     94:         */
                     95:        bool dst_matched;
                     96: };
                     97: 
                     98: /**
                     99:  * Check if UDP encapsulation has to be forced either by config or required
                    100:  * by the kernel interface
                    101:  */
                    102: static bool force_encap(ike_cfg_t *ike_cfg)
                    103: {
                    104:        if (!ike_cfg->force_encap(ike_cfg))
                    105:        {
                    106:                return charon->kernel->get_features(charon->kernel) &
                    107:                                        KERNEL_REQUIRE_UDP_ENCAPSULATION;
                    108:        }
                    109:        return TRUE;
                    110: }
                    111: 
                    112: /**
                    113:  * Get NAT-D payload type (RFC 3947 or RFC 3947 drafts).
                    114:  */
                    115: static payload_type_t get_nat_d_payload_type(ike_sa_t *ike_sa)
                    116: {
                    117:        if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
                    118:        {
                    119:                return PLV1_NAT_D_DRAFT_00_03;
                    120:        }
                    121:        return PLV1_NAT_D;
                    122: }
                    123: 
                    124: /**
                    125:  * Build NAT detection hash for a host.
                    126:  */
                    127: static chunk_t generate_natd_hash(private_isakmp_natd_t *this,
                    128:                                                                  ike_sa_id_t *ike_sa_id, host_t *host)
                    129: {
                    130:        hasher_t *hasher;
                    131:        chunk_t natd_chunk, natd_hash;
                    132:        uint64_t spi_i, spi_r;
                    133:        uint16_t port;
                    134: 
                    135:        hasher = this->keymat->get_hasher(this->keymat);
                    136:        if (!hasher)
                    137:        {
                    138:                DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
                    139:                return chunk_empty;
                    140:        }
                    141: 
                    142:        spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
                    143:        spi_r = ike_sa_id->get_responder_spi(ike_sa_id);
                    144:        port = htons(host->get_port(host));
                    145: 
                    146:        /*  natd_hash = HASH(CKY-I | CKY-R | IP | Port) */
                    147:        natd_chunk = chunk_cata("cccc", chunk_from_thing(spi_i),
                    148:                                                    chunk_from_thing(spi_r), host->get_address(host),
                    149:                                                    chunk_from_thing(port));
                    150:        if (!hasher->allocate_hash(hasher, natd_chunk, &natd_hash))
                    151:        {
                    152:                DBG1(DBG_IKE, "creating NAT-D payload hash failed");
                    153:                return chunk_empty;
                    154:        }
                    155:        DBG3(DBG_IKE, "natd_chunk %B", &natd_chunk);
                    156:        DBG3(DBG_IKE, "natd_hash %B", &natd_hash);
                    157: 
                    158:        return natd_hash;
                    159: }
                    160: 
                    161: /**
                    162:  * Build a faked NAT-D payload to enforce UDP encapsulation.
                    163:  */
                    164: static chunk_t generate_natd_hash_faked(private_isakmp_natd_t *this)
                    165: {
                    166:        hasher_t *hasher;
                    167:        chunk_t chunk;
                    168:        rng_t *rng;
                    169: 
                    170:        hasher = this->keymat->get_hasher(this->keymat);
                    171:        if (!hasher)
                    172:        {
                    173:                DBG1(DBG_IKE, "no hasher available to build NAT-D payload");
                    174:                return chunk_empty;
                    175:        }
                    176:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    177:        if (!rng ||
                    178:                !rng->allocate_bytes(rng, hasher->get_hash_size(hasher), &chunk))
                    179:        {
                    180:                DBG1(DBG_IKE, "unable to get random bytes for NAT-D fake");
                    181:                DESTROY_IF(rng);
                    182:                return chunk_empty;
                    183:        }
                    184:        rng->destroy(rng);
                    185:        return chunk;
                    186: }
                    187: 
                    188: /**
                    189:  * Build a NAT-D payload.
                    190:  */
                    191: static hash_payload_t *build_natd_payload(private_isakmp_natd_t *this, bool src,
                    192:                                                                                  host_t *host)
                    193: {
                    194:        hash_payload_t *payload;
                    195:        ike_cfg_t *config;
                    196:        chunk_t hash;
                    197: 
                    198:        config = this->ike_sa->get_ike_cfg(this->ike_sa);
                    199:        if (src && force_encap(config))
                    200:        {
                    201:                hash = generate_natd_hash_faked(this);
                    202:        }
                    203:        else
                    204:        {
                    205:                ike_sa_id_t *ike_sa_id = this->ike_sa->get_id(this->ike_sa);
                    206:                hash = generate_natd_hash(this, ike_sa_id, host);
                    207:        }
                    208:        if (!hash.len)
                    209:        {
                    210:                return NULL;
                    211:        }
                    212:        payload = hash_payload_create(get_nat_d_payload_type(this->ike_sa));
                    213:        payload->set_hash(payload, hash);
                    214:        chunk_free(&hash);
                    215:        return payload;
                    216: }
                    217: 
                    218: /**
                    219:  * Add NAT-D payloads to the message.
                    220:  */
                    221: static void add_natd_payloads(private_isakmp_natd_t *this, message_t *message)
                    222: {
                    223:        hash_payload_t *payload;
                    224:        host_t *host;
                    225: 
                    226:        /* destination has to be added first */
                    227:        host = message->get_destination(message);
                    228:        payload = build_natd_payload(this, FALSE, host);
                    229:        if (payload)
                    230:        {
                    231:                message->add_payload(message, (payload_t*)payload);
                    232:        }
                    233: 
                    234:        /* source is added second, compared with IKEv2 we always know the source,
                    235:         * as these payloads are added in the second Phase 1 exchange or the
                    236:         * response to the first */
                    237:        host = message->get_source(message);
                    238:        payload = build_natd_payload(this, TRUE, host);
                    239:        if (payload)
                    240:        {
                    241:                message->add_payload(message, (payload_t*)payload);
                    242:        }
                    243: }
                    244: 
                    245: /**
                    246:  * Read NAT-D payloads from message and evaluate them.
                    247:  */
                    248: static void process_payloads(private_isakmp_natd_t *this, message_t *message)
                    249: {
                    250:        enumerator_t *enumerator;
                    251:        payload_t *payload;
                    252:        hash_payload_t *hash_payload;
                    253:        chunk_t hash, src_hash, dst_hash;
                    254:        ike_sa_id_t *ike_sa_id;
                    255:        host_t *me, *other;
                    256:        ike_cfg_t *config;
                    257: 
                    258:        /* precompute hashes for incoming NAT-D comparison */
                    259:        ike_sa_id = message->get_ike_sa_id(message);
                    260:        me = message->get_destination(message);
                    261:        other = message->get_source(message);
                    262:        dst_hash = generate_natd_hash(this, ike_sa_id, me);
                    263:        src_hash = generate_natd_hash(this, ike_sa_id, other);
                    264: 
                    265:        DBG3(DBG_IKE, "precalculated src_hash %B", &src_hash);
                    266:        DBG3(DBG_IKE, "precalculated dst_hash %B", &dst_hash);
                    267: 
                    268:        enumerator = message->create_payload_enumerator(message);
                    269:        while (enumerator->enumerate(enumerator, &payload))
                    270:        {
                    271:                if (payload->get_type(payload) != PLV1_NAT_D &&
                    272:                        payload->get_type(payload) != PLV1_NAT_D_DRAFT_00_03)
                    273:                {
                    274:                        continue;
                    275:                }
                    276:                hash_payload = (hash_payload_t*)payload;
                    277:                if (!this->dst_seen)
                    278:                {       /* the first NAT-D payload contains the destination hash */
                    279:                        this->dst_seen = TRUE;
                    280:                        hash = hash_payload->get_hash(hash_payload);
                    281:                        DBG3(DBG_IKE, "received dst_hash %B", &hash);
                    282:                        if (chunk_equals(hash, dst_hash))
                    283:                        {
                    284:                                this->dst_matched = TRUE;
                    285:                        }
                    286:                        continue;
                    287:                }
                    288:                /* the other NAT-D payloads contain source hashes */
                    289:                this->src_seen = TRUE;
                    290:                if (!this->src_matched)
                    291:                {
                    292:                        hash = hash_payload->get_hash(hash_payload);
                    293:                        DBG3(DBG_IKE, "received src_hash %B", &hash);
                    294:                        if (chunk_equals(hash, src_hash))
                    295:                        {
                    296:                                this->src_matched = TRUE;
                    297:                        }
                    298:                }
                    299:        }
                    300:        enumerator->destroy(enumerator);
                    301: 
                    302:        chunk_free(&src_hash);
                    303:        chunk_free(&dst_hash);
                    304: 
                    305:        if (this->src_seen && this->dst_seen)
                    306:        {
                    307:                this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
                    308:                                                                        !this->dst_matched);
                    309:                this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
                    310:                                                                        !this->src_matched);
                    311:                config = this->ike_sa->get_ike_cfg(this->ike_sa);
                    312:                if (this->dst_matched && this->src_matched &&
                    313:                        force_encap(config))
                    314:                {
                    315:                        this->ike_sa->set_condition(this->ike_sa, COND_NAT_FAKE, TRUE);
                    316:                }
                    317:        }
                    318: }
                    319: 
                    320: METHOD(task_t, build_i, status_t,
                    321:        private_isakmp_natd_t *this, message_t *message)
                    322: {
                    323:        status_t result = NEED_MORE;
                    324: 
                    325:        switch (message->get_exchange_type(message))
                    326:        {
                    327:                case AGGRESSIVE:
                    328:                {       /* add NAT-D payloads to the second request, already processed
                    329:                         * those by the responder contained in the first response */
                    330:                        result = SUCCESS;
                    331:                        /* fall */
                    332:                }
                    333:                case ID_PROT:
                    334:                {       /* add NAT-D payloads to the second request, need to process
                    335:                         * those by the responder contained in the second response */
                    336:                        if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
                    337:                        {       /* wait for the second exchange */
                    338:                                return NEED_MORE;
                    339:                        }
                    340:                        add_natd_payloads(this, message);
                    341:                        return result;
                    342:                }
                    343:                default:
                    344:                        break;
                    345:        }
                    346:        return SUCCESS;
                    347: }
                    348: 
                    349: METHOD(task_t, process_i, status_t,
                    350:        private_isakmp_natd_t *this, message_t *message)
                    351: {
                    352:        status_t result = NEED_MORE;
                    353: 
                    354:        if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
                    355:        {       /* we didn't receive VIDs indicating support for NAT-T */
                    356:                return SUCCESS;
                    357:        }
                    358: 
                    359:        switch (message->get_exchange_type(message))
                    360:        {
                    361:                case ID_PROT:
                    362:                {       /* process NAT-D payloads in the second response, added them in the
                    363:                         * second request already, so we're done afterwards */
                    364:                        if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
                    365:                        {       /* wait for the second exchange */
                    366:                                return NEED_MORE;
                    367:                        }
                    368:                        result = SUCCESS;
                    369:                        /* fall */
                    370:                }
                    371:                case AGGRESSIVE:
                    372:                {       /* process NAT-D payloads in the first response, add them in the
                    373:                         * following second request */
                    374:                        process_payloads(this, message);
                    375: 
                    376:                        if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
                    377:                        {
                    378:                                this->ike_sa->float_ports(this->ike_sa);
                    379:                        }
                    380:                        return result;
                    381:                }
                    382:                default:
                    383:                        break;
                    384:        }
                    385:        return SUCCESS;
                    386: }
                    387: 
                    388: METHOD(task_t, process_r, status_t,
                    389:        private_isakmp_natd_t *this, message_t *message)
                    390: {
                    391:        status_t result = NEED_MORE;
                    392: 
                    393:        if (!this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
                    394:        {       /* we didn't receive VIDs indicating NAT-T support */
                    395:                return SUCCESS;
                    396:        }
                    397: 
                    398:        switch (message->get_exchange_type(message))
                    399:        {
                    400:                case AGGRESSIVE:
                    401:                {       /* process NAT-D payloads in the second request, already added ours
                    402:                         * in the first response */
                    403:                        result = SUCCESS;
                    404:                        /* fall */
                    405:                }
                    406:                case ID_PROT:
                    407:                {       /* process NAT-D payloads in the second request, need to add ours
                    408:                         * to the second response */
                    409:                        if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
                    410:                        {       /* wait for the second exchange */
                    411:                                return NEED_MORE;
                    412:                        }
                    413:                        process_payloads(this, message);
                    414:                        return result;
                    415:                }
                    416:                default:
                    417:                        break;
                    418:        }
                    419:        return SUCCESS;
                    420: }
                    421: 
                    422: METHOD(task_t, build_r, status_t,
                    423:        private_isakmp_natd_t *this, message_t *message)
                    424: {
                    425:        switch (message->get_exchange_type(message))
                    426:        {
                    427:                case ID_PROT:
                    428:                {       /* add NAT-D payloads to second response, already processed those
                    429:                         * contained in the second request */
                    430:                        if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
                    431:                        {       /* wait for the second exchange */
                    432:                                return NEED_MORE;
                    433:                        }
                    434:                        add_natd_payloads(this, message);
                    435:                        return SUCCESS;
                    436:                }
                    437:                case AGGRESSIVE:
                    438:                {       /* add NAT-D payloads to the first response, process those contained
                    439:                         * in the following second request */
                    440:                        add_natd_payloads(this, message);
                    441:                        return NEED_MORE;
                    442:                }
                    443:                default:
                    444:                        break;
                    445:        }
                    446:        return SUCCESS;
                    447: }
                    448: 
                    449: METHOD(task_t, get_type, task_type_t,
                    450:        private_isakmp_natd_t *this)
                    451: {
                    452:        return TASK_ISAKMP_NATD;
                    453: }
                    454: 
                    455: METHOD(task_t, migrate, void,
                    456:        private_isakmp_natd_t *this, ike_sa_t *ike_sa)
                    457: {
                    458:        this->ike_sa = ike_sa;
                    459:        this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
                    460:        this->src_seen = FALSE;
                    461:        this->dst_seen = FALSE;
                    462:        this->src_matched = FALSE;
                    463:        this->dst_matched = FALSE;
                    464: }
                    465: 
                    466: METHOD(task_t, destroy, void,
                    467:        private_isakmp_natd_t *this)
                    468: {
                    469:        free(this);
                    470: }
                    471: 
                    472: /*
                    473:  * Described in header.
                    474:  */
                    475: isakmp_natd_t *isakmp_natd_create(ike_sa_t *ike_sa, bool initiator)
                    476: {
                    477:        private_isakmp_natd_t *this;
                    478: 
                    479:        INIT(this,
                    480:                .public = {
                    481:                        .task = {
                    482:                                .get_type = _get_type,
                    483:                                .migrate = _migrate,
                    484:                                .destroy = _destroy,
                    485:                        },
                    486:                },
                    487:                .ike_sa = ike_sa,
                    488:                .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
                    489:                .initiator = initiator,
                    490:        );
                    491: 
                    492:        if (initiator)
                    493:        {
                    494:                this->public.task.build = _build_i;
                    495:                this->public.task.process = _process_i;
                    496:        }
                    497:        else
                    498:        {
                    499:                this->public.task.build = _build_r;
                    500:                this->public.task.process = _process_r;
                    501:        }
                    502: 
                    503:        return &this->public;
                    504: }

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