updated Doxyfile
[strongswan.git] / src / charon / encoding / payloads / notify_payload.c
1 /*
2 * Copyright (C) 2006-2008 Tobias Brunner
3 * Copyright (C) 2006 Daniel Roethlisberger
4 * Copyright (C) 2005-2006 Martin Willi
5 * Copyright (C) 2005 Jan Hutter
6 * 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 * $Id$
19 */
20
21 #include <stddef.h>
22
23 #include "notify_payload.h"
24
25 #include <daemon.h>
26 #include <encoding/payloads/encodings.h>
27 #include <crypto/hashers/hasher.h>
28
29 ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
30 "UNSUPPORTED_CRITICAL_PAYLOAD");
31 ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
32 "INVALID_IKE_SPI",
33 "INVALID_MAJOR_VERSION");
34 ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
35 "INVALID_SYNTAX");
36 ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
37 "INVALID_MESSAGE_ID");
38 ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
39 "INVALID_SPI");
40 ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
41 "NO_PROPOSAL_CHOSEN");
42 ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
43 "INVALID_KE_PAYLOAD");
44 ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
45 "AUTHENTICATION_FAILED");
46 ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED, AUTHENTICATION_FAILED,
47 "SINGLE_PAIR_REQUIRED",
48 "NO_ADDITIONAL_SAS",
49 "INTERNAL_ADDRESS_FAILURE",
50 "FAILED_CP_REQUIRED",
51 "TS_UNACCEPTABLE",
52 "INVALID_SELECTORS",
53 "UNACCEPTABLE_ADDRESSES",
54 "UNEXPECTED_NAT_DETECTED");
55 ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED,
56 "ME_CONNECT_FAILED");
57 ENUM_NEXT(notify_type_names, INITIAL_CONTACT, ANOTHER_AUTH_FOLLOWS, ME_CONNECT_FAILED,
58 "INITIAL_CONTACT",
59 "SET_WINDOW_SIZE",
60 "ADDITIONAL_TS_POSSIBLE",
61 "IPCOMP_SUPPORTED",
62 "NAT_DETECTION_SOURCE_IP",
63 "NAT_DETECTION_DESTINATION_IP",
64 "COOKIE",
65 "USE_TRANSPORT_MODE",
66 "HTTP_CERT_LOOKUP_SUPPORTED",
67 "REKEY_SA",
68 "ESP_TFC_PADDING_NOT_SUPPORTED",
69 "NON_FIRST_FRAGMENTS_ALSO",
70 "MOBIKE_SUPPORTED",
71 "ADDITIONAL_IP4_ADDRESS",
72 "ADDITIONAL_IP6_ADDRESS",
73 "NO_ADDITIONAL_ADDRESSES",
74 "UPDATE_SA_ADDRESSES",
75 "COOKIE2",
76 "NO_NATS_ALLOWED",
77 "AUTH_LIFETIME",
78 "MULTIPLE_AUTH_SUPPORTED",
79 "ANOTHER_AUTH_FOLLOWS");
80 ENUM_NEXT(notify_type_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, ANOTHER_AUTH_FOLLOWS,
81 "EAP_ONLY_AUTHENTICATION");
82 ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
83 "USE_BEET_MODE");
84 ENUM_NEXT(notify_type_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
85 "ME_MEDIATION",
86 "ME_ENDPOINT",
87 "ME_CALLBACK",
88 "ME_CONNECTID",
89 "ME_CONNECTKEY",
90 "ME_CONNECTAUTH",
91 "ME_RESPONSE");
92 ENUM_END(notify_type_names, ME_RESPONSE);
93
94
95 ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
96 "CRIT");
97 ENUM_NEXT(notify_type_short_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
98 "INVAL_IKE_SPI",
99 "INVAL_MAJOR");
100 ENUM_NEXT(notify_type_short_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
101 "INVAL_SYN");
102 ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
103 "INVAL_MID");
104 ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
105 "INVAL_SPI");
106 ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI,
107 "NO_PROP");
108 ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN,
109 "INVAL_KE");
110 ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD,
111 "AUTH_FAILED");
112 ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, UNEXPECTED_NAT_DETECTED, AUTHENTICATION_FAILED,
113 "SINGLE_PAIR",
114 "NO_ADD_SAS",
115 "INT_ADDR_FAIL",
116 "FAIL_CP_REQ",
117 "TS_UNACCEPT",
118 "INVAL_SEL",
119 "UNACCEPT_ADDR",
120 "UNEXPECT_NAT");
121 ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, UNEXPECTED_NAT_DETECTED,
122 "ME_CONN_FAIL");
123 ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, ANOTHER_AUTH_FOLLOWS, ME_CONNECT_FAILED,
124 "INIT_CONTACT",
125 "SET_WINSIZE",
126 "ADD_TS_POSS",
127 "IPCOMP_SUPP",
128 "NATD_S_IP",
129 "NATD_D_IP",
130 "COOKIE",
131 "USE_TRANSP",
132 "HTTP_CERT_LOOK",
133 "REKEY_SA",
134 "ESP_TFC_PAD_N",
135 "NON_FIRST_FRAG",
136 "MOBIKE_SUP",
137 "ADD_4_ADDR",
138 "ADD_6_ADDR",
139 "NO_ADD_ADDR",
140 "UPD_SA_ADDR",
141 "COOKIE2",
142 "NO_NATS",
143 "AUTH_LFT",
144 "MULT_AUTH",
145 "AUTH_FOLLOWS");
146 ENUM_NEXT(notify_type_short_names, EAP_ONLY_AUTHENTICATION, EAP_ONLY_AUTHENTICATION, ANOTHER_AUTH_FOLLOWS,
147 "EAP_ONLY");
148 ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, EAP_ONLY_AUTHENTICATION,
149 "BEET_MODE");
150 ENUM_NEXT(notify_type_short_names, ME_MEDIATION, ME_RESPONSE, USE_BEET_MODE,
151 "ME_MED",
152 "ME_EP",
153 "ME_CB",
154 "ME_CID",
155 "ME_CKEY",
156 "ME_CAUTH",
157 "ME_R");
158 ENUM_END(notify_type_short_names, ME_RESPONSE);
159
160
161 typedef struct private_notify_payload_t private_notify_payload_t;
162
163 /**
164 * Private data of an notify_payload_t object.
165 *
166 */
167 struct private_notify_payload_t {
168 /**
169 * Public notify_payload_t interface.
170 */
171 notify_payload_t public;
172
173 /**
174 * Next payload type.
175 */
176 u_int8_t next_payload;
177
178 /**
179 * Critical flag.
180 */
181 bool critical;
182
183 /**
184 * Length of this payload.
185 */
186 u_int16_t payload_length;
187
188 /**
189 * Protocol id.
190 */
191 u_int8_t protocol_id;
192
193 /**
194 * Spi size.
195 */
196 u_int8_t spi_size;
197
198 /**
199 * Notify message type.
200 */
201 u_int16_t notify_type;
202
203 /**
204 * Security parameter index (spi).
205 */
206 chunk_t spi;
207
208 /**
209 * Notification data.
210 */
211 chunk_t notification_data;
212 };
213
214 /**
215 * Encoding rules to parse or generate a IKEv2-Notify Payload.
216 *
217 * The defined offsets are the positions in a object of type
218 * private_notify_payload_t.
219 *
220 */
221 encoding_rule_t notify_payload_encodings[] = {
222 /* 1 Byte next payload type, stored in the field next_payload */
223 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
224 /* the critical bit */
225 { FLAG, offsetof(private_notify_payload_t, critical) },
226 /* 7 Bit reserved bits, nowhere stored */
227 { RESERVED_BIT, 0 },
228 { RESERVED_BIT, 0 },
229 { RESERVED_BIT, 0 },
230 { RESERVED_BIT, 0 },
231 { RESERVED_BIT, 0 },
232 { RESERVED_BIT, 0 },
233 { RESERVED_BIT, 0 },
234 /* Length of the whole payload*/
235 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
236 /* Protocol ID as 8 bit field*/
237 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
238 /* SPI Size as 8 bit field*/
239 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
240 /* Notify message type as 16 bit field*/
241 { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
242 /* SPI as variable length field*/
243 { SPI, offsetof(private_notify_payload_t, spi) },
244 /* Key Exchange Data is from variable size */
245 { NOTIFICATION_DATA, offsetof(private_notify_payload_t, notification_data) }
246 };
247
248 /*
249 1 2 3
250 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
251 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252 ! Next Payload !C! RESERVED ! Payload Length !
253 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254 ! Protocol ID ! SPI Size ! Notify Message Type !
255 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
256 ! !
257 ~ Security Parameter Index (SPI) ~
258 ! !
259 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 ! !
261 ~ Notification Data ~
262 ! !
263 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264 */
265
266 /**
267 * Implementation of payload_t.verify.
268 */
269 static status_t verify(private_notify_payload_t *this)
270 {
271 bool bad_length = FALSE;
272
273 switch (this->protocol_id)
274 {
275 case PROTO_NONE:
276 case PROTO_IKE:
277 case PROTO_AH:
278 case PROTO_ESP:
279 break;
280 default:
281 DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
282 return FAILED;
283 }
284
285 switch (this->notify_type)
286 {
287 case INVALID_KE_PAYLOAD:
288 {
289 if (this->notification_data.len != 2)
290 {
291 bad_length = TRUE;
292 }
293 break;
294 }
295 case NAT_DETECTION_SOURCE_IP:
296 case NAT_DETECTION_DESTINATION_IP:
297 case ME_CONNECTAUTH:
298 {
299 if (this->notification_data.len != HASH_SIZE_SHA1)
300 {
301 bad_length = TRUE;
302 }
303 break;
304 }
305 case INVALID_SYNTAX:
306 case INVALID_MAJOR_VERSION:
307 case NO_PROPOSAL_CHOSEN:
308 {
309 if (this->notification_data.len != 0)
310 {
311 bad_length = TRUE;
312 }
313 break;
314 }
315 case ADDITIONAL_IP4_ADDRESS:
316 {
317 if (this->notification_data.len != 4)
318 {
319 bad_length = TRUE;
320 }
321 break;
322 }
323 case ADDITIONAL_IP6_ADDRESS:
324 {
325 if (this->notification_data.len != 16)
326 {
327 bad_length = TRUE;
328 }
329 break;
330 }
331 case AUTH_LIFETIME:
332 {
333 if (this->notification_data.len != 4)
334 {
335 bad_length = TRUE;
336 }
337 break;
338 }
339 case IPCOMP_SUPPORTED:
340 {
341 if (this->notification_data.len != 3)
342 {
343 bad_length = TRUE;
344 }
345 break;
346 }
347 case ME_ENDPOINT:
348 if (this->notification_data.len != 8 &&
349 this->notification_data.len != 12 &&
350 this->notification_data.len != 24)
351 {
352 bad_length = TRUE;
353 }
354 break;
355 case ME_CONNECTID:
356 if (this->notification_data.len < 4 ||
357 this->notification_data.len > 16)
358 {
359 bad_length = TRUE;
360 }
361 break;
362 case ME_CONNECTKEY:
363 if (this->notification_data.len < 16 ||
364 this->notification_data.len > 32)
365 {
366 bad_length = TRUE;
367 }
368 break;
369 default:
370 /* TODO: verify */
371 break;
372 }
373 if (bad_length)
374 {
375 DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
376 notify_type_names, this->notify_type,
377 this->notification_data.len);
378 return FAILED;
379 }
380 return SUCCESS;
381 }
382
383 /**
384 * Implementation of payload_t.get_encoding_rules.
385 */
386 static void get_encoding_rules(private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
387 {
388 *rules = notify_payload_encodings;
389 *rule_count = sizeof(notify_payload_encodings) / sizeof(encoding_rule_t);
390 }
391
392 /**
393 * Implementation of payload_t.get_type.
394 */
395 static payload_type_t get_type(private_notify_payload_t *this)
396 {
397 return NOTIFY;
398 }
399
400 /**
401 * Implementation of payload_t.get_next_type.
402 */
403 static payload_type_t get_next_type(private_notify_payload_t *this)
404 {
405 return (this->next_payload);
406 }
407
408 /**
409 * Implementation of payload_t.set_next_type.
410 */
411 static void set_next_type(private_notify_payload_t *this,payload_type_t type)
412 {
413 this->next_payload = type;
414 }
415
416 /**
417 * recompute the payloads length.
418 */
419 static void compute_length (private_notify_payload_t *this)
420 {
421 size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH;
422 if (this->notification_data.ptr != NULL)
423 {
424 length += this->notification_data.len;
425 }
426 if (this->spi.ptr != NULL)
427 {
428 length += this->spi.len;
429 }
430 this->payload_length = length;
431 }
432
433 /**
434 * Implementation of payload_t.get_length.
435 */
436 static size_t get_length(private_notify_payload_t *this)
437 {
438 compute_length(this);
439 return this->payload_length;
440 }
441
442 /**
443 * Implementation of notify_payload_t.get_protocol_id.
444 */
445 static u_int8_t get_protocol_id(private_notify_payload_t *this)
446 {
447 return this->protocol_id;
448 }
449
450 /**
451 * Implementation of notify_payload_t.set_protocol_id.
452 */
453 static void set_protocol_id(private_notify_payload_t *this, u_int8_t protocol_id)
454 {
455 this->protocol_id = protocol_id;
456 }
457
458 /**
459 * Implementation of notify_payload_t.get_notify_type.
460 */
461 static notify_type_t get_notify_type(private_notify_payload_t *this)
462 {
463 return this->notify_type;
464 }
465
466 /**
467 * Implementation of notify_payload_t.set_notify_type.
468 */
469 static void set_notify_type(private_notify_payload_t *this, u_int16_t notify_type)
470 {
471 this->notify_type = notify_type;
472 }
473
474 /**
475 * Implementation of notify_payload_t.get_spi.
476 */
477 static u_int32_t get_spi(private_notify_payload_t *this)
478 {
479 switch (this->protocol_id)
480 {
481 case PROTO_AH:
482 case PROTO_ESP:
483 if (this->spi.len == 4)
484 {
485 return *((u_int32_t*)this->spi.ptr);
486 }
487 default:
488 break;
489 }
490 return 0;
491 }
492
493 /**
494 * Implementation of notify_payload_t.set_spi.
495 */
496 static void set_spi(private_notify_payload_t *this, u_int32_t spi)
497 {
498 chunk_free(&this->spi);
499 switch (this->protocol_id)
500 {
501 case PROTO_AH:
502 case PROTO_ESP:
503 this->spi = chunk_alloc(4);
504 *((u_int32_t*)this->spi.ptr) = spi;
505 break;
506 default:
507 break;
508 }
509 this->spi_size = this->spi.len;
510 compute_length(this);
511 }
512
513 /**
514 * Implementation of notify_payload_t.get_notification_data.
515 */
516 static chunk_t get_notification_data(private_notify_payload_t *this)
517 {
518 return (this->notification_data);
519 }
520
521 /**
522 * Implementation of notify_payload_t.set_notification_data.
523 */
524 static status_t set_notification_data(private_notify_payload_t *this, chunk_t notification_data)
525 {
526 chunk_free(&this->notification_data);
527 if (notification_data.len > 0)
528 {
529 this->notification_data = chunk_clone(notification_data);
530 }
531 compute_length(this);
532 return SUCCESS;
533 }
534
535 /**
536 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
537 */
538 static status_t destroy(private_notify_payload_t *this)
539 {
540 chunk_free(&this->notification_data);
541 chunk_free(&this->spi);
542 free(this);
543 return SUCCESS;
544 }
545
546 /*
547 * Described in header
548 */
549 notify_payload_t *notify_payload_create()
550 {
551 private_notify_payload_t *this = malloc_thing(private_notify_payload_t);
552
553 /* interface functions */
554 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
555 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
556 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
557 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
558 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
559 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
560 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
561
562 /* public functions */
563 this->public.get_protocol_id = (u_int8_t (*) (notify_payload_t *)) get_protocol_id;
564 this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id;
565 this->public.get_notify_type = (notify_type_t (*) (notify_payload_t *)) get_notify_type;
566 this->public.set_notify_type = (void (*) (notify_payload_t *,notify_type_t)) set_notify_type;
567 this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi;
568 this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi;
569 this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data;
570 this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data;
571 this->public.destroy = (void (*) (notify_payload_t *)) destroy;
572
573 /* set default values of the fields */
574 this->critical = FALSE;
575 this->next_payload = NO_PAYLOAD;
576 this->payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH;
577 this->protocol_id = 0;
578 this->notify_type = 0;
579 this->spi.ptr = NULL;
580 this->spi.len = 0;
581 this->spi_size = 0;
582 this->notification_data.ptr = NULL;
583 this->notification_data.len = 0;
584
585 return &this->public;
586 }
587
588 /*
589 * Described in header.
590 */
591 notify_payload_t *notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id, notify_type_t notify_type)
592 {
593 notify_payload_t *notify = notify_payload_create();
594
595 notify->set_notify_type(notify,notify_type);
596 notify->set_protocol_id(notify,protocol_id);
597
598 return notify;
599 }