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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2014 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_installed_packages.h"
                     17: 
                     18: #include <string.h>
                     19: 
                     20: #include <pa_tnc/pa_tnc_msg.h>
                     21: #include <bio/bio_writer.h>
                     22: #include <bio/bio_reader.h>
                     23: #include <collections/linked_list.h>
                     24: #include <utils/debug.h>
                     25: 
                     26: 
                     27: typedef struct private_ietf_attr_installed_packages_t private_ietf_attr_installed_packages_t;
                     28: typedef struct package_entry_t package_entry_t;
                     29: 
                     30: /**
                     31:  * PA-TNC Installed Packages Type  (see section 4.2.7 of RFC 5792)
                     32:  *
                     33:  *                       1                   2                   3
                     34:  *   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
                     35:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     36:  *  |          Reserved             |         Package Count         |
                     37:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     38:  *  | Pkg Name Len  |        Package Name (Variable Length)         |
                     39:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     40:  *  |  Version Len  |    Package Version Number (Variable Length)   |
                     41:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     42:  */
                     43: 
                     44: /**
                     45:  * Private data of an ietf_attr_installed_packages_t object.
                     46:  */
                     47: struct private_ietf_attr_installed_packages_t {
                     48: 
                     49:        /**
                     50:         * Public members of ietf_attr_installed_packages_t
                     51:         */
                     52:        ietf_attr_installed_packages_t public;
                     53: 
                     54:        /**
                     55:         * Vendor-specific attribute type
                     56:         */
                     57:        pen_type_t type;
                     58: 
                     59:        /**
                     60:         * Length of attribute value
                     61:         */
                     62:        size_t length;
                     63: 
                     64:        /**
                     65:         * Offset up to which attribute value has been processed
                     66:         */
                     67:        size_t offset;
                     68: 
                     69:        /**
                     70:         * Current position of attribute value pointer
                     71:         */
                     72:        chunk_t value;
                     73: 
                     74:        /**
                     75:         * Contains complete attribute or current segment
                     76:         */
                     77:        chunk_t segment;
                     78: 
                     79:        /**
                     80:         * Noskip flag
                     81:         */
                     82:        bool noskip_flag;
                     83: 
                     84:        /**
                     85:         * Number of Installed Packages in attribute
                     86:         */
                     87:        uint16_t count;
                     88: 
                     89:        /**
                     90:         * List of Installed Package entries
                     91:         */
                     92:        linked_list_t *packages;
                     93: 
                     94:        /**
                     95:         * Reference count
                     96:         */
                     97:        refcount_t ref;
                     98: };
                     99: 
                    100: /**
                    101:  * Package entry
                    102:  */
                    103: struct package_entry_t {
                    104:        chunk_t name;
                    105:        chunk_t version;
                    106: };
                    107: 
                    108: /**
                    109:  * Free a package entry
                    110:  */
                    111: static void free_package_entry(package_entry_t *entry)
                    112: {
                    113:        free(entry->name.ptr);
                    114:        free(entry->version.ptr);
                    115:        free(entry);
                    116: }
                    117: 
                    118: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
                    119:        private_ietf_attr_installed_packages_t *this)
                    120: {
                    121:        return this->type;
                    122: }
                    123: 
                    124: METHOD(pa_tnc_attr_t, get_value, chunk_t,
                    125:        private_ietf_attr_installed_packages_t *this)
                    126: {
                    127:        return this->value;
                    128: }
                    129: 
                    130: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
                    131:        private_ietf_attr_installed_packages_t *this)
                    132: {
                    133:        return this->noskip_flag;
                    134: }
                    135: 
                    136: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
                    137:        private_ietf_attr_installed_packages_t *this, bool noskip)
                    138: {
                    139:        this->noskip_flag = noskip;
                    140: }
                    141: 
                    142: METHOD(pa_tnc_attr_t, build, void,
                    143:        private_ietf_attr_installed_packages_t *this)
                    144: {
                    145:        bio_writer_t *writer;
                    146:        enumerator_t *enumerator;
                    147:        package_entry_t *entry;
                    148: 
                    149:        if (this->value.ptr)
                    150:        {
                    151:                return;
                    152:        }
                    153:        writer = bio_writer_create(IETF_INSTALLED_PACKAGES_MIN_SIZE);
                    154:        writer->write_uint16(writer, 0x0000);
                    155:        writer->write_uint16(writer, this->packages->get_count(this->packages));
                    156: 
                    157:        enumerator = this->packages->create_enumerator(this->packages);
                    158:        while (enumerator->enumerate(enumerator, &entry))
                    159:        {
                    160:                writer->write_data8(writer, entry->name);
                    161:                writer->write_data8(writer, entry->version);
                    162:        }
                    163:        enumerator->destroy(enumerator);
                    164: 
                    165:        this->value = writer->extract_buf(writer);
                    166:        this->segment = this->value;
                    167:        this->length = this->value.len;
                    168:        writer->destroy(writer);
                    169: }
                    170: 
                    171: METHOD(pa_tnc_attr_t, process, status_t,
                    172:        private_ietf_attr_installed_packages_t *this, uint32_t *offset)
                    173: {
                    174:        bio_reader_t *reader;
                    175:        package_entry_t *entry;
                    176:        status_t status = NEED_MORE;
                    177:        chunk_t name, version;
                    178:        uint16_t reserved;
                    179:        u_char *pos;
                    180: 
                    181:        if (this->offset == 0)
                    182:        {
                    183:                if (this->length < IETF_INSTALLED_PACKAGES_MIN_SIZE)
                    184:                {
                    185:                        DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_IETF,
                    186:                                                   ietf_attr_names, this->type.type);
                    187:                        *offset = this->offset;
                    188:                        return FAILED;
                    189:                }
                    190:                if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE)
                    191:                {
                    192:                        return NEED_MORE;
                    193:                }
                    194:                reader = bio_reader_create(this->value);
                    195:                reader->read_uint16(reader, &reserved);
                    196:                reader->read_uint16(reader, &this->count);
                    197:                this->offset = IETF_INSTALLED_PACKAGES_MIN_SIZE;
                    198:                this->value = reader->peek(reader);
                    199:                reader->destroy(reader);
                    200:        }
                    201: 
                    202:        reader = bio_reader_create(this->value);
                    203: 
                    204:        while (this->count)
                    205:        {
                    206:                if (!reader->read_data8(reader, &name) ||
                    207:                        !reader->read_data8(reader, &version))
                    208:                {
                    209:                        goto end;
                    210:                }
                    211:                pos = memchr(name.ptr, '\0', name.len);
                    212:                if (pos)
                    213:                {
                    214:                        DBG1(DBG_TNC, "nul termination in IETF installed package name");
                    215:                        *offset = this->offset + 1 + (pos - name.ptr);
                    216:                        status = FAILED;
                    217:                        goto end;
                    218:                }
                    219:                pos = memchr(version.ptr, '\0', version.len);
                    220:                if (pos)
                    221:                {
                    222:                        DBG1(DBG_TNC, "nul termination in IETF installed package version");
                    223:                        *offset = this->offset + 1 + name.len + 1 + (pos - version.ptr);
                    224:                        status = FAILED;
                    225:                        goto end;
                    226:                }
                    227:                this->offset += this->value.len - reader->remaining(reader);
                    228:                this->value = reader->peek(reader);
                    229: 
                    230:                entry = malloc_thing(package_entry_t);
                    231:                entry->name = chunk_clone(name);
                    232:                entry->version = chunk_clone(version);
                    233:                this->packages->insert_last(this->packages, entry);
                    234: 
                    235:                /* at least one tag ID was processed */
                    236:                status = SUCCESS;
                    237:                this->count--;
                    238:        }
                    239: 
                    240:        if (this->length != this->offset)
                    241:        {
                    242:                DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_IETF,
                    243:                                           ietf_attr_names, this->type.type);
                    244:                *offset = this->offset;
                    245:                status = FAILED;
                    246:        }
                    247: 
                    248: end:
                    249:        reader->destroy(reader);
                    250:        return status;
                    251: }
                    252: 
                    253: METHOD(pa_tnc_attr_t, add_segment, void,
                    254:        private_ietf_attr_installed_packages_t *this, chunk_t segment)
                    255: {
                    256:        this->value = chunk_cat("cc", this->value, segment);
                    257:        chunk_free(&this->segment);
                    258:        this->segment = this->value;
                    259: }
                    260: 
                    261: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
                    262:        private_ietf_attr_installed_packages_t *this)
                    263: {
                    264:        ref_get(&this->ref);
                    265:        return &this->public.pa_tnc_attribute;
                    266: }
                    267: 
                    268: METHOD(pa_tnc_attr_t, destroy, void,
                    269:        private_ietf_attr_installed_packages_t *this)
                    270: {
                    271:        if (ref_put(&this->ref))
                    272:        {
                    273:                this->packages->destroy_function(this->packages, (void*)free_package_entry);
                    274:                free(this->segment.ptr);
                    275:                free(this);
                    276:        }
                    277: }
                    278: 
                    279: METHOD(ietf_attr_installed_packages_t, add, void,
                    280:        private_ietf_attr_installed_packages_t *this, chunk_t name, chunk_t version)
                    281: {
                    282:        package_entry_t *entry;
                    283: 
                    284:        /* restrict package name and package version number fields to 255 octets */
                    285:        name.len = min(255, name.len);
                    286:        version.len = min(255, version.len);
                    287: 
                    288:        entry = malloc_thing(package_entry_t);
                    289:        entry->name = chunk_clone(name);
                    290:        entry->version = chunk_clone(version);
                    291:        this->packages->insert_last(this->packages, entry);
                    292: }
                    293: 
                    294: CALLBACK(package_filter, bool,
                    295:        void *null, enumerator_t *orig, va_list args)
                    296: {
                    297:        package_entry_t *entry;
                    298:        chunk_t *name, *version;
                    299: 
                    300:        VA_ARGS_VGET(args, name, version);
                    301: 
                    302:        if (orig->enumerate(orig, &entry))
                    303:        {
                    304:                *name = entry->name;
                    305:                *version = entry->version;
                    306:                return TRUE;
                    307:        }
                    308:        return FALSE;
                    309: }
                    310: 
                    311: METHOD(ietf_attr_installed_packages_t, create_enumerator, enumerator_t*,
                    312:        private_ietf_attr_installed_packages_t *this)
                    313: {
                    314:        return enumerator_create_filter(
                    315:                                                this->packages->create_enumerator(this->packages),
                    316:                                                package_filter, NULL, NULL);
                    317: }
                    318: 
                    319: METHOD(ietf_attr_installed_packages_t, get_count, uint16_t,
                    320:        private_ietf_attr_installed_packages_t *this)
                    321: {
                    322:        return this->count;
                    323: }
                    324: 
                    325: METHOD(ietf_attr_installed_packages_t, clear_packages, void,
                    326:        private_ietf_attr_installed_packages_t *this)
                    327: {
                    328:        package_entry_t *entry;
                    329: 
                    330:        while (this->packages->remove_first(this->packages,(void**)&entry) == SUCCESS)
                    331:        {
                    332:                free_package_entry(entry);
                    333:        }
                    334: }
                    335: 
                    336: /**
                    337:  * Described in header.
                    338:  */
                    339: pa_tnc_attr_t *ietf_attr_installed_packages_create(void)
                    340: {
                    341:        private_ietf_attr_installed_packages_t *this;
                    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:                        .add = _add,
                    357:                        .create_enumerator = _create_enumerator,
                    358:                        .get_count = _get_count,
                    359:                        .clear_packages = _clear_packages,
                    360:                },
                    361:                .type = { PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
                    362:                .packages = linked_list_create(),
                    363:                .ref = 1,
                    364:        );
                    365: 
                    366:        return &this->public.pa_tnc_attribute;
                    367: }
                    368: 
                    369: /**
                    370:  * Described in header.                .length = length,
                    371: 
                    372:  */
                    373: pa_tnc_attr_t *ietf_attr_installed_packages_create_from_data(size_t length,
                    374:                                                                                                                         chunk_t data)
                    375: {
                    376:        private_ietf_attr_installed_packages_t *this;
                    377: 
                    378:        INIT(this,
                    379:                .public = {
                    380:                        .pa_tnc_attribute = {
                    381:                                .get_type = _get_type,
                    382:                                .get_value = _get_value,
                    383:                                .get_noskip_flag = _get_noskip_flag,
                    384:                                .set_noskip_flag = _set_noskip_flag,
                    385:                                .build = _build,
                    386:                                .process = _process,
                    387:                                .add_segment = _add_segment,
                    388:                                .get_ref = _get_ref,
                    389:                                .destroy = _destroy,
                    390:                        },
                    391:                        .add = _add,
                    392:                        .create_enumerator = _create_enumerator,
                    393:                        .get_count = _get_count,
                    394:                        .clear_packages = _clear_packages,
                    395:                },
                    396:                .type = {PEN_IETF, IETF_ATTR_INSTALLED_PACKAGES },
                    397:                .length = length,
                    398:                .segment = chunk_clone(data),
                    399:                .packages = linked_list_create(),
                    400:                .ref = 1,
                    401:        );
                    402: 
                    403:        /* received either complete attribute value or first segment */
                    404:        this->value = this->segment;
                    405: 
                    406:        return &this->public.pa_tnc_attribute;
                    407: }
                    408: 
                    409: 

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