Return to ietf_swima_attr_sw_inv.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libimcv / ietf / swima |
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: }