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