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>