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
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>.
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
23 #include "notify_payload.h"
26 #include <encoding/payloads/encodings.h>
27 #include <crypto/hashers/hasher.h>
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
,
33 "INVALID_MAJOR_VERSION");
34 ENUM_NEXT(notify_type_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
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
,
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",
49 "INTERNAL_ADDRESS_FAILURE",
53 "UNACCEPTABLE_ADDRESSES",
54 "UNEXPECTED_NAT_DETECTED");
55 ENUM_NEXT(notify_type_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, UNEXPECTED_NAT_DETECTED
,
57 ENUM_NEXT(notify_type_names
, INITIAL_CONTACT
, AUTH_LIFETIME
, ME_CONNECT_FAILED
,
60 "ADDITIONAL_TS_POSSIBLE",
62 "NAT_DETECTION_SOURCE_IP",
63 "NAT_DETECTION_DESTINATION_IP",
66 "HTTP_CERT_LOOKUP_SUPPORTED",
68 "ESP_TFC_PADDING_NOT_SUPPORTED",
69 "NON_FIRST_FRAGMENTS_ALSO",
71 "ADDITIONAL_IP4_ADDRESS",
72 "ADDITIONAL_IP6_ADDRESS",
73 "NO_ADDITIONAL_ADDRESSES",
74 "UPDATE_SA_ADDRESSES",
78 ENUM_NEXT(notify_type_names
, EAP_ONLY_AUTHENTICATION
, EAP_ONLY_AUTHENTICATION
, AUTH_LIFETIME
,
79 "EAP_ONLY_AUTHENTICATION");
80 ENUM_NEXT(notify_type_names
, USE_BEET_MODE
, USE_BEET_MODE
, EAP_ONLY_AUTHENTICATION
,
82 ENUM_NEXT(notify_type_names
, ME_MEDIATION
, ME_RESPONSE
, USE_BEET_MODE
,
90 ENUM_END(notify_type_names
, ME_RESPONSE
);
93 ENUM_BEGIN(notify_type_short_names
, UNSUPPORTED_CRITICAL_PAYLOAD
, UNSUPPORTED_CRITICAL_PAYLOAD
,
95 ENUM_NEXT(notify_type_short_names
, INVALID_IKE_SPI
, INVALID_MAJOR_VERSION
, UNSUPPORTED_CRITICAL_PAYLOAD
,
98 ENUM_NEXT(notify_type_short_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
100 ENUM_NEXT(notify_type_short_names
, INVALID_MESSAGE_ID
, INVALID_MESSAGE_ID
, INVALID_SYNTAX
,
102 ENUM_NEXT(notify_type_short_names
, INVALID_SPI
, INVALID_SPI
, INVALID_MESSAGE_ID
,
104 ENUM_NEXT(notify_type_short_names
, NO_PROPOSAL_CHOSEN
, NO_PROPOSAL_CHOSEN
, INVALID_SPI
,
106 ENUM_NEXT(notify_type_short_names
, INVALID_KE_PAYLOAD
, INVALID_KE_PAYLOAD
, NO_PROPOSAL_CHOSEN
,
108 ENUM_NEXT(notify_type_short_names
, AUTHENTICATION_FAILED
, AUTHENTICATION_FAILED
, INVALID_KE_PAYLOAD
,
110 ENUM_NEXT(notify_type_short_names
, SINGLE_PAIR_REQUIRED
, UNEXPECTED_NAT_DETECTED
, AUTHENTICATION_FAILED
,
119 ENUM_NEXT(notify_type_short_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, UNEXPECTED_NAT_DETECTED
,
121 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT
, AUTH_LIFETIME
, ME_CONNECT_FAILED
,
142 ENUM_NEXT(notify_type_short_names
, EAP_ONLY_AUTHENTICATION
, EAP_ONLY_AUTHENTICATION
, AUTH_LIFETIME
,
144 ENUM_NEXT(notify_type_short_names
, USE_BEET_MODE
, USE_BEET_MODE
, EAP_ONLY_AUTHENTICATION
,
146 ENUM_NEXT(notify_type_short_names
, ME_MEDIATION
, ME_RESPONSE
, USE_BEET_MODE
,
154 ENUM_END(notify_type_short_names
, ME_RESPONSE
);
157 typedef struct private_notify_payload_t private_notify_payload_t
;
160 * Private data of an notify_payload_t object.
163 struct private_notify_payload_t
{
165 * Public notify_payload_t interface.
167 notify_payload_t
public;
172 u_int8_t next_payload
;
180 * Length of this payload.
182 u_int16_t payload_length
;
187 u_int8_t protocol_id
;
195 * Notify message type.
197 u_int16_t notify_type
;
200 * Security parameter index (spi).
207 chunk_t notification_data
;
211 * Encoding rules to parse or generate a IKEv2-Notify Payload.
213 * The defined offsets are the positions in a object of type
214 * private_notify_payload_t.
217 encoding_rule_t notify_payload_encodings
[] = {
218 /* 1 Byte next payload type, stored in the field next_payload */
219 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
220 /* the critical bit */
221 { FLAG
, offsetof(private_notify_payload_t
, critical
) },
222 /* 7 Bit reserved bits, nowhere stored */
230 /* Length of the whole payload*/
231 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
232 /* Protocol ID as 8 bit field*/
233 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
234 /* SPI Size as 8 bit field*/
235 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
236 /* Notify message type as 16 bit field*/
237 { U_INT_16
, offsetof(private_notify_payload_t
, notify_type
) },
238 /* SPI as variable length field*/
239 { SPI
, offsetof(private_notify_payload_t
, spi
) },
240 /* Key Exchange Data is from variable size */
241 { NOTIFICATION_DATA
, offsetof(private_notify_payload_t
, notification_data
) }
246 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
247 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248 ! Next Payload !C! RESERVED ! Payload Length !
249 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250 ! Protocol ID ! SPI Size ! Notify Message Type !
251 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
253 ~ Security Parameter Index (SPI) ~
255 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
257 ~ Notification Data ~
259 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * Implementation of payload_t.verify.
265 static status_t
verify(private_notify_payload_t
*this)
267 bool bad_length
= FALSE
;
269 switch (this->protocol_id
)
277 DBG1(DBG_ENC
, "Unknown protocol (%d)", this->protocol_id
);
281 switch (this->notify_type
)
283 case INVALID_KE_PAYLOAD
:
285 if (this->notification_data
.len
!= 2)
291 case NAT_DETECTION_SOURCE_IP
:
292 case NAT_DETECTION_DESTINATION_IP
:
295 if (this->notification_data
.len
!= HASH_SIZE_SHA1
)
302 case INVALID_MAJOR_VERSION
:
303 case NO_PROPOSAL_CHOSEN
:
305 if (this->notification_data
.len
!= 0)
311 case ADDITIONAL_IP4_ADDRESS
:
313 if (this->notification_data
.len
!= 4)
319 case ADDITIONAL_IP6_ADDRESS
:
321 if (this->notification_data
.len
!= 16)
329 if (this->notification_data
.len
!= 4)
336 if (this->notification_data
.len
!= 12 ||
337 this->notification_data
.len
!= 24)
343 if (this->notification_data
.len
< 4 ||
344 this->notification_data
.len
> 16)
350 if (this->notification_data
.len
< 16 ||
351 this->notification_data
.len
> 32)
362 DBG1(DBG_ENC
, "invalid notify data length for %N (%d)",
363 notify_type_names
, this->notify_type
,
364 this->notification_data
.len
);
371 * Implementation of payload_t.get_encoding_rules.
373 static void get_encoding_rules(private_notify_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
375 *rules
= notify_payload_encodings
;
376 *rule_count
= sizeof(notify_payload_encodings
) / sizeof(encoding_rule_t
);
380 * Implementation of payload_t.get_type.
382 static payload_type_t
get_type(private_notify_payload_t
*this)
388 * Implementation of payload_t.get_next_type.
390 static payload_type_t
get_next_type(private_notify_payload_t
*this)
392 return (this->next_payload
);
396 * Implementation of payload_t.set_next_type.
398 static void set_next_type(private_notify_payload_t
*this,payload_type_t type
)
400 this->next_payload
= type
;
404 * recompute the payloads length.
406 static void compute_length (private_notify_payload_t
*this)
408 size_t length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
409 if (this->notification_data
.ptr
!= NULL
)
411 length
+= this->notification_data
.len
;
413 if (this->spi
.ptr
!= NULL
)
415 length
+= this->spi
.len
;
417 this->payload_length
= length
;
421 * Implementation of payload_t.get_length.
423 static size_t get_length(private_notify_payload_t
*this)
425 compute_length(this);
426 return this->payload_length
;
430 * Implementation of notify_payload_t.get_protocol_id.
432 static u_int8_t
get_protocol_id(private_notify_payload_t
*this)
434 return this->protocol_id
;
438 * Implementation of notify_payload_t.set_protocol_id.
440 static void set_protocol_id(private_notify_payload_t
*this, u_int8_t protocol_id
)
442 this->protocol_id
= protocol_id
;
446 * Implementation of notify_payload_t.get_notify_type.
448 static notify_type_t
get_notify_type(private_notify_payload_t
*this)
450 return this->notify_type
;
454 * Implementation of notify_payload_t.set_notify_type.
456 static void set_notify_type(private_notify_payload_t
*this, u_int16_t notify_type
)
458 this->notify_type
= notify_type
;
462 * Implementation of notify_payload_t.get_spi.
464 static u_int32_t
get_spi(private_notify_payload_t
*this)
466 switch (this->protocol_id
)
470 if (this->spi
.len
== 4)
472 return *((u_int32_t
*)this->spi
.ptr
);
481 * Implementation of notify_payload_t.set_spi.
483 static void set_spi(private_notify_payload_t
*this, u_int32_t spi
)
485 chunk_free(&this->spi
);
486 switch (this->protocol_id
)
490 this->spi
= chunk_alloc(4);
491 *((u_int32_t
*)this->spi
.ptr
) = spi
;
496 this->spi_size
= this->spi
.len
;
497 compute_length(this);
501 * Implementation of notify_payload_t.get_notification_data.
503 static chunk_t
get_notification_data(private_notify_payload_t
*this)
505 return (this->notification_data
);
509 * Implementation of notify_payload_t.set_notification_data.
511 static status_t
set_notification_data(private_notify_payload_t
*this, chunk_t notification_data
)
513 chunk_free(&this->notification_data
);
514 if (notification_data
.len
> 0)
516 this->notification_data
= chunk_clone(notification_data
);
518 compute_length(this);
523 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
525 static status_t
destroy(private_notify_payload_t
*this)
527 chunk_free(&this->notification_data
);
528 chunk_free(&this->spi
);
534 * Described in header
536 notify_payload_t
*notify_payload_create()
538 private_notify_payload_t
*this = malloc_thing(private_notify_payload_t
);
540 /* interface functions */
541 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
542 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
543 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
544 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
545 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
546 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
547 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
549 /* public functions */
550 this->public.get_protocol_id
= (u_int8_t (*) (notify_payload_t
*)) get_protocol_id
;
551 this->public.set_protocol_id
= (void (*) (notify_payload_t
*,u_int8_t
)) set_protocol_id
;
552 this->public.get_notify_type
= (notify_type_t (*) (notify_payload_t
*)) get_notify_type
;
553 this->public.set_notify_type
= (void (*) (notify_payload_t
*,notify_type_t
)) set_notify_type
;
554 this->public.get_spi
= (u_int32_t (*) (notify_payload_t
*)) get_spi
;
555 this->public.set_spi
= (void (*) (notify_payload_t
*,u_int32_t
)) set_spi
;
556 this->public.get_notification_data
= (chunk_t (*) (notify_payload_t
*)) get_notification_data
;
557 this->public.set_notification_data
= (void (*) (notify_payload_t
*,chunk_t
)) set_notification_data
;
558 this->public.destroy
= (void (*) (notify_payload_t
*)) destroy
;
560 /* set default values of the fields */
561 this->critical
= FALSE
;
562 this->next_payload
= NO_PAYLOAD
;
563 this->payload_length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
564 this->protocol_id
= 0;
565 this->notify_type
= 0;
566 this->spi
.ptr
= NULL
;
569 this->notification_data
.ptr
= NULL
;
570 this->notification_data
.len
= 0;
572 return &this->public;
576 * Described in header.
578 notify_payload_t
*notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id
, notify_type_t notify_type
)
580 notify_payload_t
*notify
= notify_payload_create();
582 notify
->set_notify_type(notify
,notify_type
);
583 notify
->set_protocol_id(notify
,protocol_id
);