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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2013 Tobias Brunner
                      3:  * Copyright (C) 2009 Martin Willi
                      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: /*
                     18:  * Copyright (C) 2012-2014 Volker RĂ¼melin
                     19:  *
                     20:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     21:  * of this software and associated documentation files (the "Software"), to deal
                     22:  * in the Software without restriction, including without limitation the rights
                     23:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     24:  * copies of the Software, and to permit persons to whom the Software is
                     25:  * furnished to do so, subject to the following conditions:
                     26:  *
                     27:  * The above copyright notice and this permission notice shall be included in
                     28:  * all copies or substantial portions of the Software.
                     29:  *
                     30:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     31:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     32:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     33:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     34:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     35:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     36:  * THE SOFTWARE.
                     37:  */
                     38: 
                     39: #include "isakmp_vendor.h"
                     40: 
                     41: #include <daemon.h>
                     42: #include <encoding/payloads/vendor_id_payload.h>
                     43: 
                     44: typedef struct private_isakmp_vendor_t private_isakmp_vendor_t;
                     45: 
                     46: /**
                     47:  * Private data of an isakmp_vendor_t object.
                     48:  */
                     49: struct private_isakmp_vendor_t {
                     50: 
                     51:        /**
                     52:         * Public isakmp_vendor_t interface.
                     53:         */
                     54:        isakmp_vendor_t public;
                     55: 
                     56:        /**
                     57:         * Associated IKE_SA
                     58:         */
                     59:        ike_sa_t *ike_sa;
                     60: 
                     61:        /**
                     62:         * Are we the initiator of this task
                     63:         */
                     64:        bool initiator;
                     65: 
                     66:        /**
                     67:         * Index of best nat traversal VID found
                     68:         */
                     69:        int best_natt_ext;
                     70: 
                     71:        /**
                     72:         * Number of times we have been invoked
                     73:         */
                     74:        int count;
                     75: };
                     76: 
                     77: /**
                     78:  * IKEv1 Vendor ID database
                     79:  */
                     80: static struct {
                     81:        /* Description */
                     82:        char *desc;
                     83:        /* extension flag negotiated with vendor ID, if any */
                     84:        ike_extension_t extension;
                     85:        /* send yourself? */
                     86:        bool send;
                     87:        /* length of vendor ID string */
                     88:        int len;
                     89:        /* vendor ID string */
                     90:        char *id;
                     91: } vendor_ids[] = {
                     92: 
                     93:        /* strongSwan MD5("strongSwan") */
                     94:        { "strongSwan", EXT_STRONGSWAN, FALSE, 16,
                     95:          "\x88\x2f\xe5\x6d\x6f\xd2\x0d\xbc\x22\x51\x61\x3b\x2e\xbe\x5b\xeb"},
                     96: 
                     97:        /* XAuth, MD5("draft-ietf-ipsra-isakmp-xauth-06.txt") */
                     98:        { "XAuth", EXT_XAUTH, TRUE, 8,
                     99:          "\x09\x00\x26\x89\xdf\xd6\xb7\x12"},
                    100: 
                    101:        /* Dead peer detection, RFC 3706 */
                    102:        { "DPD", EXT_DPD, TRUE, 16,
                    103:          "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"},
                    104: 
                    105:        /* CISCO-UNITY, similar to DPD the last two bytes indicate the version */
                    106:        { "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
                    107:          "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
                    108: 
                    109:        /* Proprietary IKE fragmentation extension. Capabilities are handled
                    110:         * specially on receipt of this VID. Windows peers send this VID
                    111:         * without capabilities, but accept it with and without capabilities. */
                    112:        { "FRAGMENTATION", EXT_IKE_FRAGMENTATION, FALSE, 20,
                    113:          "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x80\x00\x00\x00"},
                    114: 
                    115:        /* Windows peers send this VID and a version number */
                    116:        { "MS NT5 ISAKMPOAKLEY", EXT_MS_WINDOWS, FALSE, 20,
                    117:          "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x00"},
                    118: 
                    119: }, vendor_natt_ids[] = {
                    120: 
                    121:        /* NAT-Traversal VIDs ordered by preference */
                    122: 
                    123:        /* NAT-Traversal, MD5("RFC 3947") */
                    124:        { "NAT-T (RFC 3947)", EXT_NATT, TRUE, 16,
                    125:          "\x4a\x13\x1c\x81\x07\x03\x58\x45\x5c\x57\x28\xf2\x0e\x95\x45\x2f"},
                    126: 
                    127:        { "draft-ietf-ipsec-nat-t-ike-03", EXT_NATT | EXT_NATT_DRAFT_02_03,
                    128:          FALSE, 16,
                    129:          "\x7d\x94\x19\xa6\x53\x10\xca\x6f\x2c\x17\x9d\x92\x15\x52\x9d\x56"},
                    130: 
                    131:        { "draft-ietf-ipsec-nat-t-ike-02", EXT_NATT | EXT_NATT_DRAFT_02_03,
                    132:          FALSE, 16,
                    133:          "\xcd\x60\x46\x43\x35\xdf\x21\xf8\x7c\xfd\xb2\xfc\x68\xb6\xa4\x48"},
                    134: 
                    135:        { "draft-ietf-ipsec-nat-t-ike-02\\n", EXT_NATT | EXT_NATT_DRAFT_02_03,
                    136:          TRUE, 16,
                    137:          "\x90\xcb\x80\x91\x3e\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f"},
                    138: 
                    139:        { "draft-ietf-ipsec-nat-t-ike-08", 0, FALSE, 16,
                    140:          "\x8f\x8d\x83\x82\x6d\x24\x6b\x6f\xc7\xa8\xa6\xa4\x28\xc1\x1d\xe8"},
                    141: 
                    142:        { "draft-ietf-ipsec-nat-t-ike-07", 0, FALSE, 16,
                    143:          "\x43\x9b\x59\xf8\xba\x67\x6c\x4c\x77\x37\xae\x22\xea\xb8\xf5\x82"},
                    144: 
                    145:        { "draft-ietf-ipsec-nat-t-ike-06", 0, FALSE, 16,
                    146:          "\x4d\x1e\x0e\x13\x6d\xea\xfa\x34\xc4\xf3\xea\x9f\x02\xec\x72\x85"},
                    147: 
                    148:        { "draft-ietf-ipsec-nat-t-ike-05", 0, FALSE, 16,
                    149:          "\x80\xd0\xbb\x3d\xef\x54\x56\x5e\xe8\x46\x45\xd4\xc8\x5c\xe3\xee"},
                    150: 
                    151:        { "draft-ietf-ipsec-nat-t-ike-04", 0, FALSE, 16,
                    152:          "\x99\x09\xb6\x4e\xed\x93\x7c\x65\x73\xde\x52\xac\xe9\x52\xfa\x6b"},
                    153: 
                    154:        { "draft-ietf-ipsec-nat-t-ike-00", 0, FALSE, 16,
                    155:          "\x44\x85\x15\x2d\x18\xb6\xbb\xcd\x0b\xe8\xa8\x46\x95\x79\xdd\xcc"},
                    156: 
                    157:        { "draft-ietf-ipsec-nat-t-ike", 0, FALSE, 16,
                    158:          "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62"},
                    159: 
                    160:        { "draft-stenberg-ipsec-nat-traversal-02", 0, FALSE, 16,
                    161:          "\x61\x05\xc4\x22\xe7\x68\x47\xe4\x3f\x96\x84\x80\x12\x92\xae\xcd"},
                    162: 
                    163:        { "draft-stenberg-ipsec-nat-traversal-01", 0, FALSE, 16,
                    164:          "\x27\xba\xb5\xdc\x01\xea\x07\x60\xea\x4e\x31\x90\xac\x27\xc0\xd0"},
                    165: 
                    166: };
                    167: 
                    168: /**
                    169:  * According to racoon 0x80000000 seems to indicate support for fragmentation
                    170:  * of Aggressive and Main mode messages.  0x40000000 seems to indicate support
                    171:  * for fragmentation of base ISAKMP messages (Cisco adds that and thus sends
                    172:  * 0xc0000000)
                    173:  */
                    174: static const uint32_t fragmentation_ike = 0x80000000;
                    175: 
                    176: static bool is_known_vid(chunk_t data, int i)
                    177: {
                    178:        switch (vendor_ids[i].extension)
                    179:        {
                    180:                case EXT_IKE_FRAGMENTATION:
                    181:                        if (data.len >= 16 && memeq(data.ptr, vendor_ids[i].id, 16))
                    182:                        {
                    183:                                switch (data.len)
                    184:                                {
                    185:                                        case 16:
                    186:                                                return TRUE;
                    187:                                        case 20:
                    188:                                                return untoh32(&data.ptr[16]) & fragmentation_ike;
                    189:                                }
                    190:                        }
                    191:                        break;
                    192:                case EXT_MS_WINDOWS:
                    193:                        return data.len == 20 && memeq(data.ptr, vendor_ids[i].id, 16);
                    194:                case EXT_CISCO_UNITY:
                    195:                        return data.len == 16 && memeq(data.ptr, vendor_ids[i].id, 14);
                    196:                default:
                    197:                        return chunk_equals(data, chunk_create(vendor_ids[i].id,
                    198:                                                                                                   vendor_ids[i].len));
                    199:        }
                    200:        return FALSE;
                    201: }
                    202: 
                    203: /**
                    204:  * Add supported vendor ID payloads
                    205:  */
                    206: static void build(private_isakmp_vendor_t *this, message_t *message)
                    207: {
                    208:        vendor_id_payload_t *vid_payload;
                    209:        bool strongswan, cisco_unity, fragmentation;
                    210:        ike_cfg_t *ike_cfg;
                    211:        int i;
                    212: 
                    213:        strongswan = lib->settings->get_bool(lib->settings,
                    214:                                                                                 "%s.send_vendor_id", FALSE, lib->ns);
                    215:        cisco_unity = lib->settings->get_bool(lib->settings,
                    216:                                                                                 "%s.cisco_unity", FALSE, lib->ns);
                    217:        ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
                    218:        fragmentation = ike_cfg->fragmentation(ike_cfg) != FRAGMENTATION_NO;
                    219:        if (!this->initiator && fragmentation)
                    220:        {
                    221:                fragmentation = this->ike_sa->supports_extension(this->ike_sa,
                    222:                                                                                                                 EXT_IKE_FRAGMENTATION);
                    223:        }
                    224:        for (i = 0; i < countof(vendor_ids); i++)
                    225:        {
                    226:                if (vendor_ids[i].send ||
                    227:                   (vendor_ids[i].extension == EXT_STRONGSWAN && strongswan) ||
                    228:                   (vendor_ids[i].extension == EXT_CISCO_UNITY && cisco_unity) ||
                    229:                   (vendor_ids[i].extension == EXT_IKE_FRAGMENTATION && fragmentation))
                    230:                {
                    231:                        DBG2(DBG_IKE, "sending %s vendor ID", vendor_ids[i].desc);
                    232:                        vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
                    233:                                chunk_clone(chunk_create(vendor_ids[i].id, vendor_ids[i].len)));
                    234:                        message->add_payload(message, &vid_payload->payload_interface);
                    235:                }
                    236:        }
                    237:        for (i = 0; i < countof(vendor_natt_ids); i++)
                    238:        {
                    239:                if ((this->initiator && vendor_natt_ids[i].send) ||
                    240:                        this->best_natt_ext == i)
                    241:                {
                    242:                        DBG2(DBG_IKE, "sending %s vendor ID", vendor_natt_ids[i].desc);
                    243:                        vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
                    244:                                                        chunk_clone(chunk_create(vendor_natt_ids[i].id,
                    245:                                                                                                         vendor_natt_ids[i].len)));
                    246:                        message->add_payload(message, &vid_payload->payload_interface);
                    247:                }
                    248:        }
                    249: }
                    250: 
                    251: /**
                    252:  * Process vendor ID payloads
                    253:  */
                    254: static void process(private_isakmp_vendor_t *this, message_t *message)
                    255: {
                    256:        enumerator_t *enumerator;
                    257:        payload_t *payload;
                    258:        int i;
                    259: 
                    260:        enumerator = message->create_payload_enumerator(message);
                    261:        while (enumerator->enumerate(enumerator, &payload))
                    262:        {
                    263:                if (payload->get_type(payload) == PLV1_VENDOR_ID)
                    264:                {
                    265:                        vendor_id_payload_t *vid;
                    266:                        bool found = FALSE;
                    267:                        chunk_t data;
                    268: 
                    269:                        vid = (vendor_id_payload_t*)payload;
                    270:                        data = vid->get_data(vid);
                    271: 
                    272:                        for (i = 0; i < countof(vendor_ids); i++)
                    273:                        {
                    274:                                if (is_known_vid(data, i))
                    275:                                {
                    276:                                        DBG1(DBG_IKE, "received %s vendor ID", vendor_ids[i].desc);
                    277:                                        if (vendor_ids[i].extension)
                    278:                                        {
                    279:                                                this->ike_sa->enable_extension(this->ike_sa,
                    280:                                                                                                           vendor_ids[i].extension);
                    281:                                        }
                    282:                                        found = TRUE;
                    283:                                        break;
                    284:                                }
                    285:                        }
                    286:                        if (!found)
                    287:                        {
                    288:                                for (i = 0; i < countof(vendor_natt_ids); i++)
                    289:                                {
                    290:                                        if (chunk_equals(data, chunk_create(vendor_natt_ids[i].id,
                    291:                                                                                                        vendor_natt_ids[i].len)))
                    292:                                        {
                    293:                                                DBG1(DBG_IKE, "received %s vendor ID",
                    294:                                                         vendor_natt_ids[i].desc);
                    295:                                                if (vendor_natt_ids[i].extension &&
                    296:                                                   (i < this->best_natt_ext || this->best_natt_ext < 0))
                    297:                                                {
                    298:                                                        this->best_natt_ext = i;
                    299:                                                }
                    300:                                                found = TRUE;
                    301:                                                break;
                    302:                                        }
                    303:                                }
                    304:                        }
                    305:                        if (!found)
                    306:                        {
                    307:                                DBG1(DBG_ENC, "received unknown vendor ID: %#B", &data);
                    308:                        }
                    309:                }
                    310:        }
                    311:        enumerator->destroy(enumerator);
                    312: 
                    313:        if (this->best_natt_ext >= 0)
                    314:        {
                    315:                this->ike_sa->enable_extension(this->ike_sa,
                    316:                                                                vendor_natt_ids[this->best_natt_ext].extension);
                    317:        }
                    318: }
                    319: 
                    320: METHOD(task_t, build_i, status_t,
                    321:        private_isakmp_vendor_t *this, message_t *message)
                    322: {
                    323:        if (this->count++ == 0)
                    324:        {
                    325:                build(this, message);
                    326:        }
                    327:        if (message->get_exchange_type(message) == AGGRESSIVE && this->count > 1)
                    328:        {
                    329:                return SUCCESS;
                    330:        }
                    331:        return NEED_MORE;
                    332: }
                    333: 
                    334: METHOD(task_t, process_r, status_t,
                    335:        private_isakmp_vendor_t *this, message_t *message)
                    336: {
                    337:        this->count++;
                    338:        process(this, message);
                    339:        if (message->get_exchange_type(message) == AGGRESSIVE && this->count > 1)
                    340:        {
                    341:                return SUCCESS;
                    342:        }
                    343:        return NEED_MORE;
                    344: }
                    345: 
                    346: METHOD(task_t, build_r, status_t,
                    347:        private_isakmp_vendor_t *this, message_t *message)
                    348: {
                    349:        if (this->count == 1)
                    350:        {
                    351:                build(this, message);
                    352:        }
                    353:        if (message->get_exchange_type(message) == ID_PROT && this->count > 2)
                    354:        {
                    355:                return SUCCESS;
                    356:        }
                    357:        return NEED_MORE;
                    358: }
                    359: 
                    360: METHOD(task_t, process_i, status_t,
                    361:        private_isakmp_vendor_t *this, message_t *message)
                    362: {
                    363:        process(this, message);
                    364:        if (message->get_exchange_type(message) == ID_PROT && this->count > 2)
                    365:        {
                    366:                return SUCCESS;
                    367:        }
                    368:        return NEED_MORE;
                    369: }
                    370: 
                    371: METHOD(task_t, migrate, void,
                    372:        private_isakmp_vendor_t *this, ike_sa_t *ike_sa)
                    373: {
                    374:        this->ike_sa = ike_sa;
                    375:        this->count = 0;
                    376: }
                    377: 
                    378: METHOD(task_t, get_type, task_type_t,
                    379:        private_isakmp_vendor_t *this)
                    380: {
                    381:        return TASK_ISAKMP_VENDOR;
                    382: }
                    383: 
                    384: METHOD(task_t, destroy, void,
                    385:        private_isakmp_vendor_t *this)
                    386: {
                    387:        free(this);
                    388: }
                    389: 
                    390: /**
                    391:  * See header
                    392:  */
                    393: isakmp_vendor_t *isakmp_vendor_create(ike_sa_t *ike_sa, bool initiator)
                    394: {
                    395:        private_isakmp_vendor_t *this;
                    396: 
                    397:        INIT(this,
                    398:                .public = {
                    399:                        .task = {
                    400:                                .migrate = _migrate,
                    401:                                .get_type = _get_type,
                    402:                                .destroy = _destroy,
                    403:                        },
                    404:                },
                    405:                .initiator = initiator,
                    406:                .ike_sa = ike_sa,
                    407:                .best_natt_ext = -1,
                    408:        );
                    409: 
                    410:        if (initiator)
                    411:        {
                    412:                this->public.task.build = _build_i;
                    413:                this->public.task.process = _process_i;
                    414:        }
                    415:        else
                    416:        {
                    417:                this->public.task.build = _build_r;
                    418:                this->public.task.process = _process_r;
                    419:        }
                    420: 
                    421:        return &this->public;
                    422: }

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