Annotation of embedaddon/strongswan/src/libimcv/pa_tnc/pa_tnc_attr_manager.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011-2014 Andreas Steffen
                      3:  *
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "pa_tnc_attr_manager.h"
                     18: 
                     19: #include "imcv.h"
                     20: #include "pa_tnc_attr.h"
                     21: #include "ietf/ietf_attr_pa_tnc_error.h"
                     22: 
                     23: #include <collections/linked_list.h>
                     24: #include <utils/debug.h>
                     25: 
                     26: typedef struct private_pa_tnc_attr_manager_t private_pa_tnc_attr_manager_t;
                     27: typedef struct entry_t entry_t;
                     28: 
                     29: struct entry_t {
                     30:        pen_t vendor_id;
                     31:        enum_name_t *attr_names;
                     32:        pa_tnc_attr_create_t attr_create;
                     33: };
                     34: 
                     35: /**
                     36:  * Private data of a pa_tnc_attr_manager_t object.
                     37:  *
                     38:  */
                     39: struct private_pa_tnc_attr_manager_t {
                     40: 
                     41:        /**
                     42:         * Public pa_tnc_attr_manager_t interface.
                     43:         */
                     44:        pa_tnc_attr_manager_t public;
                     45: 
                     46:        /**
                     47:         * List of PA-TNC vendor attributes
                     48:         */
                     49:        linked_list_t *list;
                     50: };
                     51: 
                     52: METHOD(pa_tnc_attr_manager_t, add_vendor, void,
                     53:        private_pa_tnc_attr_manager_t *this, pen_t vendor_id,
                     54:        pa_tnc_attr_create_t attr_create, enum_name_t *attr_names)
                     55: {
                     56:        entry_t *entry;
                     57: 
                     58:        entry = malloc_thing(entry_t);
                     59:        entry->vendor_id = vendor_id;
                     60:        entry->attr_create = attr_create;
                     61:        entry->attr_names = attr_names;
                     62: 
                     63:        this->list->insert_last(this->list, entry);
                     64:        DBG2(DBG_TNC, "added %N attributes", pen_names, vendor_id);
                     65: }
                     66: 
                     67: METHOD(pa_tnc_attr_manager_t, remove_vendor, void,
                     68:        private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
                     69: {
                     70:        enumerator_t *enumerator;
                     71:        entry_t *entry;
                     72: 
                     73:        enumerator = this->list->create_enumerator(this->list);
                     74:        while (enumerator->enumerate(enumerator, &entry))
                     75:        {
                     76:                if (entry->vendor_id == vendor_id)
                     77:                {
                     78:                        this->list->remove_at(this->list, enumerator);
                     79:                        free(entry);
                     80:                        DBG2(DBG_TNC, "removed %N attributes", pen_names, vendor_id);
                     81:                }
                     82:        }
                     83:        enumerator->destroy(enumerator);
                     84: }
                     85: 
                     86: METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*,
                     87:        private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
                     88: {
                     89:        enumerator_t *enumerator;
                     90:        entry_t *entry;
                     91:        enum_name_t *attr_names = NULL;
                     92: 
                     93:        enumerator = this->list->create_enumerator(this->list);
                     94:        while (enumerator->enumerate(enumerator, &entry))
                     95:        {
                     96:                if (entry->vendor_id == vendor_id)
                     97:                {
                     98:                        attr_names = entry->attr_names;
                     99:                        break;
                    100:                }
                    101:        }
                    102:        enumerator->destroy(enumerator);
                    103: 
                    104:        return attr_names;
                    105: }
                    106: 
                    107: /**
                    108:  *  PA-TNC attribute
                    109:  *
                    110:  *                       1                   2                   3
                    111:  *  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
                    112:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    113:  *  |     Flags     |          PA-TNC Attribute Vendor ID           |
                    114:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    115:  *  |                     PA-TNC Attribute Type                     |
                    116:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    117:  *  |                    PA-TNC Attribute Length                    |
                    118:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    119:  *  |                 Attribute Value (Variable Length)             |
                    120:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                    121:  */
                    122: 
                    123: METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
                    124:        private_pa_tnc_attr_manager_t *this, bio_reader_t *reader, bool segmented,
                    125:        uint32_t *offset, chunk_t msg_info, pa_tnc_attr_t **error)
                    126: {
                    127:        uint8_t flags;
                    128:        uint32_t type, length, value_len;
                    129:        chunk_t value;
                    130:        ietf_attr_pa_tnc_error_t *error_attr;
                    131:        pen_t vendor_id;
                    132:        pen_type_t unsupported_type;
                    133:        pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
                    134:        enum_name_t *pa_attr_names;
                    135:        pa_tnc_attr_t *attr = NULL;
                    136:        enumerator_t *enumerator;
                    137:        entry_t *entry;
                    138: 
                    139:        /* properly initialize error return argument in case of no error */
                    140:        *error = NULL;
                    141: 
                    142:        if (reader->remaining(reader) < PA_TNC_ATTR_HEADER_SIZE)
                    143:        {
                    144:                DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
                    145:                *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
                    146:                                                        msg_info, *offset);
                    147:                return NULL;
                    148:        }
                    149:        reader->read_uint8 (reader, &flags);
                    150:        reader->read_uint24(reader, &vendor_id);
                    151:        reader->read_uint32(reader, &type);
                    152:        reader->read_uint32(reader, &length);
                    153: 
                    154:        pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
                    155:                                                                                                          vendor_id);
                    156:        if (pa_attr_names)
                    157:        {
                    158:                DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
                    159:                                          "0x%06x/0x%08x", pen_names, vendor_id,
                    160:                                           pa_attr_names, type, vendor_id, type);
                    161:        }
                    162:        else
                    163:        {
                    164:                DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
                    165:                                          "0x%06x/0x%08x", pen_names, vendor_id,
                    166:                                           vendor_id, type);
                    167:        }
                    168: 
                    169:        if (length < PA_TNC_ATTR_HEADER_SIZE)
                    170:        {
                    171:                DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
                    172:                                           length);
                    173:                *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
                    174:                                                msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
                    175:                return NULL;
                    176:        }
                    177:        length -= PA_TNC_ATTR_HEADER_SIZE;
                    178:        value_len = segmented ? reader->remaining(reader) : length;
                    179: 
                    180:        if (!reader->read_data(reader, value_len, &value))
                    181:        {
                    182:                DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
                    183:                *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
                    184:                                                msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
                    185:                return NULL;
                    186:        }
                    187:        DBG3(DBG_TNC, "%B", &value);
                    188: 
                    189:        if (vendor_id == PEN_RESERVED)
                    190:        {
                    191:                *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
                    192:                                                msg_info, *offset + 1);
                    193:                return NULL;
                    194:        }
                    195:        if (type == IETF_ATTR_RESERVED)
                    196:        {
                    197:                *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
                    198:                                                msg_info, *offset + 4);
                    199:                return NULL;
                    200:        }
                    201: 
                    202:        /* check if the attribute type is registered */
                    203:        enumerator = this->list->create_enumerator(this->list);
                    204:        while (enumerator->enumerate(enumerator, &entry))
                    205:        {
                    206:                if (entry->vendor_id == vendor_id)
                    207:                {
                    208:                        if (entry->attr_create)
                    209:                        {
                    210:                                attr = entry->attr_create(type, length, value);
                    211:                        }
                    212:                        break;
                    213:                }
                    214:        }
                    215:        enumerator->destroy(enumerator);
                    216: 
                    217:        if (!attr)
                    218:        {
                    219:                if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
                    220:                {
                    221:                        DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
                    222:                        (*offset) += PA_TNC_ATTR_HEADER_SIZE + length;
                    223:                        return NULL;
                    224:                }
                    225: 
                    226:                DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
                    227:                unsupported_type = pen_type_create(vendor_id, type);
                    228:                error_code = pen_type_create(PEN_IETF, PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
                    229:                *error = ietf_attr_pa_tnc_error_create(error_code, msg_info);
                    230:                error_attr = (ietf_attr_pa_tnc_error_t*)(*error);
                    231:                error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
                    232:                return NULL;
                    233:        }
                    234:        (*offset) += PA_TNC_ATTR_HEADER_SIZE;
                    235: 
                    236:        return attr;
                    237: }
                    238: 
                    239: METHOD(pa_tnc_attr_manager_t, construct, pa_tnc_attr_t*,
                    240:        private_pa_tnc_attr_manager_t *this, pen_t vendor_id, uint32_t type,
                    241:        chunk_t value)
                    242: {
                    243:        enum_name_t *pa_attr_names;
                    244:        pa_tnc_attr_t *attr = NULL;
                    245:        enumerator_t *enumerator;
                    246:        entry_t *entry;
                    247: 
                    248:        pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
                    249:                                                                                                          vendor_id);
                    250:        if (pa_attr_names)
                    251:        {
                    252:                DBG2(DBG_TNC, "generating PA-TNC attribute type '%N/%N' "
                    253:                                          "0x%06x/0x%08x", pen_names, vendor_id,
                    254:                                           pa_attr_names, type, vendor_id, type);
                    255:        }
                    256:        else
                    257:        {
                    258:                DBG2(DBG_TNC, "generating PA-TNC attribute type '%N' "
                    259:                                          "0x%06x/0x%08x", pen_names, vendor_id,
                    260:                                           vendor_id, type);
                    261:        }
                    262:        enumerator = this->list->create_enumerator(this->list);
                    263:        while (enumerator->enumerate(enumerator, &entry))
                    264:        {
                    265:                if (entry->vendor_id == vendor_id)
                    266:                {
                    267:                        if (entry->attr_create)
                    268:                        {
                    269:                                attr = entry->attr_create(type, value.len, value);
                    270:                        }
                    271:                        break;
                    272:                }
                    273:        }
                    274:        enumerator->destroy(enumerator);
                    275:        return attr;
                    276: }
                    277: 
                    278: METHOD(pa_tnc_attr_manager_t, destroy, void,
                    279:        private_pa_tnc_attr_manager_t *this)
                    280: {
                    281:        this->list->destroy_function(this->list, free);
                    282:        free(this);
                    283: }
                    284: 
                    285: /**
                    286:  * See header
                    287:  */
                    288: pa_tnc_attr_manager_t *pa_tnc_attr_manager_create(void)
                    289: {
                    290:        private_pa_tnc_attr_manager_t *this;
                    291: 
                    292:        INIT(this,
                    293:                .public = {
                    294:                        .add_vendor = _add_vendor,
                    295:                        .remove_vendor = _remove_vendor,
                    296:                        .get_names = _get_names,
                    297:                        .create = _create,
                    298:                        .construct = _construct,
                    299:                        .destroy = _destroy,
                    300:                },
                    301:                .list = linked_list_create(),
                    302:        );
                    303: 
                    304:        return &this->public;
                    305: }
                    306: 

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