Annotation of embedaddon/strongswan/src/libimcv/pa_tnc/pa_tnc_attr_manager.c, revision 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>