Annotation of embedaddon/strongswan/src/libimcv/ietf/ietf_attr_pa_tnc_error.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011-2018 Andreas Steffen
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "ietf_attr_pa_tnc_error.h"
                     17: 
                     18: #include <pa_tnc/pa_tnc_msg.h>
                     19: #include <bio/bio_writer.h>
                     20: #include <bio/bio_reader.h>
                     21: #include <utils/debug.h>
                     22: 
                     23: ENUM(pa_tnc_error_code_names, PA_ERROR_RESERVED,
                     24:                                                          PA_ERROR_SWIMA_SUBSCRIPTION_ID_REUSE,
                     25:        "Reserved",
                     26:        "Invalid Parameter",
                     27:        "Version Not Supported",
                     28:        "Attribute Type Not Supported",
                     29:        "SWIMA Error",
                     30:        "SWIMA Subscription Denied",
                     31:        "SWIMA Response Too Large",
                     32:        "SWIMA Subscription Fulfillment Error",
                     33:        "SWIMA Subscription ID Reuse"
                     34: );
                     35: 
                     36: typedef struct private_ietf_attr_pa_tnc_error_t private_ietf_attr_pa_tnc_error_t;
                     37: 
                     38: /**
                     39:  * PA-TNC Error Attribute Type  (see section 4.2.8 of RFC 5792)
                     40:  *
                     41:  *                       1                   2                   3
                     42:  *   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
                     43:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     44:  *  |    Reserved   |            PA-TNC Error Code Vendor ID        |
                     45:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     46:  *  |                        PA-TNC Error Code                      |
                     47:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     48:  *  |                 Error Information (Variable Length)           |
                     49:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     50:  */
                     51: 
                     52: #define PA_ERROR_HEADER_SIZE           8
                     53: #define PA_ERROR_RESERVED                      0x00
                     54: 
                     55: /**
                     56:  * All IETF Error Types return the first 8 bytes of the erroneous PA-TNC message
                     57:  *
                     58:  *                       1                   2                   3
                     59:  *   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
                     60:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     61:  *  |    Version    |            Copy of Reserved                   |
                     62:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     63:  *  |                       Message Identifier                      |
                     64:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     65:  */
                     66: 
                     67: #define PA_ERROR_MSG_INFO_SIZE         8
                     68: #define PA_ERROR_MSG_INFO_MAX_SIZE     1024
                     69: 
                     70: /**
                     71:  * "Invalid Parameter" Error Code
                     72:  *                       1                   2                   3
                     73:  *   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
                     74:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     75:  *  |                             Offset                            |
                     76:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     77:  */
                     78: 
                     79: /**
                     80:  * "Version Not Supported" Error Code
                     81:  *
                     82:  *                       1                   2                   3
                     83:  *   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
                     84:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     85:  *  |  Max Version  |  Min Version  |            Reserved           |
                     86:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     87:  */
                     88: 
                     89: #define PA_ERROR_VERSION_RESERVED      0x0000
                     90: 
                     91: /**
                     92:  * "Attribute Type Not Supported" Error Code
                     93:  *
                     94:  *                        1                   2                   3
                     95:  *   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
                     96:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     97:  *  |     Flags     |          PA-TNC Attribute Vendor ID           |
                     98:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     99:  *  |                     PA-TNC Attribute Type                     |
                    100:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    101:  */
                    102: 
                    103: #define PA_ERROR_ATTR_INFO_SIZE                8
                    104: 
                    105: /**
                    106:  * Private data of an ietf_attr_pa_tnc_error_t object.
                    107:  */
                    108: struct private_ietf_attr_pa_tnc_error_t {
                    109: 
                    110:        /**
                    111:         * Public members of ietf_attr_pa_tnc_error_t
                    112:         */
                    113:        ietf_attr_pa_tnc_error_t public;
                    114: 
                    115:        /**
                    116:         * Vendor-specific attribute type
                    117:         */
                    118:        pen_type_t type;
                    119: 
                    120:        /**
                    121:         * Length of attribute value
                    122:         */
                    123:        size_t length;
                    124: 
                    125:        /**
                    126:         * Attribute value or segment
                    127:         */
                    128:        chunk_t value;
                    129: 
                    130:        /**
                    131:         * Noskip flag
                    132:         */
                    133:        bool noskip_flag;
                    134: 
                    135:        /**
                    136:         * Vendor-specific error code
                    137:         */
                    138:        pen_type_t error_code;
                    139: 
                    140:        /**
                    141:         * First 8 bytes of erroneous PA-TNC message
                    142:         */
                    143:        chunk_t msg_info;
                    144: 
                    145:        /**
                    146:         * Flags of unsupported PA-TNC attribute
                    147:         */
                    148:        uint8_t flags;
                    149: 
                    150:        /**
                    151:         * Vendor ID and type of unsupported PA-TNC attribute
                    152:         */
                    153:        pen_type_t unsupported_type;
                    154: 
                    155:        /**
                    156:         * PA-TNC error offset
                    157:         */
                    158:        uint32_t error_offset;
                    159: 
                    160:        /**
                    161:         * Reference count
                    162:         */
                    163:        refcount_t ref;
                    164: };
                    165: 
                    166: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
                    167:        private_ietf_attr_pa_tnc_error_t *this)
                    168: {
                    169:        return this->type;
                    170: }
                    171: 
                    172: METHOD(pa_tnc_attr_t, get_value, chunk_t,
                    173:        private_ietf_attr_pa_tnc_error_t *this)
                    174: {
                    175:        return this->value;
                    176: }
                    177: 
                    178: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
                    179:        private_ietf_attr_pa_tnc_error_t *this)
                    180: {
                    181:        return this->noskip_flag;
                    182: }
                    183: 
                    184: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
                    185:        private_ietf_attr_pa_tnc_error_t *this, bool noskip)
                    186: {
                    187:        this->noskip_flag = noskip;
                    188: }
                    189: 
                    190: METHOD(pa_tnc_attr_t, build, void,
                    191:        private_ietf_attr_pa_tnc_error_t *this)
                    192: {
                    193:        bio_writer_t *writer;
                    194: 
                    195:        if (this->value.ptr)
                    196:        {
                    197:                return;
                    198:        }
                    199:        writer = bio_writer_create(PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE);
                    200:        writer->write_uint8 (writer, PA_ERROR_RESERVED);
                    201:        writer->write_uint24(writer, this->error_code.vendor_id);
                    202:        writer->write_uint32(writer, this->error_code.type);
                    203:        writer->write_data  (writer, this->msg_info);
                    204: 
                    205:        if (this->error_code.vendor_id == PEN_IETF)
                    206:        {
                    207:                switch (this->error_code.type)
                    208:                {
                    209:                        case PA_ERROR_INVALID_PARAMETER:
                    210:                                writer->write_uint32(writer, this->error_offset);
                    211:                                break;
                    212:                        case PA_ERROR_VERSION_NOT_SUPPORTED:
                    213:                                writer->write_uint8 (writer, PA_TNC_VERSION);
                    214:                                writer->write_uint8 (writer, PA_TNC_VERSION);
                    215:                                writer->write_uint16(writer, PA_ERROR_VERSION_RESERVED);
                    216:                                break;
                    217:                        case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
                    218:                                writer->write_uint8 (writer, this->flags);
                    219:                                writer->write_uint24(writer, this->unsupported_type.vendor_id);
                    220:                                writer->write_uint32(writer, this->unsupported_type.type);
                    221:                                break;
                    222:                        default:
                    223:                                break;
                    224:                }
                    225:        }
                    226:        this->value = writer->extract_buf(writer);
                    227:        this->length = this->value.len;
                    228:        writer->destroy(writer);
                    229: }
                    230: 
                    231: METHOD(pa_tnc_attr_t, process, status_t,
                    232:        private_ietf_attr_pa_tnc_error_t *this, uint32_t *offset)
                    233: {
                    234:        bio_reader_t *reader;
                    235:        uint8_t reserved;
                    236:        uint32_t vendor_id, type;
                    237: 
                    238:        *offset = 0;
                    239: 
                    240:        if (this->value.len < this->length)
                    241:        {
                    242:                return NEED_MORE;
                    243:        }
                    244:        if (this->value.len < PA_ERROR_HEADER_SIZE)
                    245:        {
                    246:                DBG1(DBG_TNC, "insufficient data for PA-TNC error header");
                    247:                return FAILED;
                    248:        }
                    249:        reader = bio_reader_create(this->value);
                    250:        reader->read_uint8 (reader, &reserved);
                    251:        reader->read_uint24(reader, &this->error_code.vendor_id);
                    252:        reader->read_uint32(reader, &this->error_code.type);
                    253: 
                    254:        if (this->error_code.vendor_id == PEN_IETF &&
                    255:                this->error_code.type <= PA_ERROR_PA_TNC_MSG_ROOF)
                    256:        {
                    257:                if (!reader->read_data(reader, PA_ERROR_MSG_INFO_SIZE, &this->msg_info))
                    258:                {
                    259:                        reader->destroy(reader);
                    260:                        DBG1(DBG_TNC, "insufficient data for IETF error information");
                    261:                        *offset = PA_ERROR_HEADER_SIZE;
                    262:                        return FAILED;
                    263:                }
                    264:                this->msg_info = chunk_clone(this->msg_info);
                    265: 
                    266:                switch (this->error_code.type)
                    267:                {
                    268:                        case PA_ERROR_INVALID_PARAMETER:
                    269:                                if (!reader->read_uint32(reader, &this->error_offset))
                    270:                                {
                    271:                                        reader->destroy(reader);
                    272:                                        DBG1(DBG_TNC, "insufficient data for error offset field");
                    273:                                        *offset = PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE;
                    274:                                        return FAILED;
                    275:                                }
                    276:                                break;
                    277:                        case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
                    278:                                if (reader->remaining(reader) < PA_ERROR_ATTR_INFO_SIZE)
                    279:                                {
                    280:                                        reader->destroy(reader);
                    281:                                        DBG1(DBG_TNC, "insufficient data for unsupported attribute "
                    282:                                                                  "information");
                    283:                                        *offset = PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE;
                    284:                                        return FAILED;
                    285:                                }
                    286:                                reader->read_uint8 (reader, &this->flags);
                    287:                                reader->read_uint24(reader, &vendor_id);
                    288:                                reader->read_uint32(reader, &type);
                    289:                                this->unsupported_type = pen_type_create(vendor_id, type);
                    290:                                break;
                    291:                        default:
                    292:                                break;
                    293:                }
                    294:        }
                    295:        else
                    296:        {
                    297:                reader->read_data(reader, reader->remaining(reader), &this->msg_info);
                    298:                this->msg_info = chunk_clone(this->msg_info);
                    299:        }
                    300:        reader->destroy(reader);
                    301: 
                    302:        return SUCCESS;
                    303: }
                    304: 
                    305: METHOD(pa_tnc_attr_t, add_segment, void,
                    306:        private_ietf_attr_pa_tnc_error_t *this, chunk_t segment)
                    307: {
                    308:        this->value = chunk_cat("mc", this->value, segment);
                    309: }
                    310: 
                    311: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
                    312:        private_ietf_attr_pa_tnc_error_t *this)
                    313: {
                    314:        ref_get(&this->ref);
                    315:        return &this->public.pa_tnc_attribute;
                    316: }
                    317: 
                    318: METHOD(pa_tnc_attr_t, destroy, void,
                    319:        private_ietf_attr_pa_tnc_error_t *this)
                    320: {
                    321:        if (ref_put(&this->ref))
                    322:        {
                    323:                free(this->value.ptr);
                    324:                free(this->msg_info.ptr);
                    325:                free(this);
                    326:        }
                    327: }
                    328: 
                    329: METHOD(ietf_attr_pa_tnc_error_t, get_error_code, pen_type_t,
                    330:        private_ietf_attr_pa_tnc_error_t *this)
                    331: {
                    332:        return this->error_code;
                    333: }
                    334: 
                    335: METHOD(ietf_attr_pa_tnc_error_t, get_msg_info, chunk_t,
                    336:        private_ietf_attr_pa_tnc_error_t *this)
                    337: {
                    338:        return this->msg_info;
                    339: }
                    340: 
                    341: METHOD(ietf_attr_pa_tnc_error_t, get_unsupported_attr, pen_type_t,
                    342:        private_ietf_attr_pa_tnc_error_t *this, uint8_t *flags)
                    343: {
                    344:        if (flags)
                    345:        {
                    346:                *flags = this->flags;
                    347:        }
                    348:        return this->unsupported_type;
                    349: }
                    350: 
                    351: METHOD(ietf_attr_pa_tnc_error_t, set_unsupported_attr, void,
                    352:        private_ietf_attr_pa_tnc_error_t *this, uint8_t flags, pen_type_t type)
                    353: {
                    354:        this->flags = flags;
                    355:        this->unsupported_type = type;
                    356: }
                    357: 
                    358: METHOD(ietf_attr_pa_tnc_error_t, get_offset, uint32_t,
                    359:        private_ietf_attr_pa_tnc_error_t *this)
                    360: {
                    361:        return this->error_offset;
                    362: }
                    363: 
                    364: /**
                    365:  * Generic constructor
                    366:  */
                    367: static private_ietf_attr_pa_tnc_error_t* create_generic()
                    368: {
                    369:        private_ietf_attr_pa_tnc_error_t *this;
                    370: 
                    371:        INIT(this,
                    372:                .public = {
                    373:                        .pa_tnc_attribute = {
                    374:                                .get_type = _get_type,
                    375:                                .get_value = _get_value,
                    376:                                .get_noskip_flag = _get_noskip_flag,
                    377:                                .set_noskip_flag = _set_noskip_flag,
                    378:                                .build = _build,
                    379:                                .process = _process,
                    380:                                .add_segment = _add_segment,
                    381:                                .get_ref = _get_ref,
                    382:                                .destroy = _destroy,
                    383:                        },
                    384:                        .get_error_code = _get_error_code,
                    385:                        .get_msg_info = _get_msg_info,
                    386:                        .get_unsupported_attr = _get_unsupported_attr,
                    387:                        .set_unsupported_attr = _set_unsupported_attr,
                    388:                        .get_offset = _get_offset,
                    389:                },
                    390:                .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
                    391:                .ref = 1,
                    392:        );
                    393: 
                    394:        return this;
                    395: }
                    396: 
                    397: /**
                    398:  * Described in header.
                    399:  */
                    400: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
                    401:                                                                                         chunk_t msg_info)
                    402: {
                    403:        private_ietf_attr_pa_tnc_error_t *this;
                    404: 
                    405:        if (error_code.vendor_id == PEN_IETF &&
                    406:                error_code.type <= PA_ERROR_PA_TNC_MSG_ROOF)
                    407:        {
                    408:                msg_info.len = PA_ERROR_MSG_INFO_SIZE;
                    409:        }
                    410:        else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE)
                    411:        {
                    412:                msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE;
                    413:        }
                    414: 
                    415:        this = create_generic();
                    416:        this->error_code = error_code;
                    417:        this->msg_info = chunk_clone(msg_info);
                    418: 
                    419:        return &this->public.pa_tnc_attribute;
                    420: }
                    421: 
                    422: /**
                    423:  * Described in header.
                    424:  */
                    425: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
                    426:                                                                                                                 chunk_t msg_info,
                    427:                                                                                                                 uint32_t error_offset)
                    428: {
                    429:        private_ietf_attr_pa_tnc_error_t *this;
                    430: 
                    431:        /* the first 8 bytes of the erroneous PA-TNC message are sent back */
                    432:        msg_info.len = PA_ERROR_MSG_INFO_SIZE;
                    433: 
                    434:        this = create_generic();
                    435:        this->error_code = error_code;
                    436:        this->msg_info = chunk_clone(msg_info);
                    437:        this->error_offset = error_offset;
                    438: 
                    439:        return &this->public.pa_tnc_attribute;
                    440: }
                    441: 
                    442: /**
                    443:  * Described in header.
                    444:  */
                    445: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(size_t length,
                    446:                                                                                                           chunk_t data)
                    447: {
                    448:        private_ietf_attr_pa_tnc_error_t *this;
                    449: 
                    450:        this = create_generic();
                    451:        this->length = length;
                    452:        this->value = chunk_clone(data);
                    453: 
                    454:        return &this->public.pa_tnc_attribute;
                    455: }

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