Annotation of embedaddon/strongswan/src/libimcv/pa_tnc/pa_tnc_attr_manager.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2011-2014 Andreas Steffen
3: *
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "pa_tnc_attr_manager.h"
18:
19: #include "imcv.h"
20: #include "pa_tnc_attr.h"
21: #include "ietf/ietf_attr_pa_tnc_error.h"
22:
23: #include <collections/linked_list.h>
24: #include <utils/debug.h>
25:
26: typedef struct private_pa_tnc_attr_manager_t private_pa_tnc_attr_manager_t;
27: typedef struct entry_t entry_t;
28:
29: struct entry_t {
30: pen_t vendor_id;
31: enum_name_t *attr_names;
32: pa_tnc_attr_create_t attr_create;
33: };
34:
35: /**
36: * Private data of a pa_tnc_attr_manager_t object.
37: *
38: */
39: struct private_pa_tnc_attr_manager_t {
40:
41: /**
42: * Public pa_tnc_attr_manager_t interface.
43: */
44: pa_tnc_attr_manager_t public;
45:
46: /**
47: * List of PA-TNC vendor attributes
48: */
49: linked_list_t *list;
50: };
51:
52: METHOD(pa_tnc_attr_manager_t, add_vendor, void,
53: private_pa_tnc_attr_manager_t *this, pen_t vendor_id,
54: pa_tnc_attr_create_t attr_create, enum_name_t *attr_names)
55: {
56: entry_t *entry;
57:
58: entry = malloc_thing(entry_t);
59: entry->vendor_id = vendor_id;
60: entry->attr_create = attr_create;
61: entry->attr_names = attr_names;
62:
63: this->list->insert_last(this->list, entry);
64: DBG2(DBG_TNC, "added %N attributes", pen_names, vendor_id);
65: }
66:
67: METHOD(pa_tnc_attr_manager_t, remove_vendor, void,
68: private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
69: {
70: enumerator_t *enumerator;
71: entry_t *entry;
72:
73: enumerator = this->list->create_enumerator(this->list);
74: while (enumerator->enumerate(enumerator, &entry))
75: {
76: if (entry->vendor_id == vendor_id)
77: {
78: this->list->remove_at(this->list, enumerator);
79: free(entry);
80: DBG2(DBG_TNC, "removed %N attributes", pen_names, vendor_id);
81: }
82: }
83: enumerator->destroy(enumerator);
84: }
85:
86: METHOD(pa_tnc_attr_manager_t, get_names, enum_name_t*,
87: private_pa_tnc_attr_manager_t *this, pen_t vendor_id)
88: {
89: enumerator_t *enumerator;
90: entry_t *entry;
91: enum_name_t *attr_names = NULL;
92:
93: enumerator = this->list->create_enumerator(this->list);
94: while (enumerator->enumerate(enumerator, &entry))
95: {
96: if (entry->vendor_id == vendor_id)
97: {
98: attr_names = entry->attr_names;
99: break;
100: }
101: }
102: enumerator->destroy(enumerator);
103:
104: return attr_names;
105: }
106:
107: /**
108: * PA-TNC attribute
109: *
110: * 1 2 3
111: * 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
112: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113: * | Flags | PA-TNC Attribute Vendor ID |
114: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115: * | PA-TNC Attribute Type |
116: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117: * | PA-TNC Attribute Length |
118: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119: * | Attribute Value (Variable Length) |
120: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121: */
122:
123: METHOD(pa_tnc_attr_manager_t, create, pa_tnc_attr_t*,
124: private_pa_tnc_attr_manager_t *this, bio_reader_t *reader, bool segmented,
125: uint32_t *offset, chunk_t msg_info, pa_tnc_attr_t **error)
126: {
127: uint8_t flags;
128: uint32_t type, length, value_len;
129: chunk_t value;
130: ietf_attr_pa_tnc_error_t *error_attr;
131: pen_t vendor_id;
132: pen_type_t unsupported_type;
133: pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
134: enum_name_t *pa_attr_names;
135: pa_tnc_attr_t *attr = NULL;
136: enumerator_t *enumerator;
137: entry_t *entry;
138:
139: /* properly initialize error return argument in case of no error */
140: *error = NULL;
141:
142: if (reader->remaining(reader) < PA_TNC_ATTR_HEADER_SIZE)
143: {
144: DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute header");
145: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
146: msg_info, *offset);
147: return NULL;
148: }
149: reader->read_uint8 (reader, &flags);
150: reader->read_uint24(reader, &vendor_id);
151: reader->read_uint32(reader, &type);
152: reader->read_uint32(reader, &length);
153:
154: pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
155: vendor_id);
156: if (pa_attr_names)
157: {
158: DBG2(DBG_TNC, "processing PA-TNC attribute type '%N/%N' "
159: "0x%06x/0x%08x", pen_names, vendor_id,
160: pa_attr_names, type, vendor_id, type);
161: }
162: else
163: {
164: DBG2(DBG_TNC, "processing PA-TNC attribute type '%N' "
165: "0x%06x/0x%08x", pen_names, vendor_id,
166: vendor_id, type);
167: }
168:
169: if (length < PA_TNC_ATTR_HEADER_SIZE)
170: {
171: DBG1(DBG_TNC, "%u bytes too small for PA-TNC attribute length",
172: length);
173: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
174: msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
175: return NULL;
176: }
177: length -= PA_TNC_ATTR_HEADER_SIZE;
178: value_len = segmented ? reader->remaining(reader) : length;
179:
180: if (!reader->read_data(reader, value_len, &value))
181: {
182: DBG1(DBG_TNC, "insufficient bytes for PA-TNC attribute value");
183: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
184: msg_info, *offset + PA_TNC_ATTR_INFO_SIZE);
185: return NULL;
186: }
187: DBG3(DBG_TNC, "%B", &value);
188:
189: if (vendor_id == PEN_RESERVED)
190: {
191: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
192: msg_info, *offset + 1);
193: return NULL;
194: }
195: if (type == IETF_ATTR_RESERVED)
196: {
197: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
198: msg_info, *offset + 4);
199: return NULL;
200: }
201:
202: /* check if the attribute type is registered */
203: enumerator = this->list->create_enumerator(this->list);
204: while (enumerator->enumerate(enumerator, &entry))
205: {
206: if (entry->vendor_id == vendor_id)
207: {
208: if (entry->attr_create)
209: {
210: attr = entry->attr_create(type, length, value);
211: }
212: break;
213: }
214: }
215: enumerator->destroy(enumerator);
216:
217: if (!attr)
218: {
219: if (!(flags & PA_TNC_ATTR_FLAG_NOSKIP))
220: {
221: DBG1(DBG_TNC, "skipping unsupported PA-TNC attribute");
222: (*offset) += PA_TNC_ATTR_HEADER_SIZE + length;
223: return NULL;
224: }
225:
226: DBG1(DBG_TNC, "unsupported PA-TNC attribute with NOSKIP flag");
227: unsupported_type = pen_type_create(vendor_id, type);
228: error_code = pen_type_create(PEN_IETF, PA_ERROR_ATTR_TYPE_NOT_SUPPORTED);
229: *error = ietf_attr_pa_tnc_error_create(error_code, msg_info);
230: error_attr = (ietf_attr_pa_tnc_error_t*)(*error);
231: error_attr->set_unsupported_attr(error_attr, flags, unsupported_type);
232: return NULL;
233: }
234: (*offset) += PA_TNC_ATTR_HEADER_SIZE;
235:
236: return attr;
237: }
238:
239: METHOD(pa_tnc_attr_manager_t, construct, pa_tnc_attr_t*,
240: private_pa_tnc_attr_manager_t *this, pen_t vendor_id, uint32_t type,
241: chunk_t value)
242: {
243: enum_name_t *pa_attr_names;
244: pa_tnc_attr_t *attr = NULL;
245: enumerator_t *enumerator;
246: entry_t *entry;
247:
248: pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
249: vendor_id);
250: if (pa_attr_names)
251: {
252: DBG2(DBG_TNC, "generating PA-TNC attribute type '%N/%N' "
253: "0x%06x/0x%08x", pen_names, vendor_id,
254: pa_attr_names, type, vendor_id, type);
255: }
256: else
257: {
258: DBG2(DBG_TNC, "generating PA-TNC attribute type '%N' "
259: "0x%06x/0x%08x", pen_names, vendor_id,
260: vendor_id, type);
261: }
262: enumerator = this->list->create_enumerator(this->list);
263: while (enumerator->enumerate(enumerator, &entry))
264: {
265: if (entry->vendor_id == vendor_id)
266: {
267: if (entry->attr_create)
268: {
269: attr = entry->attr_create(type, value.len, value);
270: }
271: break;
272: }
273: }
274: enumerator->destroy(enumerator);
275: return attr;
276: }
277:
278: METHOD(pa_tnc_attr_manager_t, destroy, void,
279: private_pa_tnc_attr_manager_t *this)
280: {
281: this->list->destroy_function(this->list, free);
282: free(this);
283: }
284:
285: /**
286: * See header
287: */
288: pa_tnc_attr_manager_t *pa_tnc_attr_manager_create(void)
289: {
290: private_pa_tnc_attr_manager_t *this;
291:
292: INIT(this,
293: .public = {
294: .add_vendor = _add_vendor,
295: .remove_vendor = _remove_vendor,
296: .get_names = _get_names,
297: .create = _create,
298: .construct = _construct,
299: .destroy = _destroy,
300: },
301: .list = linked_list_create(),
302: );
303:
304: return &this->public;
305: }
306:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>