Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/id_payload.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2005-2011 Martin Willi
3: * Copyright (C) 2010 revosec AG
4: * Copyright (C) 2007-2011 Tobias Brunner
5: * Copyright (C) 2005 Jan Hutter
6: * HSR Hochschule fuer Technik Rapperswil
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public License as published by the
10: * Free Software Foundation; either version 2 of the License, or (at your
11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12: *
13: * This program is distributed in the hope that it will be useful, but
14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16: * for more details.
17: */
18:
19: #include <stddef.h>
20:
21: #include "id_payload.h"
22:
23: #include <daemon.h>
24: #include <encoding/payloads/encodings.h>
25:
26: typedef struct private_id_payload_t private_id_payload_t;
27:
28: /**
29: * Private data of an id_payload_t object.
30: */
31: struct private_id_payload_t {
32:
33: /**
34: * Public id_payload_t interface.
35: */
36: id_payload_t public;
37:
38: /**
39: * Next payload type.
40: */
41: uint8_t next_payload;
42:
43: /**
44: * Critical flag.
45: */
46: bool critical;
47:
48: /**
49: * Reserved bits
50: */
51: bool reserved_bit[7];
52:
53: /**
54: * Reserved bytes
55: */
56: uint8_t reserved_byte[3];
57:
58: /**
59: * Length of this payload.
60: */
61: uint16_t payload_length;
62:
63: /**
64: * Type of the ID Data.
65: */
66: uint8_t id_type;
67:
68: /**
69: * The contained id data value.
70: */
71: chunk_t id_data;
72:
73: /**
74: * Tunneled protocol ID for IKEv1 quick modes.
75: */
76: uint8_t protocol_id;
77:
78: /**
79: * Tunneled port for IKEv1 quick modes.
80: */
81: uint16_t port;
82:
83: /**
84: * one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, IDv1 and PLV1_NAT_OA
85: */
86: payload_type_t type;
87: };
88:
89: /**
90: * Encoding rules for an IKEv2 ID payload
91: */
92: static encoding_rule_t encodings_v2[] = {
93: /* 1 Byte next payload type, stored in the field next_payload */
94: { U_INT_8, offsetof(private_id_payload_t, next_payload) },
95: /* the critical bit */
96: { FLAG, offsetof(private_id_payload_t, critical) },
97: /* 7 Bit reserved bits */
98: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[0]) },
99: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[1]) },
100: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[2]) },
101: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[3]) },
102: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[4]) },
103: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[5]) },
104: { RESERVED_BIT, offsetof(private_id_payload_t, reserved_bit[6]) },
105: /* Length of the whole payload*/
106: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
107: /* 1 Byte ID type*/
108: { U_INT_8, offsetof(private_id_payload_t, id_type) },
109: /* 3 reserved bytes */
110: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
111: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[1])},
112: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[2])},
113: /* some id data bytes, length is defined in PAYLOAD_LENGTH */
114: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
115: };
116:
117: /*
118: 1 2 3
119: 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
120: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121: ! Next Payload !C! RESERVED ! Payload Length !
122: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123: ! ID Type ! RESERVED |
124: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125: ! !
126: ~ Identification Data ~
127: ! !
128: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129: */
130:
131: /**
132: * Encoding rules for an IKEv1 ID payload
133: */
134: static encoding_rule_t encodings_v1[] = {
135: /* 1 Byte next payload type, stored in the field next_payload */
136: { U_INT_8, offsetof(private_id_payload_t, next_payload) },
137: /* Reserved Byte is skipped */
138: { RESERVED_BYTE, offsetof(private_id_payload_t, reserved_byte[0])},
139: /* Length of the whole payload*/
140: { PAYLOAD_LENGTH, offsetof(private_id_payload_t, payload_length) },
141: /* 1 Byte ID type*/
142: { U_INT_8, offsetof(private_id_payload_t, id_type) },
143: { U_INT_8, offsetof(private_id_payload_t, protocol_id) },
144: { U_INT_16, offsetof(private_id_payload_t, port) },
145: /* some id data bytes, length is defined in PAYLOAD_LENGTH */
146: { CHUNK_DATA, offsetof(private_id_payload_t, id_data) },
147: };
148:
149: /*
150: 1 2 3
151: 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
152: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153: ! Next Payload ! RESERVED ! Payload Length !
154: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155: ! ID Type ! Protocol ID ! Port |
156: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157: ! !
158: ~ Identification Data ~
159: ! !
160: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161: */
162:
163: METHOD(payload_t, verify, status_t,
164: private_id_payload_t *this)
165: {
166: bool bad_length = FALSE;
167:
168: if ((this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) &&
169: this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
170: {
171: DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
172: this->id_type, payload_type_short_names, this->type);
173: return FAILED;
174: }
175: switch (this->id_type)
176: {
177: case ID_IPV4_ADDR_RANGE:
178: case ID_IPV4_ADDR_SUBNET:
179: bad_length = this->id_data.len != 8;
180: break;
181: case ID_IPV6_ADDR_RANGE:
182: case ID_IPV6_ADDR_SUBNET:
183: bad_length = this->id_data.len != 32;
184: break;
185: }
186: if (bad_length)
187: {
188: DBG1(DBG_ENC, "invalid %N length (%d bytes)",
189: id_type_names, this->id_type, this->id_data.len);
190: return FAILED;
191: }
192: return SUCCESS;
193: }
194:
195: METHOD(payload_t, get_encoding_rules, int,
196: private_id_payload_t *this, encoding_rule_t **rules)
197: {
198: if (this->type == PLV1_ID ||
199: this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03)
200: {
201: *rules = encodings_v1;
202: return countof(encodings_v1);
203: }
204: *rules = encodings_v2;
205: return countof(encodings_v2);
206: }
207:
208: METHOD(payload_t, get_header_length, int,
209: private_id_payload_t *this)
210: {
211: return 8;
212: }
213:
214: METHOD(payload_t, get_type, payload_type_t,
215: private_id_payload_t *this)
216: {
217: return this->type;
218: }
219:
220: METHOD(payload_t, get_next_type, payload_type_t,
221: private_id_payload_t *this)
222: {
223: return this->next_payload;
224: }
225:
226: METHOD(payload_t, set_next_type, void,
227: private_id_payload_t *this, payload_type_t type)
228: {
229: this->next_payload = type;
230: }
231:
232: METHOD(payload_t, get_length, size_t,
233: private_id_payload_t *this)
234: {
235: return this->payload_length;
236: }
237:
238: METHOD(id_payload_t, get_identification, identification_t*,
239: private_id_payload_t *this)
240: {
241: return identification_create_from_encoding(this->id_type, this->id_data);
242: }
243:
244: /**
245: * Create a traffic selector from an range ID
246: */
247: static traffic_selector_t *get_ts_from_range(private_id_payload_t *this,
248: ts_type_t type)
249: {
250: return traffic_selector_create_from_bytes(this->protocol_id, type,
251: chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port,
252: chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535);
253: }
254:
255: /**
256: * Create a traffic selector from an subnet ID
257: */
258: static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this,
259: ts_type_t type)
260: {
261: traffic_selector_t *ts;
262: chunk_t net, netmask;
263: int i;
264:
265: net = chunk_create(this->id_data.ptr, this->id_data.len / 2);
266: netmask = chunk_clone(chunk_skip(this->id_data, this->id_data.len / 2));
267: for (i = 0; i < net.len; i++)
268: {
269: netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i];
270: }
271: ts = traffic_selector_create_from_bytes(this->protocol_id, type,
272: net, this->port, netmask, this->port ?: 65535);
273: chunk_free(&netmask);
274: return ts;
275: }
276:
277: /**
278: * Create a traffic selector from an IP ID
279: */
280: static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this,
281: ts_type_t type)
282: {
283: return traffic_selector_create_from_bytes(this->protocol_id, type,
284: this->id_data, this->port, this->id_data, this->port ?: 65535);
285: }
286:
287: METHOD(id_payload_t, get_ts, traffic_selector_t*,
288: private_id_payload_t *this)
289: {
290: switch (this->id_type)
291: {
292: case ID_IPV4_ADDR_SUBNET:
293: if (this->id_data.len == 8)
294: {
295: return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE);
296: }
297: break;
298: case ID_IPV6_ADDR_SUBNET:
299: if (this->id_data.len == 32)
300: {
301: return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE);
302: }
303: break;
304: case ID_IPV4_ADDR_RANGE:
305: if (this->id_data.len == 8)
306: {
307: return get_ts_from_range(this, TS_IPV4_ADDR_RANGE);
308: }
309: break;
310: case ID_IPV6_ADDR_RANGE:
311: if (this->id_data.len == 32)
312: {
313: return get_ts_from_range(this, TS_IPV6_ADDR_RANGE);
314: }
315: break;
316: case ID_IPV4_ADDR:
317: if (this->id_data.len == 4)
318: {
319: return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE);
320: }
321: break;
322: case ID_IPV6_ADDR:
323: if (this->id_data.len == 16)
324: {
325: return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE);
326: }
327: break;
328: default:
329: break;
330: }
331: return NULL;
332: }
333:
334: METHOD(id_payload_t, get_encoded, chunk_t,
335: private_id_payload_t *this)
336: {
337: uint16_t port = htons(this->port);
338: return chunk_cat("cccc", chunk_from_thing(this->id_type),
339: chunk_from_thing(this->protocol_id),
340: chunk_from_thing(port), this->id_data);
341: }
342:
343: METHOD2(payload_t, id_payload_t, destroy, void,
344: private_id_payload_t *this)
345: {
346: free(this->id_data.ptr);
347: free(this);
348: }
349:
350: /*
351: * Described in header.
352: */
353: id_payload_t *id_payload_create(payload_type_t type)
354: {
355: private_id_payload_t *this;
356:
357: INIT(this,
358: .public = {
359: .payload_interface = {
360: .verify = _verify,
361: .get_encoding_rules = _get_encoding_rules,
362: .get_header_length = _get_header_length,
363: .get_length = _get_length,
364: .get_next_type = _get_next_type,
365: .set_next_type = _set_next_type,
366: .get_type = _get_type,
367: .destroy = _destroy,
368: },
369: .get_identification = _get_identification,
370: .get_encoded = _get_encoded,
371: .get_ts = _get_ts,
372: .destroy = _destroy,
373: },
374: .next_payload = PL_NONE,
375: .payload_length = get_header_length(this),
376: .type = type,
377: );
378: return &this->public;
379: }
380:
381: /*
382: * Described in header.
383: */
384: id_payload_t *id_payload_create_from_identification(payload_type_t type,
385: identification_t *id)
386: {
387: private_id_payload_t *this;
388:
389: this = (private_id_payload_t*)id_payload_create(type);
390: this->id_data = chunk_clone(id->get_encoding(id));
391: this->id_type = id->get_type(id);
392: this->payload_length += this->id_data.len;
393:
394: return &this->public;
395: }
396:
397: /*
398: * Described in header.
399: */
400: id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
401: {
402: private_id_payload_t *this;
403: uint8_t mask;
404: host_t *net;
405:
406: this = (private_id_payload_t*)id_payload_create(PLV1_ID);
407:
408: if (ts->is_host(ts, NULL))
409: {
410: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
411: {
412: this->id_type = ID_IPV4_ADDR;
413: }
414: else
415: {
416: this->id_type = ID_IPV6_ADDR;
417: }
418: this->id_data = chunk_clone(ts->get_from_address(ts));
419: }
420: else if (ts->to_subnet(ts, &net, &mask))
421: {
422: uint8_t netmask[16], len, byte;
423:
424: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
425: {
426: this->id_type = ID_IPV4_ADDR_SUBNET;
427: len = 4;
428: }
429: else
430: {
431: this->id_type = ID_IPV6_ADDR_SUBNET;
432: len = 16;
433: }
434: memset(netmask, 0, sizeof(netmask));
435: for (byte = 0; byte < sizeof(netmask); byte++)
436: {
437: if (mask < 8)
438: {
439: netmask[byte] = 0xFF << (8 - mask);
440: break;
441: }
442: netmask[byte] = 0xFF;
443: mask -= 8;
444: }
445: this->id_data = chunk_cat("cc", net->get_address(net),
446: chunk_create(netmask, len));
447: net->destroy(net);
448: }
449: else
450: {
451: if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE)
452: {
453: this->id_type = ID_IPV4_ADDR_RANGE;
454: }
455: else
456: {
457: this->id_type = ID_IPV6_ADDR_RANGE;
458: }
459: this->id_data = chunk_cat("cc",
460: ts->get_from_address(ts), ts->get_to_address(ts));
461: net->destroy(net);
462: }
463: this->port = ts->get_from_port(ts);
464: this->protocol_id = ts->get_protocol(ts);
465: this->payload_length += this->id_data.len;
466:
467: return &this->public;
468: }
469:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>