Annotation of embedaddon/strongswan/src/libimcv/ietf/ietf_attr_pa_tnc_error.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2011-2018 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_pa_tnc_error.h"
17:
18: #include <pa_tnc/pa_tnc_msg.h>
19: #include <bio/bio_writer.h>
20: #include <bio/bio_reader.h>
21: #include <utils/debug.h>
22:
23: ENUM(pa_tnc_error_code_names, PA_ERROR_RESERVED,
24: PA_ERROR_SWIMA_SUBSCRIPTION_ID_REUSE,
25: "Reserved",
26: "Invalid Parameter",
27: "Version Not Supported",
28: "Attribute Type Not Supported",
29: "SWIMA Error",
30: "SWIMA Subscription Denied",
31: "SWIMA Response Too Large",
32: "SWIMA Subscription Fulfillment Error",
33: "SWIMA Subscription ID Reuse"
34: );
35:
36: typedef struct private_ietf_attr_pa_tnc_error_t private_ietf_attr_pa_tnc_error_t;
37:
38: /**
39: * PA-TNC Error Attribute Type (see section 4.2.8 of RFC 5792)
40: *
41: * 1 2 3
42: * 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
43: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44: * | Reserved | PA-TNC Error Code Vendor ID |
45: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46: * | PA-TNC Error Code |
47: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48: * | Error Information (Variable Length) |
49: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50: */
51:
52: #define PA_ERROR_HEADER_SIZE 8
53: #define PA_ERROR_RESERVED 0x00
54:
55: /**
56: * All IETF Error Types return the first 8 bytes of the erroneous PA-TNC message
57: *
58: * 1 2 3
59: * 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
60: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61: * | Version | Copy of Reserved |
62: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63: * | Message Identifier |
64: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65: */
66:
67: #define PA_ERROR_MSG_INFO_SIZE 8
68: #define PA_ERROR_MSG_INFO_MAX_SIZE 1024
69:
70: /**
71: * "Invalid Parameter" Error Code
72: * 1 2 3
73: * 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
74: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75: * | Offset |
76: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77: */
78:
79: /**
80: * "Version Not Supported" Error Code
81: *
82: * 1 2 3
83: * 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
84: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85: * | Max Version | Min Version | Reserved |
86: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87: */
88:
89: #define PA_ERROR_VERSION_RESERVED 0x0000
90:
91: /**
92: * "Attribute Type Not Supported" Error Code
93: *
94: * 1 2 3
95: * 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
96: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97: * | Flags | PA-TNC Attribute Vendor ID |
98: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99: * | PA-TNC Attribute Type |
100: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101: */
102:
103: #define PA_ERROR_ATTR_INFO_SIZE 8
104:
105: /**
106: * Private data of an ietf_attr_pa_tnc_error_t object.
107: */
108: struct private_ietf_attr_pa_tnc_error_t {
109:
110: /**
111: * Public members of ietf_attr_pa_tnc_error_t
112: */
113: ietf_attr_pa_tnc_error_t public;
114:
115: /**
116: * Vendor-specific attribute type
117: */
118: pen_type_t type;
119:
120: /**
121: * Length of attribute value
122: */
123: size_t length;
124:
125: /**
126: * Attribute value or segment
127: */
128: chunk_t value;
129:
130: /**
131: * Noskip flag
132: */
133: bool noskip_flag;
134:
135: /**
136: * Vendor-specific error code
137: */
138: pen_type_t error_code;
139:
140: /**
141: * First 8 bytes of erroneous PA-TNC message
142: */
143: chunk_t msg_info;
144:
145: /**
146: * Flags of unsupported PA-TNC attribute
147: */
148: uint8_t flags;
149:
150: /**
151: * Vendor ID and type of unsupported PA-TNC attribute
152: */
153: pen_type_t unsupported_type;
154:
155: /**
156: * PA-TNC error offset
157: */
158: uint32_t error_offset;
159:
160: /**
161: * Reference count
162: */
163: refcount_t ref;
164: };
165:
166: METHOD(pa_tnc_attr_t, get_type, pen_type_t,
167: private_ietf_attr_pa_tnc_error_t *this)
168: {
169: return this->type;
170: }
171:
172: METHOD(pa_tnc_attr_t, get_value, chunk_t,
173: private_ietf_attr_pa_tnc_error_t *this)
174: {
175: return this->value;
176: }
177:
178: METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
179: private_ietf_attr_pa_tnc_error_t *this)
180: {
181: return this->noskip_flag;
182: }
183:
184: METHOD(pa_tnc_attr_t, set_noskip_flag,void,
185: private_ietf_attr_pa_tnc_error_t *this, bool noskip)
186: {
187: this->noskip_flag = noskip;
188: }
189:
190: METHOD(pa_tnc_attr_t, build, void,
191: private_ietf_attr_pa_tnc_error_t *this)
192: {
193: bio_writer_t *writer;
194:
195: if (this->value.ptr)
196: {
197: return;
198: }
199: writer = bio_writer_create(PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE);
200: writer->write_uint8 (writer, PA_ERROR_RESERVED);
201: writer->write_uint24(writer, this->error_code.vendor_id);
202: writer->write_uint32(writer, this->error_code.type);
203: writer->write_data (writer, this->msg_info);
204:
205: if (this->error_code.vendor_id == PEN_IETF)
206: {
207: switch (this->error_code.type)
208: {
209: case PA_ERROR_INVALID_PARAMETER:
210: writer->write_uint32(writer, this->error_offset);
211: break;
212: case PA_ERROR_VERSION_NOT_SUPPORTED:
213: writer->write_uint8 (writer, PA_TNC_VERSION);
214: writer->write_uint8 (writer, PA_TNC_VERSION);
215: writer->write_uint16(writer, PA_ERROR_VERSION_RESERVED);
216: break;
217: case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
218: writer->write_uint8 (writer, this->flags);
219: writer->write_uint24(writer, this->unsupported_type.vendor_id);
220: writer->write_uint32(writer, this->unsupported_type.type);
221: break;
222: default:
223: break;
224: }
225: }
226: this->value = writer->extract_buf(writer);
227: this->length = this->value.len;
228: writer->destroy(writer);
229: }
230:
231: METHOD(pa_tnc_attr_t, process, status_t,
232: private_ietf_attr_pa_tnc_error_t *this, uint32_t *offset)
233: {
234: bio_reader_t *reader;
235: uint8_t reserved;
236: uint32_t vendor_id, type;
237:
238: *offset = 0;
239:
240: if (this->value.len < this->length)
241: {
242: return NEED_MORE;
243: }
244: if (this->value.len < PA_ERROR_HEADER_SIZE)
245: {
246: DBG1(DBG_TNC, "insufficient data for PA-TNC error header");
247: return FAILED;
248: }
249: reader = bio_reader_create(this->value);
250: reader->read_uint8 (reader, &reserved);
251: reader->read_uint24(reader, &this->error_code.vendor_id);
252: reader->read_uint32(reader, &this->error_code.type);
253:
254: if (this->error_code.vendor_id == PEN_IETF &&
255: this->error_code.type <= PA_ERROR_PA_TNC_MSG_ROOF)
256: {
257: if (!reader->read_data(reader, PA_ERROR_MSG_INFO_SIZE, &this->msg_info))
258: {
259: reader->destroy(reader);
260: DBG1(DBG_TNC, "insufficient data for IETF error information");
261: *offset = PA_ERROR_HEADER_SIZE;
262: return FAILED;
263: }
264: this->msg_info = chunk_clone(this->msg_info);
265:
266: switch (this->error_code.type)
267: {
268: case PA_ERROR_INVALID_PARAMETER:
269: if (!reader->read_uint32(reader, &this->error_offset))
270: {
271: reader->destroy(reader);
272: DBG1(DBG_TNC, "insufficient data for error offset field");
273: *offset = PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE;
274: return FAILED;
275: }
276: break;
277: case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
278: if (reader->remaining(reader) < PA_ERROR_ATTR_INFO_SIZE)
279: {
280: reader->destroy(reader);
281: DBG1(DBG_TNC, "insufficient data for unsupported attribute "
282: "information");
283: *offset = PA_ERROR_HEADER_SIZE + PA_ERROR_MSG_INFO_SIZE;
284: return FAILED;
285: }
286: reader->read_uint8 (reader, &this->flags);
287: reader->read_uint24(reader, &vendor_id);
288: reader->read_uint32(reader, &type);
289: this->unsupported_type = pen_type_create(vendor_id, type);
290: break;
291: default:
292: break;
293: }
294: }
295: else
296: {
297: reader->read_data(reader, reader->remaining(reader), &this->msg_info);
298: this->msg_info = chunk_clone(this->msg_info);
299: }
300: reader->destroy(reader);
301:
302: return SUCCESS;
303: }
304:
305: METHOD(pa_tnc_attr_t, add_segment, void,
306: private_ietf_attr_pa_tnc_error_t *this, chunk_t segment)
307: {
308: this->value = chunk_cat("mc", this->value, segment);
309: }
310:
311: METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
312: private_ietf_attr_pa_tnc_error_t *this)
313: {
314: ref_get(&this->ref);
315: return &this->public.pa_tnc_attribute;
316: }
317:
318: METHOD(pa_tnc_attr_t, destroy, void,
319: private_ietf_attr_pa_tnc_error_t *this)
320: {
321: if (ref_put(&this->ref))
322: {
323: free(this->value.ptr);
324: free(this->msg_info.ptr);
325: free(this);
326: }
327: }
328:
329: METHOD(ietf_attr_pa_tnc_error_t, get_error_code, pen_type_t,
330: private_ietf_attr_pa_tnc_error_t *this)
331: {
332: return this->error_code;
333: }
334:
335: METHOD(ietf_attr_pa_tnc_error_t, get_msg_info, chunk_t,
336: private_ietf_attr_pa_tnc_error_t *this)
337: {
338: return this->msg_info;
339: }
340:
341: METHOD(ietf_attr_pa_tnc_error_t, get_unsupported_attr, pen_type_t,
342: private_ietf_attr_pa_tnc_error_t *this, uint8_t *flags)
343: {
344: if (flags)
345: {
346: *flags = this->flags;
347: }
348: return this->unsupported_type;
349: }
350:
351: METHOD(ietf_attr_pa_tnc_error_t, set_unsupported_attr, void,
352: private_ietf_attr_pa_tnc_error_t *this, uint8_t flags, pen_type_t type)
353: {
354: this->flags = flags;
355: this->unsupported_type = type;
356: }
357:
358: METHOD(ietf_attr_pa_tnc_error_t, get_offset, uint32_t,
359: private_ietf_attr_pa_tnc_error_t *this)
360: {
361: return this->error_offset;
362: }
363:
364: /**
365: * Generic constructor
366: */
367: static private_ietf_attr_pa_tnc_error_t* create_generic()
368: {
369: private_ietf_attr_pa_tnc_error_t *this;
370:
371: INIT(this,
372: .public = {
373: .pa_tnc_attribute = {
374: .get_type = _get_type,
375: .get_value = _get_value,
376: .get_noskip_flag = _get_noskip_flag,
377: .set_noskip_flag = _set_noskip_flag,
378: .build = _build,
379: .process = _process,
380: .add_segment = _add_segment,
381: .get_ref = _get_ref,
382: .destroy = _destroy,
383: },
384: .get_error_code = _get_error_code,
385: .get_msg_info = _get_msg_info,
386: .get_unsupported_attr = _get_unsupported_attr,
387: .set_unsupported_attr = _set_unsupported_attr,
388: .get_offset = _get_offset,
389: },
390: .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
391: .ref = 1,
392: );
393:
394: return this;
395: }
396:
397: /**
398: * Described in header.
399: */
400: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
401: chunk_t msg_info)
402: {
403: private_ietf_attr_pa_tnc_error_t *this;
404:
405: if (error_code.vendor_id == PEN_IETF &&
406: error_code.type <= PA_ERROR_PA_TNC_MSG_ROOF)
407: {
408: msg_info.len = PA_ERROR_MSG_INFO_SIZE;
409: }
410: else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE)
411: {
412: msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE;
413: }
414:
415: this = create_generic();
416: this->error_code = error_code;
417: this->msg_info = chunk_clone(msg_info);
418:
419: return &this->public.pa_tnc_attribute;
420: }
421:
422: /**
423: * Described in header.
424: */
425: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
426: chunk_t msg_info,
427: uint32_t error_offset)
428: {
429: private_ietf_attr_pa_tnc_error_t *this;
430:
431: /* the first 8 bytes of the erroneous PA-TNC message are sent back */
432: msg_info.len = PA_ERROR_MSG_INFO_SIZE;
433:
434: this = create_generic();
435: this->error_code = error_code;
436: this->msg_info = chunk_clone(msg_info);
437: this->error_offset = error_offset;
438:
439: return &this->public.pa_tnc_attribute;
440: }
441:
442: /**
443: * Described in header.
444: */
445: pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(size_t length,
446: chunk_t data)
447: {
448: private_ietf_attr_pa_tnc_error_t *this;
449:
450: this = create_generic();
451: this->length = length;
452: this->value = chunk_clone(data);
453:
454: return &this->public.pa_tnc_attribute;
455: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>