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
21 #include "notify_payload.h"
24 #include <encoding/payloads/encodings.h>
25 #include <crypto/hashers/hasher.h>
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
,
31 "INVALID_MAJOR_VERSION");
32 ENUM_NEXT(notify_type_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
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
,
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",
47 "INTERNAL_ADDRESS_FAILURE",
51 "UNACCEPTABLE_ADDRESSES",
52 "UNEXPECTED_NAT_DETECTED",
54 ENUM_NEXT(notify_type_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, USE_ASSIGNED_HoA
,
56 ENUM_NEXT(notify_type_names
, INITIAL_CONTACT
, EAP_ONLY_AUTHENTICATION
, ME_CONNECT_FAILED
,
59 "ADDITIONAL_TS_POSSIBLE",
61 "NAT_DETECTION_SOURCE_IP",
62 "NAT_DETECTION_DESTINATION_IP",
65 "HTTP_CERT_LOOKUP_SUPPORTED",
67 "ESP_TFC_PADDING_NOT_SUPPORTED",
68 "NON_FIRST_FRAGMENTS_ALSO",
70 "ADDITIONAL_IP4_ADDRESS",
71 "ADDITIONAL_IP6_ADDRESS",
72 "NO_ADDITIONAL_ADDRESSES",
73 "UPDATE_SA_ADDRESSES",
77 "MULTIPLE_AUTH_SUPPORTED",
78 "ANOTHER_AUTH_FOLLOWS",
90 "EAP_ONLY_AUTHENTICATION");
91 ENUM_NEXT(notify_type_names
, USE_BEET_MODE
, USE_BEET_MODE
, EAP_ONLY_AUTHENTICATION
,
93 ENUM_NEXT(notify_type_names
, ME_MEDIATION
, ME_RESPONSE
, USE_BEET_MODE
,
101 ENUM_END(notify_type_names
, ME_RESPONSE
);
104 ENUM_BEGIN(notify_type_short_names
, UNSUPPORTED_CRITICAL_PAYLOAD
, UNSUPPORTED_CRITICAL_PAYLOAD
,
106 ENUM_NEXT(notify_type_short_names
, INVALID_IKE_SPI
, INVALID_MAJOR_VERSION
, UNSUPPORTED_CRITICAL_PAYLOAD
,
109 ENUM_NEXT(notify_type_short_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
111 ENUM_NEXT(notify_type_short_names
, INVALID_MESSAGE_ID
, INVALID_MESSAGE_ID
, INVALID_SYNTAX
,
113 ENUM_NEXT(notify_type_short_names
, INVALID_SPI
, INVALID_SPI
, INVALID_MESSAGE_ID
,
115 ENUM_NEXT(notify_type_short_names
, NO_PROPOSAL_CHOSEN
, NO_PROPOSAL_CHOSEN
, INVALID_SPI
,
117 ENUM_NEXT(notify_type_short_names
, INVALID_KE_PAYLOAD
, INVALID_KE_PAYLOAD
, NO_PROPOSAL_CHOSEN
,
119 ENUM_NEXT(notify_type_short_names
, AUTHENTICATION_FAILED
, AUTHENTICATION_FAILED
, INVALID_KE_PAYLOAD
,
121 ENUM_NEXT(notify_type_short_names
, SINGLE_PAIR_REQUIRED
, USE_ASSIGNED_HoA
, AUTHENTICATION_FAILED
,
131 ENUM_NEXT(notify_type_short_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, USE_ASSIGNED_HoA
,
133 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT
, EAP_ONLY_AUTHENTICATION
, ME_CONNECT_FAILED
,
168 ENUM_NEXT(notify_type_short_names
, USE_BEET_MODE
, USE_BEET_MODE
, EAP_ONLY_AUTHENTICATION
,
170 ENUM_NEXT(notify_type_short_names
, ME_MEDIATION
, ME_RESPONSE
, USE_BEET_MODE
,
178 ENUM_END(notify_type_short_names
, ME_RESPONSE
);
181 typedef struct private_notify_payload_t private_notify_payload_t
;
184 * Private data of an notify_payload_t object.
187 struct private_notify_payload_t
{
189 * Public notify_payload_t interface.
191 notify_payload_t
public;
196 u_int8_t next_payload
;
204 * Length of this payload.
206 u_int16_t payload_length
;
211 u_int8_t protocol_id
;
219 * Notify message type.
221 u_int16_t notify_type
;
224 * Security parameter index (spi).
231 chunk_t notification_data
;
235 * Encoding rules to parse or generate a IKEv2-Notify Payload.
237 * The defined offsets are the positions in a object of type
238 * private_notify_payload_t.
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 */
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
) }
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 ~ Security Parameter Index (SPI) ~
279 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 ~ Notification Data ~
283 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
287 * Implementation of payload_t.verify.
289 static status_t
verify(private_notify_payload_t
*this)
291 bool bad_length
= FALSE
;
293 switch (this->protocol_id
)
301 DBG1(DBG_ENC
, "Unknown protocol (%d)", this->protocol_id
);
305 switch (this->notify_type
)
307 case INVALID_KE_PAYLOAD
:
309 if (this->notification_data
.len
!= 2)
315 case NAT_DETECTION_SOURCE_IP
:
316 case NAT_DETECTION_DESTINATION_IP
:
319 if (this->notification_data
.len
!= HASH_SIZE_SHA1
)
326 case INVALID_MAJOR_VERSION
:
327 case NO_PROPOSAL_CHOSEN
:
329 if (this->notification_data
.len
!= 0)
335 case ADDITIONAL_IP4_ADDRESS
:
337 if (this->notification_data
.len
!= 4)
343 case ADDITIONAL_IP6_ADDRESS
:
345 if (this->notification_data
.len
!= 16)
353 if (this->notification_data
.len
!= 4)
359 case IPCOMP_SUPPORTED
:
361 if (this->notification_data
.len
!= 3)
368 if (this->notification_data
.len
!= 8 &&
369 this->notification_data
.len
!= 12 &&
370 this->notification_data
.len
!= 24)
376 if (this->notification_data
.len
< 4 ||
377 this->notification_data
.len
> 16)
383 if (this->notification_data
.len
< 16 ||
384 this->notification_data
.len
> 32)
395 DBG1(DBG_ENC
, "invalid notify data length for %N (%d)",
396 notify_type_names
, this->notify_type
,
397 this->notification_data
.len
);
404 * Implementation of payload_t.get_encoding_rules.
406 static void get_encoding_rules(private_notify_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
408 *rules
= notify_payload_encodings
;
409 *rule_count
= sizeof(notify_payload_encodings
) / sizeof(encoding_rule_t
);
413 * Implementation of payload_t.get_type.
415 static payload_type_t
get_type(private_notify_payload_t
*this)
421 * Implementation of payload_t.get_next_type.
423 static payload_type_t
get_next_type(private_notify_payload_t
*this)
425 return (this->next_payload
);
429 * Implementation of payload_t.set_next_type.
431 static void set_next_type(private_notify_payload_t
*this,payload_type_t type
)
433 this->next_payload
= type
;
437 * recompute the payloads length.
439 static void compute_length (private_notify_payload_t
*this)
441 size_t length
= NOTIFY_PAYLOAD_HEADER_LENGTH
;
442 if (this->notification_data
.ptr
!= NULL
)
444 length
+= this->notification_data
.len
;
446 if (this->spi
.ptr
!= NULL
)
448 length
+= this->spi
.len
;
450 this->payload_length
= length
;
454 * Implementation of payload_t.get_length.
456 static size_t get_length(private_notify_payload_t
*this)
458 compute_length(this);
459 return this->payload_length
;
463 * Implementation of notify_payload_t.get_protocol_id.
465 static u_int8_t
get_protocol_id(private_notify_payload_t
*this)
467 return this->protocol_id
;
471 * Implementation of notify_payload_t.set_protocol_id.
473 static void set_protocol_id(private_notify_payload_t
*this, u_int8_t protocol_id
)
475 this->protocol_id
= protocol_id
;
479 * Implementation of notify_payload_t.get_notify_type.
481 static notify_type_t
get_notify_type(private_notify_payload_t
*this)
483 return this->notify_type
;
487 * Implementation of notify_payload_t.set_notify_type.
489 static void set_notify_type(private_notify_payload_t
*this, u_int16_t notify_type
)
491 this->notify_type
= notify_type
;
495 * Implementation of notify_payload_t.get_spi.
497 static u_int32_t
get_spi(private_notify_payload_t
*this)
499 switch (this->protocol_id
)
503 if (this->spi
.len
== 4)
505 return *((u_int32_t
*)this->spi
.ptr
);
514 * Implementation of notify_payload_t.set_spi.
516 static void set_spi(private_notify_payload_t
*this, u_int32_t spi
)
518 chunk_free(&this->spi
);
519 switch (this->protocol_id
)
523 this->spi
= chunk_alloc(4);
524 *((u_int32_t
*)this->spi
.ptr
) = spi
;
529 this->spi_size
= this->spi
.len
;
530 compute_length(this);
534 * Implementation of notify_payload_t.get_notification_data.
536 static chunk_t
get_notification_data(private_notify_payload_t
*this)
538 return (this->notification_data
);
542 * Implementation of notify_payload_t.set_notification_data.
544 static status_t
set_notification_data(private_notify_payload_t
*this, chunk_t notification_data
)
546 chunk_free(&this->notification_data
);
547 if (notification_data
.len
> 0)
549 this->notification_data
= chunk_clone(notification_data
);
551 compute_length(this);
556 * Implementation of notify_payload_t.destroy and notify_payload_t.destroy.
558 static status_t
destroy(private_notify_payload_t
*this)
560 chunk_free(&this->notification_data
);
561 chunk_free(&this->spi
);
567 * Described in header
569 notify_payload_t
*notify_payload_create()
571 private_notify_payload_t
*this = malloc_thing(private_notify_payload_t
);
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
;
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
;
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
;
602 this->notification_data
.ptr
= NULL
;
603 this->notification_data
.len
= 0;
605 return &this->public;
609 * Described in header.
611 notify_payload_t
*notify_payload_create_from_protocol_and_type(protocol_id_t protocol_id
, notify_type_t notify_type
)
613 notify_payload_t
*notify
= notify_payload_create();
615 notify
->set_notify_type(notify
,notify_type
);
616 notify
->set_protocol_id(notify
,protocol_id
);