Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/configuration_attribute.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2005-2010 Martin Willi
3: * Copyright (C) 2010 revosec AG
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #include <stddef.h>
19:
20: #include "configuration_attribute.h"
21:
22: #include <encoding/payloads/encodings.h>
23: #include <library.h>
24: #include <daemon.h>
25:
26: typedef struct private_configuration_attribute_t private_configuration_attribute_t;
27:
28: /**
29: * Private data of an configuration_attribute_t object.
30: */
31: struct private_configuration_attribute_t {
32:
33: /**
34: * Public configuration_attribute_t interface.
35: */
36: configuration_attribute_t public;
37:
38: /**
39: * Value encoded in length field?
40: */
41: bool af_flag;
42:
43: /**
44: * Reserved bit (af_flag in IKEv2)
45: */
46: bool reserved;
47:
48: /**
49: * Type of the attribute.
50: */
51: uint16_t attr_type;
52:
53: /**
54: * Length of the attribute, value if af_flag set.
55: */
56: uint16_t length_or_value;
57:
58: /**
59: * Attribute value as chunk.
60: */
61: chunk_t value;
62:
63: /**
64: * Payload type, PLV2_CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
65: */
66: payload_type_t type;
67: };
68:
69: /**
70: * Encoding rules for a IKEv2 configuration attribute / IKEv1 data attribute
71: */
72: static encoding_rule_t encodings_v2[] = {
73: /* 1 reserved bit */
74: { RESERVED_BIT, offsetof(private_configuration_attribute_t, reserved) },
75: /* type of the attribute as 15 bit unsigned integer */
76: { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
77: /* Length of attribute value */
78: { ATTRIBUTE_LENGTH, offsetof(private_configuration_attribute_t, length_or_value)},
79: /* Value of attribute if attribute format flag is zero */
80: { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
81: };
82:
83: /*
84: 1 2 3
85: 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
86: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87: !R| Attribute Type ! Length |
88: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89: | |
90: ~ Value ~
91: | |
92: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93: */
94:
95: /**
96: * Encoding rules for a IKEv1 data attribute
97: */
98: static encoding_rule_t encodings_v1[] = {
99: /* AF Flag */
100: { ATTRIBUTE_FORMAT, offsetof(private_configuration_attribute_t, af_flag) },
101: /* type of the attribute as 15 bit unsigned integer */
102: { ATTRIBUTE_TYPE, offsetof(private_configuration_attribute_t, attr_type) },
103: /* Length of attribute value */
104: { ATTRIBUTE_LENGTH_OR_VALUE, offsetof(private_configuration_attribute_t, length_or_value)},
105: /* Value of attribute if attribute format flag is zero */
106: { ATTRIBUTE_VALUE, offsetof(private_configuration_attribute_t, value) },
107: };
108:
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: !F| Attribute Type ! Length |
114: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115: | |
116: ~ Value ~
117: | |
118: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119: */
120:
121:
122: METHOD(payload_t, verify, status_t,
123: private_configuration_attribute_t *this)
124: {
125: bool failed = FALSE;
126:
127: switch (this->attr_type)
128: {
129: case INTERNAL_IP4_ADDRESS:
130: case INTERNAL_IP4_NETMASK:
131: case INTERNAL_IP4_DNS:
132: case INTERNAL_IP4_NBNS:
133: case INTERNAL_ADDRESS_EXPIRY:
134: case INTERNAL_IP4_DHCP:
135: case P_CSCF_IP4_ADDRESS:
136: if (this->length_or_value != 0 && this->length_or_value != 4)
137: {
138: failed = TRUE;
139: }
140: break;
141: case INTERNAL_IP4_SUBNET:
142: if (this->length_or_value != 0 && this->length_or_value != 8)
143: {
144: failed = TRUE;
145: }
146: break;
147: case INTERNAL_IP6_ADDRESS:
148: if (this->type == PLV1_CONFIGURATION_ATTRIBUTE &&
149: this->length_or_value == 16)
150: { /* 16 bytes are correct for IKEv1, but older releases sent a
151: * prefix byte so we still accept 0 or 17 as in IKEv2 */
152: break;
153: }
154: /* fall-through */
155: case INTERNAL_IP6_SUBNET:
156: if (this->length_or_value != 0 && this->length_or_value != 17)
157: {
158: failed = TRUE;
159: }
160: break;
161: case INTERNAL_IP6_DNS:
162: case INTERNAL_IP6_NBNS:
163: case INTERNAL_IP6_DHCP:
164: case P_CSCF_IP6_ADDRESS:
165: if (this->length_or_value != 0 && this->length_or_value != 16)
166: {
167: failed = TRUE;
168: }
169: break;
170: case SUPPORTED_ATTRIBUTES:
171: if (this->length_or_value % 2)
172: {
173: failed = TRUE;
174: }
175: break;
176: case APPLICATION_VERSION:
177: case INTERNAL_IP4_SERVER:
178: case INTERNAL_IP6_SERVER:
179: case XAUTH_TYPE:
180: case XAUTH_USER_NAME:
181: case XAUTH_USER_PASSWORD:
182: case XAUTH_PASSCODE:
183: case XAUTH_MESSAGE:
184: case XAUTH_CHALLENGE:
185: case XAUTH_DOMAIN:
186: case XAUTH_STATUS:
187: case XAUTH_NEXT_PIN:
188: case XAUTH_ANSWER:
189: case UNITY_BANNER:
190: case UNITY_SAVE_PASSWD:
191: case UNITY_DEF_DOMAIN:
192: case UNITY_SPLITDNS_NAME:
193: case UNITY_SPLIT_INCLUDE:
194: case UNITY_NATT_PORT:
195: case UNITY_LOCAL_LAN:
196: case UNITY_PFS:
197: case UNITY_FW_TYPE:
198: case UNITY_BACKUP_SERVERS:
199: case UNITY_DDNS_HOSTNAME:
200: /* any length acceptable */
201: break;
202: default:
203: DBG1(DBG_ENC, "unknown attribute type %N",
204: configuration_attribute_type_names, this->attr_type);
205: break;
206: }
207:
208: if (failed)
209: {
210: DBG1(DBG_ENC, "invalid attribute length %d for %N",
211: this->length_or_value, configuration_attribute_type_names,
212: this->attr_type);
213: return FAILED;
214: }
215: return SUCCESS;
216: }
217:
218: METHOD(payload_t, get_encoding_rules, int,
219: private_configuration_attribute_t *this, encoding_rule_t **rules)
220: {
221: if (this->type == PLV2_CONFIGURATION_ATTRIBUTE)
222: {
223: *rules = encodings_v2;
224: return countof(encodings_v2);
225: }
226: *rules = encodings_v1;
227: return countof(encodings_v1);
228: }
229:
230: METHOD(payload_t, get_header_length, int,
231: private_configuration_attribute_t *this)
232: {
233: return 4;
234: }
235:
236: METHOD(payload_t, get_type, payload_type_t,
237: private_configuration_attribute_t *this)
238: {
239: return this->type;
240: }
241:
242: METHOD(payload_t, get_next_type, payload_type_t,
243: private_configuration_attribute_t *this)
244: {
245: return PL_NONE;
246: }
247:
248: METHOD(payload_t, set_next_type, void,
249: private_configuration_attribute_t *this, payload_type_t type)
250: {
251: }
252:
253: METHOD(payload_t, get_length, size_t,
254: private_configuration_attribute_t *this)
255: {
256: return get_header_length(this) + this->value.len;
257: }
258:
259: METHOD(configuration_attribute_t, get_cattr_type, configuration_attribute_type_t,
260: private_configuration_attribute_t *this)
261: {
262: return this->attr_type;
263: }
264:
265: METHOD(configuration_attribute_t, get_chunk, chunk_t,
266: private_configuration_attribute_t *this)
267: {
268: if (this->af_flag)
269: {
270: return chunk_from_thing(this->length_or_value);
271: }
272: return this->value;
273: }
274:
275: METHOD(configuration_attribute_t, get_value, uint16_t,
276: private_configuration_attribute_t *this)
277: {
278: if (this->af_flag)
279: {
280: return this->length_or_value;
281: }
282: return 0;
283: }
284:
285: METHOD2(payload_t, configuration_attribute_t, destroy, void,
286: private_configuration_attribute_t *this)
287: {
288: free(this->value.ptr);
289: free(this);
290: }
291:
292: /*
293: * Described in header.
294: */
295: configuration_attribute_t *configuration_attribute_create(payload_type_t type)
296: {
297: private_configuration_attribute_t *this;
298:
299: INIT(this,
300: .public = {
301: .payload_interface = {
302: .verify = _verify,
303: .get_encoding_rules = _get_encoding_rules,
304: .get_header_length = _get_header_length,
305: .get_length = _get_length,
306: .get_next_type = _get_next_type,
307: .set_next_type = _set_next_type,
308: .get_type = _get_type,
309: .destroy = _destroy,
310: },
311: .get_chunk = _get_chunk,
312: .get_value = _get_value,
313: .get_type = _get_cattr_type,
314: .destroy = _destroy,
315: },
316: .type = type
317: );
318: return &this->public;
319: }
320:
321: /*
322: * Described in header.
323: */
324: configuration_attribute_t *configuration_attribute_create_chunk(
325: payload_type_t type, configuration_attribute_type_t attr_type, chunk_t chunk)
326: {
327: private_configuration_attribute_t *this;
328:
329: this = (private_configuration_attribute_t*)
330: configuration_attribute_create(type);
331: this->attr_type = ((uint16_t)attr_type) & 0x7FFF;
332: this->value = chunk_clone(chunk);
333: this->length_or_value = chunk.len;
334:
335: return &this->public;
336: }
337:
338: /*
339: * Described in header.
340: */
341: configuration_attribute_t *configuration_attribute_create_value(
342: configuration_attribute_type_t attr_type, uint16_t value)
343: {
344: private_configuration_attribute_t *this;
345:
346: this = (private_configuration_attribute_t*)
347: configuration_attribute_create(PLV1_CONFIGURATION_ATTRIBUTE);
348: this->attr_type = ((uint16_t)attr_type) & 0x7FFF;
349: this->length_or_value = value;
350: this->af_flag = TRUE;
351:
352: return &this->public;
353: }
354:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>