Annotation of embedaddon/strongswan/src/libimcv/seg/seg_env.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2014-2015 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 "seg_env.h"
17:
18: #include "imcv.h"
19: #include "pa_tnc/pa_tnc_msg.h"
20: #include "ietf/ietf_attr_pa_tnc_error.h"
21: #include "tcg/seg/tcg_seg_attr_seg_env.h"
22:
23: #include <utils/debug.h>
24: #include <bio/bio_reader.h>
25: #include <bio/bio_writer.h>
26:
27: #define BASE_ATTR_ID_PREFIX 0xFF
28:
29: typedef struct private_seg_env_t private_seg_env_t;
30:
31: /**
32: * Private data of a seg_env_t object.
33: */
34: struct private_seg_env_t {
35:
36: /**
37: * Public seg_env_t interface.
38: */
39: seg_env_t public;
40:
41: /**
42: * Base Attribute ID
43: */
44: uint32_t base_attr_id;
45:
46: /**
47: * Base Attribute
48: */
49: pa_tnc_attr_t *base_attr;
50:
51: /**
52: * Base Attribute Info to be used for PA-TNC error messages
53: */
54: u_char base_attr_info[8];
55:
56: /**
57: * Base Attribute needs more segment data
58: */
59: bool need_more;
60:
61: /**
62: * Pointer to remaining attribute data to be sent
63: */
64: chunk_t data;
65:
66: /**
67: * Maximum PA-TNC attribute segment size
68: */
69: uint32_t max_seg_size;
70:
71: };
72:
73: METHOD(seg_env_t, get_base_attr_id, uint32_t,
74: private_seg_env_t *this)
75: {
76: return this->base_attr_id;
77: }
78:
79: METHOD(seg_env_t, get_base_attr, pa_tnc_attr_t*,
80: private_seg_env_t *this)
81: {
82: return this->need_more ? NULL : this->base_attr->get_ref(this->base_attr);
83: }
84:
85: METHOD(seg_env_t, get_base_attr_info, chunk_t,
86: private_seg_env_t *this)
87: {
88: return chunk_create(this->base_attr_info, 8);
89: }
90:
91: METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
92: private_seg_env_t *this, size_t max_attr_len)
93: {
94: pa_tnc_attr_t *seg_env_attr;
95: bio_writer_t *writer;
96: pen_type_t type;
97: chunk_t segment_data, value;
98: size_t seg_size;
99: uint8_t flags, seg_env_flags;
100:
101: /* compute size of first segment */
102: seg_size = max_attr_len ? min(this->max_seg_size,
103: max_attr_len - PA_TNC_ATTR_HEADER_SIZE
104: - TCG_SEG_ATTR_SEG_ENV_HEADER)
105: : this->max_seg_size;
106:
107: /* get components of base attribute header and data */
108: flags = this->base_attr->get_noskip_flag(this->base_attr) ?
109: PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE;
110: type = this->base_attr->get_type(this->base_attr);
111:
112: /* attribute data going into the first segment */
113: segment_data = this->data;
114: segment_data.len = seg_size - PA_TNC_ATTR_HEADER_SIZE;
115:
116: /* build encoding of the base attribute header and first segment data */
117: writer = bio_writer_create(this->max_seg_size);
118: writer->write_uint8 (writer, flags);
119: writer->write_uint24(writer, type.vendor_id);
120: writer->write_uint32(writer, type.type);
121: writer->write_uint32(writer, PA_TNC_ATTR_HEADER_SIZE + this->data.len);
122: writer->write_data (writer, segment_data);
123: value = writer->extract_buf(writer);
124: writer->destroy(writer);
125: this->data = chunk_skip(this->data, segment_data.len);
126:
127: DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)",
128: this->base_attr_id, seg_size);
129:
130: seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE;
131: seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags,
132: this->base_attr_id);
133: chunk_free(&value);
134:
135: return seg_env_attr;
136: }
137:
138: METHOD(seg_env_t, next_segment, pa_tnc_attr_t*,
139: private_seg_env_t *this, bool *last)
140: {
141: pa_tnc_attr_t *seg_env_attr;
142: chunk_t segment_data;
143: uint8_t seg_env_flags;
144: bool is_last_segment;
145:
146: if (this->data.len == 0)
147: {
148: /* no more attribute data to segment available */
149: return NULL;
150: }
151:
152: /* attribute data going into the next segment */
153: segment_data = this->data;
154: segment_data.len = min(this->max_seg_size, this->data.len);
155: this->data = chunk_skip(this->data, segment_data.len);
156:
157: is_last_segment = (this->data.len == 0);
158: if (last)
159: {
160: *last = is_last_segment;
161: }
162: DBG2(DBG_TNC, "creating %s segment for base attribute ID %d (%d bytes)",
163: is_last_segment ? "last" : "next", this->base_attr_id,
164: segment_data.len);
165:
166: seg_env_flags = is_last_segment ? SEG_ENV_FLAG_NONE : SEG_ENV_FLAG_MORE;
167: seg_env_attr = tcg_seg_attr_seg_env_create(segment_data, seg_env_flags,
168: this->base_attr_id);
169:
170: return seg_env_attr;
171: }
172:
173: METHOD(seg_env_t, add_segment, bool,
174: private_seg_env_t *this, chunk_t segment, pa_tnc_attr_t **error)
175: {
176: pen_type_t type, error_code;
177: uint32_t attr_offset;
178: chunk_t msg_info;
179: status_t status;
180:
181: this->base_attr->add_segment(this->base_attr, segment);
182: status = this->base_attr->process(this->base_attr, &attr_offset);
183:
184: if (status != SUCCESS && status != NEED_MORE)
185: {
186: type = this->base_attr->get_type(this->base_attr);
187: if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
188: {
189: /* error while processing a PA-TNC error attribute - abort */
190: return FALSE;
191: }
192: error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
193: msg_info = get_base_attr_info(this);
194: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
195: msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
196: return FALSE;
197: }
198: this->need_more = (status == NEED_MORE);
199:
200: return TRUE;
201: }
202:
203: METHOD(seg_env_t, destroy, void,
204: private_seg_env_t *this)
205: {
206: DESTROY_IF(this->base_attr);
207: free(this);
208: }
209:
210: /**
211: * See header
212: */
213: seg_env_t *seg_env_create(uint32_t base_attr_id, pa_tnc_attr_t *base_attr,
214: uint32_t max_seg_size)
215: {
216: private_seg_env_t *this;
217: chunk_t value;
218:
219: base_attr->build(base_attr);
220: value = base_attr->get_value(base_attr);
221:
222: /**
223: * The PA-TNC attribute header must not be segmented and
224: * there must be at least a first and one next segment
225: */
226: if (max_seg_size < PA_TNC_ATTR_HEADER_SIZE ||
227: max_seg_size >= PA_TNC_ATTR_HEADER_SIZE + value.len)
228: {
229: base_attr->destroy(base_attr);
230: return NULL;
231: }
232:
233: INIT(this,
234: .public = {
235: .get_base_attr_id = _get_base_attr_id,
236: .get_base_attr = _get_base_attr,
237: .get_base_attr_info = _get_base_attr_info,
238: .first_segment = _first_segment,
239: .next_segment = _next_segment,
240: .add_segment = _add_segment,
241: .destroy = _destroy,
242: },
243: .base_attr_id = base_attr_id,
244: .base_attr = base_attr,
245: .max_seg_size = max_seg_size,
246: .data = base_attr->get_value(base_attr),
247: );
248:
249: return &this->public;
250: }
251:
252: /**
253: * See header
254: */
255: seg_env_t *seg_env_create_from_data(uint32_t base_attr_id, chunk_t data,
256: uint32_t max_seg_size, pa_tnc_attr_t** error)
257: {
258: private_seg_env_t *this;
259: pen_type_t type, error_code;
260: bio_reader_t *reader;
261: chunk_t msg_info;
262: uint32_t offset = 0, attr_offset;
263: status_t status;
264:
265: INIT(this,
266: .public = {
267: .get_base_attr_id = _get_base_attr_id,
268: .get_base_attr = _get_base_attr,
269: .get_base_attr_info = _get_base_attr_info,
270: .first_segment = _first_segment,
271: .next_segment = _next_segment,
272: .add_segment = _add_segment,
273: .destroy = _destroy,
274: },
275: .base_attr_id = base_attr_id,
276: .max_seg_size = max_seg_size,
277: );
278:
279: /* create info field to be used by PA-TNC error messages */
280: memset(this->base_attr_info, 0xff, 4);
281: htoun32(this->base_attr_info + 4, base_attr_id);
282: msg_info = get_base_attr_info(this);
283:
284: /* extract from base attribute segment from data */
285: reader = bio_reader_create(data);
286: this->base_attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
287: reader, TRUE, &offset, msg_info, error);
288: reader->destroy(reader);
289:
290: if (!this->base_attr)
291: {
292: destroy(this);
293: return NULL;
294: }
295: status = this->base_attr->process(this->base_attr, &attr_offset);
296:
297: if (status != SUCCESS && status != NEED_MORE)
298: {
299: type = this->base_attr->get_type(this->base_attr);
300: if (!(type.vendor_id == PEN_IETF &&
301: type.type == IETF_ATTR_PA_TNC_ERROR))
302: {
303: error_code = pen_type_create(PEN_IETF, PA_ERROR_INVALID_PARAMETER);
304: *error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
305: msg_info, PA_TNC_ATTR_HEADER_SIZE + attr_offset);
306: }
307: destroy(this);
308: return NULL;
309: }
310: this->need_more = (status == NEED_MORE);
311:
312: return &this->public;
313: }
314:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>