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