Annotation of embedaddon/strongswan/src/libimcv/ietf/swima/ietf_swima_attr_sw_inv.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2017 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_swima_attr_sw_inv.h"
        !            17: #include "swima/swima_record.h"
        !            18: 
        !            19: #include <pa_tnc/pa_tnc_msg.h>
        !            20: #include <bio/bio_writer.h>
        !            21: #include <bio/bio_reader.h>
        !            22: #include <utils/debug.h>
        !            23: 
        !            24: 
        !            25: typedef struct private_ietf_swima_attr_sw_inv_t private_ietf_swima_attr_sw_inv_t;
        !            26: 
        !            27: /**
        !            28:  * Software [Identifier] Inventory
        !            29:  * see sections 5.8/5.10 of RFC 8412 SWIMA
        !            30:  *
        !            31:  *                       1                   2                   3
        !            32:  *   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
        !            33:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            34:  *  |     Flags     |           Software Identifier Count           |
        !            35:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            36:  *  |               Request ID Copy / Subscription ID               |
        !            37:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            38:  *  |                           EID Epoch                           |
        !            39:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            40:  *  |                           Last EID                            |
        !            41:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            42:  *  |                       Record Identifier                       |
        !            43:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            44:  *  |              Data Model Type PEN              |Data Model Type|
        !            45:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            46:  *  | Source ID Num |   Reserved    |  Software Identifier Length   |
        !            47:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            48:  *  |             Software Identifier (Variable Length)             |
        !            49:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            50:  *  |    Software Locator Length    |  Software Locator (Var. Len)  |
        !            51:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            52:  *
        !            53:  * Software Inventory only
        !            54:  * see section 5.10 of IETF SW Inventory Message and Attributes for PA-TNC
        !            55:  *
        !            56:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            57:  *  |                          Record Length                        |
        !            58:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            59:  *  |                   Record (Variable length)                    |
        !            60:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !            61:  */
        !            62: 
        !            63: /**
        !            64:  * Private data of an ietf_swima_attr_sw_inv_t object.
        !            65:  */
        !            66: struct private_ietf_swima_attr_sw_inv_t {
        !            67: 
        !            68:        /**
        !            69:         * Public members of ietf_swima_attr_sw_inv_t
        !            70:         */
        !            71:        ietf_swima_attr_sw_inv_t public;
        !            72: 
        !            73:        /**
        !            74:         * Vendor-specific attribute type
        !            75:         */
        !            76:        pen_type_t type;
        !            77: 
        !            78:        /**
        !            79:         * Length of attribute value
        !            80:         */
        !            81:        size_t length;
        !            82: 
        !            83:        /**
        !            84:         * Offset up to which attribute value has been processed
        !            85:         */
        !            86:        size_t offset;
        !            87: 
        !            88:        /**
        !            89:         * Current position of attribute value pointer
        !            90:         */
        !            91:        chunk_t value;
        !            92: 
        !            93:        /**
        !            94:         * Contains complete attribute or current segment
        !            95:         */
        !            96:        chunk_t segment;
        !            97: 
        !            98:        /**
        !            99:         * Noskip flag
        !           100:         */
        !           101:        bool noskip_flag;
        !           102: 
        !           103:        /**
        !           104:         * Request ID
        !           105:         */
        !           106:        uint32_t request_id;
        !           107: 
        !           108:        /**
        !           109:         * Attribute flags
        !           110:         */
        !           111:        uint8_t flags;
        !           112: 
        !           113:        /**
        !           114:         * Number of unprocessed software inventory evidence records in attribute
        !           115:         */
        !           116:        uint32_t record_count;
        !           117: 
        !           118:        /**
        !           119:         * SWID Tag ID Inventory
        !           120:         */
        !           121:        swima_inventory_t *inventory;
        !           122: 
        !           123:        /**
        !           124:         * Reference count
        !           125:         */
        !           126:        refcount_t ref;
        !           127: };
        !           128: 
        !           129: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
        !           130:        private_ietf_swima_attr_sw_inv_t *this)
        !           131: {
        !           132:        return this->type;
        !           133: }
        !           134: 
        !           135: METHOD(pa_tnc_attr_t, get_value, chunk_t,
        !           136:        private_ietf_swima_attr_sw_inv_t *this)
        !           137: {
        !           138:        return this->value;
        !           139: }
        !           140: 
        !           141: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
        !           142:        private_ietf_swima_attr_sw_inv_t *this)
        !           143: {
        !           144:        return this->noskip_flag;
        !           145: }
        !           146: 
        !           147: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
        !           148:        private_ietf_swima_attr_sw_inv_t *this, bool noskip)
        !           149: {
        !           150:        this->noskip_flag = noskip;
        !           151: }
        !           152: 
        !           153: /**
        !           154:  * This function is shared with ietf_swima_attr_sw_ev.c
        !           155:  **/
        !           156: extern void ietf_swima_attr_sw_ev_build_sw_record(bio_writer_t *writer,
        !           157:                        uint8_t action, swima_record_t *sw_record, bool has_record);
        !           158: 
        !           159: METHOD(pa_tnc_attr_t, build, void,
        !           160:        private_ietf_swima_attr_sw_inv_t *this)
        !           161: {
        !           162:        bio_writer_t *writer;
        !           163:        swima_record_t *sw_record;
        !           164:        uint32_t last_eid, eid_epoch;
        !           165:        enumerator_t *enumerator;
        !           166: 
        !           167:        if (this->value.ptr)
        !           168:        {
        !           169:                return;
        !           170:        }
        !           171:        last_eid = this->inventory->get_eid(this->inventory, &eid_epoch);
        !           172: 
        !           173:        writer = bio_writer_create(IETF_SWIMA_SW_INV_MIN_SIZE);
        !           174:        writer->write_uint8 (writer, this->flags);
        !           175:        writer->write_uint24(writer, this->inventory->get_count(this->inventory));
        !           176:        writer->write_uint32(writer, this->request_id);
        !           177:        writer->write_uint32(writer, eid_epoch);
        !           178:        writer->write_uint32(writer, last_eid);
        !           179: 
        !           180:        enumerator = this->inventory->create_enumerator(this->inventory);
        !           181:        while (enumerator->enumerate(enumerator, &sw_record))
        !           182:        {
        !           183:                ietf_swima_attr_sw_ev_build_sw_record(writer, 0x00, sw_record,
        !           184:                                                        this->type.type == IETF_ATTR_SW_INVENTORY);
        !           185:        }
        !           186:        enumerator->destroy(enumerator);
        !           187: 
        !           188:        this->value = writer->extract_buf(writer);
        !           189:        this->segment = this->value;
        !           190:        this->length = this->value.len;
        !           191:        writer->destroy(writer);
        !           192: }
        !           193: 
        !           194: /**
        !           195:  * This function is shared with ietf_swima_attr_sw_ev.c
        !           196:  **/
        !           197: extern bool ietf_swima_attr_sw_ev_process_sw_record(bio_reader_t *reader,
        !           198:                        uint8_t *action, swima_record_t **sw_record, bool has_record);
        !           199: 
        !           200: METHOD(pa_tnc_attr_t, process, status_t,
        !           201:        private_ietf_swima_attr_sw_inv_t *this, uint32_t *offset)
        !           202: {
        !           203:        bio_reader_t *reader;
        !           204:        uint32_t last_eid, eid_epoch;
        !           205:        swima_record_t *sw_record;
        !           206:        status_t status = NEED_MORE;
        !           207: 
        !           208:        if (this->offset == 0)
        !           209:        {
        !           210:                if (this->length < IETF_SWIMA_SW_INV_MIN_SIZE)
        !           211:                {
        !           212:                        DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_IETF,
        !           213:                                                   ietf_attr_names, this->type.type);
        !           214:                        *offset = this->offset;
        !           215:                        return FAILED;
        !           216:                }
        !           217:                if (this->value.len < IETF_SWIMA_SW_INV_MIN_SIZE)
        !           218:                {
        !           219:                        return NEED_MORE;
        !           220:                }
        !           221:                reader = bio_reader_create(this->value);
        !           222:                reader->read_uint8 (reader, &this->flags);
        !           223:                reader->read_uint24(reader, &this->record_count);
        !           224:                reader->read_uint32(reader, &this->request_id);
        !           225:                reader->read_uint32(reader, &eid_epoch);
        !           226:                reader->read_uint32(reader, &last_eid);
        !           227:                this->offset = IETF_SWIMA_SW_INV_MIN_SIZE;
        !           228:                this->value = reader->peek(reader);
        !           229:                this->inventory->set_eid(this->inventory, last_eid, eid_epoch);
        !           230:                reader->destroy(reader);
        !           231:        }
        !           232: 
        !           233:        reader = bio_reader_create(this->value);
        !           234: 
        !           235:        while (this->record_count)
        !           236:        {
        !           237:                if (!ietf_swima_attr_sw_ev_process_sw_record(reader, NULL, &sw_record,
        !           238:                                                                this->type.type == IETF_ATTR_SW_INVENTORY))
        !           239:                {
        !           240:                        goto end;
        !           241:                }
        !           242: 
        !           243:                this->inventory->add(this->inventory, sw_record);
        !           244:                this->offset += this->value.len - reader->remaining(reader);
        !           245:                this->value = reader->peek(reader);
        !           246: 
        !           247:                /* at least one software inventory evidence record was processed */
        !           248:                status = SUCCESS;
        !           249:                this->record_count--;
        !           250:        }
        !           251: 
        !           252:        if (this->length == this->offset)
        !           253:        {
        !           254:                status = SUCCESS;
        !           255:        }
        !           256:        else
        !           257:        {
        !           258:                DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_IETF,
        !           259:                                           ietf_attr_names, this->type.type);
        !           260:                *offset = this->offset;
        !           261:                status = FAILED;
        !           262:        }
        !           263: 
        !           264: end:
        !           265:        reader->destroy(reader);
        !           266:        return status;
        !           267: }
        !           268: 
        !           269: METHOD(pa_tnc_attr_t, add_segment, void,
        !           270:        private_ietf_swima_attr_sw_inv_t *this, chunk_t segment)
        !           271: {
        !           272:        this->value = chunk_cat("cc", this->value, segment);
        !           273:        chunk_free(&this->segment);
        !           274:        this->segment = this->value;
        !           275: }
        !           276: 
        !           277: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
        !           278:        private_ietf_swima_attr_sw_inv_t *this)
        !           279: {
        !           280:        ref_get(&this->ref);
        !           281:        return &this->public.pa_tnc_attribute;
        !           282: }
        !           283: 
        !           284: METHOD(pa_tnc_attr_t, destroy, void,
        !           285:        private_ietf_swima_attr_sw_inv_t *this)
        !           286: {
        !           287:        if (ref_put(&this->ref))
        !           288:        {
        !           289:                this->inventory->destroy(this->inventory);
        !           290:                free(this->segment.ptr);
        !           291:                free(this);
        !           292:        }
        !           293: }
        !           294: 
        !           295: METHOD(ietf_swima_attr_sw_inv_t, get_flags, uint8_t,
        !           296:        private_ietf_swima_attr_sw_inv_t *this)
        !           297: {
        !           298:        return this->flags;
        !           299: }
        !           300: 
        !           301: METHOD(ietf_swima_attr_sw_inv_t, get_request_id, uint32_t,
        !           302:        private_ietf_swima_attr_sw_inv_t *this)
        !           303: {
        !           304:        return this->request_id;
        !           305: }
        !           306: 
        !           307: METHOD(ietf_swima_attr_sw_inv_t, get_record_count, uint32_t,
        !           308:        private_ietf_swima_attr_sw_inv_t *this)
        !           309: {
        !           310:        return this->record_count;
        !           311: }
        !           312: 
        !           313: METHOD(ietf_swima_attr_sw_inv_t, set_inventory, void,
        !           314:        private_ietf_swima_attr_sw_inv_t *this, swima_inventory_t *inventory)
        !           315: {
        !           316:        this->inventory->destroy(this->inventory);
        !           317:        this->inventory = inventory->get_ref(inventory);
        !           318: }
        !           319: 
        !           320: METHOD(ietf_swima_attr_sw_inv_t, get_inventory, swima_inventory_t*,
        !           321:        private_ietf_swima_attr_sw_inv_t *this)
        !           322: {
        !           323:        return this->inventory;
        !           324: }
        !           325: 
        !           326: METHOD(ietf_swima_attr_sw_inv_t, clear_inventory, void,
        !           327:        private_ietf_swima_attr_sw_inv_t *this)
        !           328: {
        !           329:        this->inventory->clear(this->inventory);
        !           330: }
        !           331: 
        !           332: /**
        !           333:  * Described in header.
        !           334:  */
        !           335: pa_tnc_attr_t *ietf_swima_attr_sw_inv_create(uint8_t flags, uint32_t request_id,
        !           336:                                                                                         bool sw_id_only)
        !           337: {
        !           338:        private_ietf_swima_attr_sw_inv_t *this;
        !           339:        ietf_attr_t type;
        !           340: 
        !           341:        type = sw_id_only ? IETF_ATTR_SW_ID_INVENTORY : IETF_ATTR_SW_INVENTORY;
        !           342: 
        !           343:        INIT(this,
        !           344:                .public = {
        !           345:                        .pa_tnc_attribute = {
        !           346:                                .get_type = _get_type,
        !           347:                                .get_value = _get_value,
        !           348:                                .get_noskip_flag = _get_noskip_flag,
        !           349:                                .set_noskip_flag = _set_noskip_flag,
        !           350:                                .build = _build,
        !           351:                                .process = _process,
        !           352:                                .add_segment = _add_segment,
        !           353:                                .get_ref = _get_ref,
        !           354:                                .destroy = _destroy,
        !           355:                        },
        !           356:                        .get_flags = _get_flags,
        !           357:                        .get_request_id = _get_request_id,
        !           358:                        .get_record_count = _get_record_count,
        !           359:                        .set_inventory = _set_inventory,
        !           360:                        .get_inventory = _get_inventory,
        !           361:                        .clear_inventory = _clear_inventory,
        !           362:                },
        !           363:                .type = { PEN_IETF, type },
        !           364:                .flags = flags,
        !           365:                .request_id = request_id,
        !           366:                .inventory = swima_inventory_create(),
        !           367:                .ref = 1,
        !           368:        );
        !           369: 
        !           370:        return &this->public.pa_tnc_attribute;
        !           371: }
        !           372: 
        !           373: 
        !           374: /**
        !           375:  * Described in header.
        !           376:  */
        !           377: pa_tnc_attr_t *ietf_swima_attr_sw_inv_create_from_data(size_t length,
        !           378:                                                                                chunk_t data, bool sw_id_only)
        !           379: {
        !           380:        private_ietf_swima_attr_sw_inv_t *this;
        !           381:        ietf_attr_t type;
        !           382: 
        !           383:        type = sw_id_only ? IETF_ATTR_SW_ID_INVENTORY : IETF_ATTR_SW_INVENTORY;
        !           384: 
        !           385:        INIT(this,
        !           386:                .public = {
        !           387:                        .pa_tnc_attribute = {
        !           388:                                .get_type = _get_type,
        !           389:                                .get_value = _get_value,
        !           390:                                .get_noskip_flag = _get_noskip_flag,
        !           391:                                .set_noskip_flag = _set_noskip_flag,
        !           392:                                .build = _build,
        !           393:                                .process = _process,
        !           394:                                .add_segment = _add_segment,
        !           395:                                .get_ref = _get_ref,
        !           396:                                .destroy = _destroy,
        !           397:                        },
        !           398:                        .get_flags = _get_flags,
        !           399:                        .get_request_id = _get_request_id,
        !           400:                        .get_record_count = _get_record_count,
        !           401:                        .set_inventory = _set_inventory,
        !           402:                        .get_inventory = _get_inventory,
        !           403:                        .clear_inventory = _clear_inventory,
        !           404:                },
        !           405:                .type = { PEN_IETF, type },
        !           406:                .length = length,
        !           407:                .segment = chunk_clone(data),
        !           408:                .inventory = swima_inventory_create(),
        !           409:                .ref = 1,
        !           410:        );
        !           411: 
        !           412:        /* received either complete attribute value or first segment */
        !           413:        this->value = this->segment;
        !           414: 
        !           415:        return &this->public.pa_tnc_attribute;
        !           416: }

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