Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/id_payload.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2005-2011 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      4:  * Copyright (C) 2007-2011 Tobias Brunner
                      5:  * Copyright (C) 2005 Jan Hutter
                      6:  * HSR Hochschule fuer Technik Rapperswil
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include <stddef.h>
                     20: 
                     21: #include "id_payload.h"
                     22: 
                     23: #include <daemon.h>
                     24: #include <encoding/payloads/encodings.h>
                     25: 
                     26: typedef struct private_id_payload_t private_id_payload_t;
                     27: 
                     28: /**
                     29:  * Private data of an id_payload_t object.
                     30:  */
                     31: struct private_id_payload_t {
                     32: 
                     33:        /**
                     34:         * Public id_payload_t interface.
                     35:         */
                     36:        id_payload_t public;
                     37: 
                     38:        /**
                     39:         * Next payload type.
                     40:         */
                     41:        uint8_t next_payload;
                     42: 
                     43:        /**
                     44:         * Critical flag.
                     45:         */
                     46:        bool critical;
                     47: 
                     48:        /**
                     49:         * Reserved bits
                     50:         */
                     51:        bool reserved_bit[7];
                     52: 
                     53:        /**
                     54:         * Reserved bytes
                     55:         */
                     56:        uint8_t reserved_byte[3];
                     57: 
                     58:        /**
                     59:         * Length of this payload.
                     60:         */
                     61:        uint16_t payload_length;
                     62: 
                     63:        /**
                     64:         * Type of the ID Data.
                     65:         */
                     66:        uint8_t id_type;
                     67: 
                     68:        /**
                     69:         * The contained id data value.
                     70:         */
                     71:        chunk_t id_data;
                     72: 
                     73:        /**
                     74:         * Tunneled protocol ID for IKEv1 quick modes.
                     75:         */
                     76:        uint8_t protocol_id;
                     77: 
                     78:        /**
                     79:         * Tunneled port for IKEv1 quick modes.
                     80:         */
                     81:        uint16_t port;
                     82: 
                     83:        /**
                     84:         * one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, IDv1 and PLV1_NAT_OA
                     85:         */
                     86:        payload_type_t type;
                     87: };
                     88: 
                     89: /**
                     90:  * Encoding rules for an IKEv2 ID payload
                     91:  */
                     92: static encoding_rule_t encodings_v2[] = {
                     93:        /* 1 Byte next payload type, stored in the field next_payload */
                     94:        { U_INT_8,                      offsetof(private_id_payload_t, next_payload)    },
                     95:        /* the critical bit */
                     96:        { FLAG,                         offsetof(private_id_payload_t, critical)                },
                     97:        /* 7 Bit reserved bits */
                     98:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[0]) },
                     99:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[1]) },
                    100:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[2]) },
                    101:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[3]) },
                    102:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[4]) },
                    103:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[5]) },
                    104:        { RESERVED_BIT,         offsetof(private_id_payload_t, reserved_bit[6]) },
                    105:        /* Length of the whole payload*/
                    106:        { PAYLOAD_LENGTH,       offsetof(private_id_payload_t, payload_length)  },
                    107:        /* 1 Byte ID type*/
                    108:        { U_INT_8,                      offsetof(private_id_payload_t, id_type)                 },
                    109:        /* 3 reserved bytes */
                    110:        { RESERVED_BYTE,        offsetof(private_id_payload_t, reserved_byte[0])},
                    111:        { RESERVED_BYTE,        offsetof(private_id_payload_t, reserved_byte[1])},
                    112:        { RESERVED_BYTE,        offsetof(private_id_payload_t, reserved_byte[2])},
                    113:        /* some id data bytes, length is defined in PAYLOAD_LENGTH */
                    114:        { CHUNK_DATA,           offsetof(private_id_payload_t, id_data)                 },
                    115: };
                    116: 
                    117: /*
                    118:                            1                   2                   3
                    119:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                    120:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    121:       ! Next Payload  !C!  RESERVED   !         Payload Length        !
                    122:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    123:       !   ID Type     !                 RESERVED                      |
                    124:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    125:       !                                                               !
                    126:       ~                   Identification Data                         ~
                    127:       !                                                               !
                    128:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    129: */
                    130: 
                    131: /**
                    132:  * Encoding rules for an IKEv1 ID payload
                    133:  */
                    134: static encoding_rule_t encodings_v1[] = {
                    135:        /* 1 Byte next payload type, stored in the field next_payload */
                    136:        { U_INT_8,                      offsetof(private_id_payload_t, next_payload)    },
                    137:        /* Reserved Byte is skipped */
                    138:        { RESERVED_BYTE,        offsetof(private_id_payload_t, reserved_byte[0])},
                    139:        /* Length of the whole payload*/
                    140:        { PAYLOAD_LENGTH,       offsetof(private_id_payload_t, payload_length)  },
                    141:        /* 1 Byte ID type*/
                    142:        { U_INT_8,                      offsetof(private_id_payload_t, id_type)                 },
                    143:        { U_INT_8,                      offsetof(private_id_payload_t, protocol_id)             },
                    144:        { U_INT_16,                     offsetof(private_id_payload_t, port)                    },
                    145:        /* some id data bytes, length is defined in PAYLOAD_LENGTH */
                    146:        { CHUNK_DATA,           offsetof(private_id_payload_t, id_data)                 },
                    147: };
                    148: 
                    149: /*
                    150:                            1                   2                   3
                    151:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                    152:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    153:       ! Next Payload  !    RESERVED   !         Payload Length        !
                    154:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    155:       !   ID Type     ! Protocol ID   !           Port                |
                    156:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    157:       !                                                               !
                    158:       ~                   Identification Data                         ~
                    159:       !                                                               !
                    160:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    161: */
                    162: 
                    163: METHOD(payload_t, verify, status_t,
                    164:        private_id_payload_t *this)
                    165: {
                    166:        bool bad_length = FALSE;
                    167: 
                    168:        if ((this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) &&
                    169:                this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
                    170:        {
                    171:                DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
                    172:                         this->id_type, payload_type_short_names, this->type);
                    173:                return FAILED;
                    174:        }
                    175:        switch (this->id_type)
                    176:        {
                    177:                case ID_IPV4_ADDR_RANGE:
                    178:                case ID_IPV4_ADDR_SUBNET:
                    179:                        bad_length = this->id_data.len != 8;
                    180:                        break;
                    181:                case ID_IPV6_ADDR_RANGE:
                    182:                case ID_IPV6_ADDR_SUBNET:
                    183:                        bad_length = this->id_data.len != 32;
                    184:                        break;
                    185:        }
                    186:        if (bad_length)
                    187:        {
                    188:                DBG1(DBG_ENC, "invalid %N length (%d bytes)",
                    189:                         id_type_names, this->id_type, this->id_data.len);
                    190:                return FAILED;
                    191:        }
                    192:        return SUCCESS;
                    193: }
                    194: 
                    195: METHOD(payload_t, get_encoding_rules, int,
                    196:        private_id_payload_t *this, encoding_rule_t **rules)
                    197: {
                    198:        if (this->type == PLV1_ID ||
                    199:                this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03)
                    200:        {
                    201:                *rules = encodings_v1;
                    202:                return countof(encodings_v1);
                    203:        }
                    204:        *rules = encodings_v2;
                    205:        return countof(encodings_v2);
                    206: }
                    207: 
                    208: METHOD(payload_t, get_header_length, int,
                    209:        private_id_payload_t *this)
                    210: {
                    211:        return 8;
                    212: }
                    213: 
                    214: METHOD(payload_t, get_type, payload_type_t,
                    215:        private_id_payload_t *this)
                    216: {
                    217:        return this->type;
                    218: }
                    219: 
                    220: METHOD(payload_t, get_next_type, payload_type_t,
                    221:        private_id_payload_t *this)
                    222: {
                    223:        return this->next_payload;
                    224: }
                    225: 
                    226: METHOD(payload_t, set_next_type, void,
                    227:        private_id_payload_t *this, payload_type_t type)
                    228: {
                    229:        this->next_payload = type;
                    230: }
                    231: 
                    232: METHOD(payload_t, get_length, size_t,
                    233:        private_id_payload_t *this)
                    234: {
                    235:        return this->payload_length;
                    236: }
                    237: 
                    238: METHOD(id_payload_t, get_identification, identification_t*,
                    239:        private_id_payload_t *this)
                    240: {
                    241:        return identification_create_from_encoding(this->id_type, this->id_data);
                    242: }
                    243: 
                    244: /**
                    245:  * Create a traffic selector from an range ID
                    246:  */
                    247: static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
                    248:                                                                                         ts_type_t type)
                    249: {
                    250:        return traffic_selector_create_from_bytes(this->protocol_id, type,
                    251:                chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
                    252:                chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
                    253: }
                    254: 
                    255: /**
                    256:  * Create a traffic selector from an subnet ID
                    257:  */
                    258: static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
                    259:                                                                                          ts_type_t type)
                    260: {
                    261:        traffic_selector_t *ts;
                    262:        chunk_t net, netmask;
                    263:        int i;
                    264: 
                    265:        net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
                    266:        netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2));
                    267:        for (i = 0; i < net.len; i++)
                    268:        {
                    269:                netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
                    270:        }
                    271:        ts = traffic_selector_create_from_bytes(this->protocol_id, type,
                    272:                                                                net, this->port, netmask, this->port ?: 65535);
                    273:        chunk_free(&netmask);
                    274:        return ts;
                    275: }
                    276: 
                    277: /**
                    278:  * Create a traffic selector from an IP ID
                    279:  */
                    280: static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
                    281:                                                                                  ts_type_t type)
                    282: {
                    283:        return traffic_selector_create_from_bytes(this->protocol_id, type,
                    284:                                this->id_data, this->port, this->id_data, this->port ?: 65535);
                    285: }
                    286: 
                    287: METHOD(id_payload_t, get_ts, traffic_selector_t*,
                    288:        private_id_payload_t *this)
                    289: {
                    290:        switch (this->id_type)
                    291:        {
                    292:                case ID_IPV4_ADDR_SUBNET:
                    293:                        if (this->id_data.len == 8)
                    294:                        {
                    295:                                return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
                    296:                        }
                    297:                        break;
                    298:                case ID_IPV6_ADDR_SUBNET:
                    299:                        if (this->id_data.len == 32)
                    300:                        {
                    301:                                return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
                    302:                        }
                    303:                        break;
                    304:                case ID_IPV4_ADDR_RANGE:
                    305:                        if (this->id_data.len == 8)
                    306:                        {
                    307:                                return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
                    308:                        }
                    309:                        break;
                    310:                case ID_IPV6_ADDR_RANGE:
                    311:                        if (this->id_data.len == 32)
                    312:                        {
                    313:                                return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
                    314:                        }
                    315:                        break;
                    316:                case ID_IPV4_ADDR:
                    317:                        if (this->id_data.len == 4)
                    318:                        {
                    319:                                return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
                    320:                        }
                    321:                        break;
                    322:                case ID_IPV6_ADDR:
                    323:                        if (this->id_data.len == 16)
                    324:                        {
                    325:                                return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
                    326:                        }
                    327:                        break;
                    328:                default:
                    329:                        break;
                    330:        }
                    331:        return NULL;
                    332: }
                    333: 
                    334: METHOD(id_payload_t, get_encoded, chunk_t,
                    335:        private_id_payload_t *this)
                    336: {
                    337:        uint16_t port = htons(this->port);
                    338:        return chunk_cat("cccc", chunk_from_thing(this->id_type),
                    339:                                         chunk_from_thing(this->protocol_id),
                    340:                                         chunk_from_thing(port), this->id_data);
                    341: }
                    342: 
                    343: METHOD2(payload_t, id_payload_t, destroy, void,
                    344:        private_id_payload_t *this)
                    345: {
                    346:        free(this->id_data.ptr);
                    347:        free(this);
                    348: }
                    349: 
                    350: /*
                    351:  * Described in header.
                    352:  */
                    353: id_payload_t *id_payload_create(payload_type_t type)
                    354: {
                    355:        private_id_payload_t *this;
                    356: 
                    357:        INIT(this,
                    358:                .public = {
                    359:                        .payload_interface = {
                    360:                                .verify = _verify,
                    361:                                .get_encoding_rules = _get_encoding_rules,
                    362:                                .get_header_length = _get_header_length,
                    363:                                .get_length = _get_length,
                    364:                                .get_next_type = _get_next_type,
                    365:                                .set_next_type = _set_next_type,
                    366:                                .get_type = _get_type,
                    367:                                .destroy = _destroy,
                    368:                        },
                    369:                        .get_identification = _get_identification,
                    370:                        .get_encoded = _get_encoded,
                    371:                        .get_ts = _get_ts,
                    372:                        .destroy = _destroy,
                    373:                },
                    374:                .next_payload = PL_NONE,
                    375:                .payload_length = get_header_length(this),
                    376:                .type = type,
                    377:        );
                    378:        return &this->public;
                    379: }
                    380: 
                    381: /*
                    382:  * Described in header.
                    383:  */
                    384: id_payload_t *id_payload_create_from_identification(payload_type_t type,
                    385:                                                                                                        identification_t *id)
                    386: {
                    387:        private_id_payload_t *this;
                    388: 
                    389:        this = (private_id_payload_t*)id_payload_create(type);
                    390:        this->id_data = chunk_clone(id->get_encoding(id));
                    391:        this->id_type = id->get_type(id);
                    392:        this->payload_length += this->id_data.len;
                    393: 
                    394:        return &this->public;
                    395: }
                    396: 
                    397: /*
                    398:  * Described in header.
                    399:  */
                    400: id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
                    401: {
                    402:        private_id_payload_t *this;
                    403:        uint8_t mask;
                    404:        host_t *net;
                    405: 
                    406:        this = (private_id_payload_t*)id_payload_create(PLV1_ID);
                    407: 
                    408:        if (ts->is_host(ts, NULL))
                    409:        {
                    410:                if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
                    411:                {
                    412:                        this->id_type = ID_IPV4_ADDR;
                    413:                }
                    414:                else
                    415:                {
                    416:                        this->id_type = ID_IPV6_ADDR;
                    417:                }
                    418:                this->id_data = chunk_clone(ts->get_from_address(ts));
                    419:        }
                    420:        else if (ts->to_subnet(ts, &net, &mask))
                    421:        {
                    422:                uint8_t netmask[16], len, byte;
                    423: 
                    424:                if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
                    425:                {
                    426:                        this->id_type = ID_IPV4_ADDR_SUBNET;
                    427:                        len = 4;
                    428:                }
                    429:                else
                    430:                {
                    431:                        this->id_type = ID_IPV6_ADDR_SUBNET;
                    432:                        len = 16;
                    433:                }
                    434:                memset(netmask, 0, sizeof(netmask));
                    435:                for (byte = 0; byte < sizeof(netmask); byte++)
                    436:                {
                    437:                        if (mask < 8)
                    438:                        {
                    439:                                netmask[byte] = 0xFF << (8 - mask);
                    440:                                break;
                    441:                        }
                    442:                        netmask[byte] = 0xFF;
                    443:                        mask -= 8;
                    444:                }
                    445:                this->id_data = chunk_cat("cc", net->get_address(net),
                    446:                                                                  chunk_create(netmask, len));
                    447:                net->destroy(net);
                    448:        }
                    449:        else
                    450:        {
                    451:                if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
                    452:                {
                    453:                        this->id_type = ID_IPV4_ADDR_RANGE;
                    454:                }
                    455:                else
                    456:                {
                    457:                        this->id_type = ID_IPV6_ADDR_RANGE;
                    458:                }
                    459:                this->id_data = chunk_cat("cc",
                    460:                                                        ts->get_from_address(ts), ts->get_to_address(ts));
                    461:                net->destroy(net);
                    462:        }
                    463:        this->port = ts->get_from_port(ts);
                    464:        this->protocol_id = ts->get_protocol(ts);
                    465:        this->payload_length += this->id_data.len;
                    466: 
                    467:        return &this->public;
                    468: }
                    469: 

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