Annotation of embedaddon/strongswan/src/libimcv/ietf/swima/ietf_swima_attr_sw_inv.c, revision 1.1.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>