2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2006-2008 Tobias Brunner
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * Hochschule fuer Technik Rapperswil
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>.
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
22 #include "notify_payload.h"
25 #include <encoding/payloads/encodings.h>
26 #include <crypto/hashers/hasher.h>
28 ENUM_BEGIN(notify_type_names
, UNSUPPORTED_CRITICAL_PAYLOAD
, UNSUPPORTED_CRITICAL_PAYLOAD
,
29 "UNSUPPORTED_CRITICAL_PAYLOAD");
30 ENUM_NEXT(notify_type_names
, INVALID_IKE_SPI
, INVALID_MAJOR_VERSION
, UNSUPPORTED_CRITICAL_PAYLOAD
,
32 "INVALID_MAJOR_VERSION");
33 ENUM_NEXT(notify_type_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
35 ENUM_NEXT(notify_type_names
, INVALID_MESSAGE_ID
, INVALID_MESSAGE_ID
, INVALID_SYNTAX
,
36 "INVALID_MESSAGE_ID");
37 ENUM_NEXT(notify_type_names
, INVALID_SPI
, INVALID_SPI
, INVALID_MESSAGE_ID
,
39 ENUM_NEXT(notify_type_names
, ATTRIBUTES_NOT_SUPPORTED
, NO_PROPOSAL_CHOSEN
, INVALID_SPI
,
40 "ATTRIBUTES_NOT_SUPPORTED",
41 "NO_PROPOSAL_CHOSEN");
42 ENUM_NEXT(notify_type_names
, PAYLOAD_MALFORMED
, AUTHENTICATION_FAILED
, NO_PROPOSAL_CHOSEN
,
45 "INVALID_ID_INFORMATION",
46 "INVALID_CERT_ENCODING",
47 "INVALID_CERTIFICATE",
48 "CERT_TYPE_UNSUPPORTED",
49 "INVALID_CERT_AUTHORITY",
50 "INVALID_HASH_INFORMATION",
51 "AUTHENTICATION_FAILED");
52 ENUM_NEXT(notify_type_names
, SINGLE_PAIR_REQUIRED
, CHILD_SA_NOT_FOUND
, AUTHENTICATION_FAILED
,
53 "SINGLE_PAIR_REQUIRED",
55 "INTERNAL_ADDRESS_FAILURE",
59 "UNACCEPTABLE_ADDRESSES",
60 "UNEXPECTED_NAT_DETECTED",
63 "CHILD_SA_NOT_FOUND");
64 ENUM_NEXT(notify_type_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, CHILD_SA_NOT_FOUND
,
66 ENUM_NEXT(notify_type_names
, MS_NOTIFY_STATUS
, MS_NOTIFY_STATUS
, ME_CONNECT_FAILED
,
68 ENUM_NEXT(notify_type_names
, INITIAL_CONTACT
, PSK_CONFIRM
, MS_NOTIFY_STATUS
,
71 "ADDITIONAL_TS_POSSIBLE",
73 "NAT_DETECTION_SOURCE_IP",
74 "NAT_DETECTION_DESTINATION_IP",
77 "HTTP_CERT_LOOKUP_SUPPORTED",
79 "ESP_TFC_PADDING_NOT_SUPPORTED",
80 "NON_FIRST_FRAGMENTS_ALSO",
82 "ADDITIONAL_IP4_ADDRESS",
83 "ADDITIONAL_IP6_ADDRESS",
84 "NO_ADDITIONAL_ADDRESSES",
85 "UPDATE_SA_ADDRESSES",
89 "MULTIPLE_AUTH_SUPPORTED",
90 "ANOTHER_AUTH_FOLLOWS",
102 "EAP_ONLY_AUTHENTICATION",
103 "CHILDLESS_IKEV2_SUPPORTED",
104 "QUICK_CRASH_DETECTION",
105 "IKEV2_MESSAGE_ID_SYNC_SUPPORTED",
106 "IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
107 "IKEV2_MESSAGE_ID_SYNC",
108 "IPSEC_REPLAY_COUNTER_SYNC",
109 "SECURE PASSWORD_METHOD",
112 ENUM_NEXT(notify_type_names
, INITIAL_CONTACT_IKEV1
, INITIAL_CONTACT_IKEV1
, PSK_CONFIRM
,
114 ENUM_NEXT(notify_type_names
, DPD_R_U_THERE
, DPD_R_U_THERE_ACK
, INITIAL_CONTACT_IKEV1
,
116 "DPD_R_U_THERE_ACK");
117 ENUM_NEXT(notify_type_names
, UNITY_LOAD_BALANCE
, UNITY_LOAD_BALANCE
, DPD_R_U_THERE_ACK
,
118 "UNITY_LOAD_BALANCE");
119 ENUM_NEXT(notify_type_names
, USE_BEET_MODE
, USE_BEET_MODE
, UNITY_LOAD_BALANCE
,
121 ENUM_NEXT(notify_type_names
, ME_MEDIATION
, RADIUS_ATTRIBUTE
, USE_BEET_MODE
,
129 "RADIUS_ATTRIBUTE",);
130 ENUM_END(notify_type_names
, RADIUS_ATTRIBUTE
);
133 ENUM_BEGIN(notify_type_short_names
, UNSUPPORTED_CRITICAL_PAYLOAD
, UNSUPPORTED_CRITICAL_PAYLOAD
,
135 ENUM_NEXT(notify_type_short_names
, INVALID_IKE_SPI
, INVALID_MAJOR_VERSION
, UNSUPPORTED_CRITICAL_PAYLOAD
,
138 ENUM_NEXT(notify_type_short_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
140 ENUM_NEXT(notify_type_short_names
, INVALID_MESSAGE_ID
, INVALID_MESSAGE_ID
, INVALID_SYNTAX
,
142 ENUM_NEXT(notify_type_short_names
, INVALID_SPI
, INVALID_SPI
, INVALID_MESSAGE_ID
,
144 ENUM_NEXT(notify_type_short_names
, ATTRIBUTES_NOT_SUPPORTED
, NO_PROPOSAL_CHOSEN
, INVALID_SPI
,
147 ENUM_NEXT(notify_type_short_names
, PAYLOAD_MALFORMED
, AUTHENTICATION_FAILED
, NO_PROPOSAL_CHOSEN
,
157 ENUM_NEXT(notify_type_short_names
, SINGLE_PAIR_REQUIRED
, CHILD_SA_NOT_FOUND
, AUTHENTICATION_FAILED
,
169 ENUM_NEXT(notify_type_short_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, CHILD_SA_NOT_FOUND
,
171 ENUM_NEXT(notify_type_short_names
, MS_NOTIFY_STATUS
, MS_NOTIFY_STATUS
, ME_CONNECT_FAILED
,
173 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT
, PSK_CONFIRM
, MS_NOTIFY_STATUS
,
217 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT_IKEV1
, INITIAL_CONTACT_IKEV1
, PSK_CONFIRM
,
219 ENUM_NEXT(notify_type_short_names
, DPD_R_U_THERE
, DPD_R_U_THERE_ACK
, INITIAL_CONTACT_IKEV1
,
222 ENUM_NEXT(notify_type_short_names
, UNITY_LOAD_BALANCE
, UNITY_LOAD_BALANCE
, DPD_R_U_THERE_ACK
,
224 ENUM_NEXT(notify_type_short_names
, USE_BEET_MODE
, USE_BEET_MODE
, UNITY_LOAD_BALANCE
,
226 ENUM_NEXT(notify_type_short_names
, ME_MEDIATION
, RADIUS_ATTRIBUTE
, USE_BEET_MODE
,
235 ENUM_END(notify_type_short_names
, RADIUS_ATTRIBUTE
);
238 typedef struct private_notify_payload_t private_notify_payload_t
;
241 * Private data of an notify_payload_t object.
243 struct private_notify_payload_t
{
246 * Public notify_payload_t interface.
248 notify_payload_t
public;
253 u_int8_t next_payload
;
266 * Length of this payload.
268 u_int16_t payload_length
;
271 * Domain of interpretation, IKEv1 only.
278 u_int8_t protocol_id
;
286 * Notify message type.
288 u_int16_t notify_type
;
291 * Security parameter index (spi).
301 * Type of payload, NOTIFY or NOTIFY_V1
307 * Encoding rules for an IKEv2 notification payload
309 static encoding_rule_t encodings_v2
[] = {
310 /* 1 Byte next payload type, stored in the field next_payload */
311 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
312 /* the critical bit */
313 { FLAG
, offsetof(private_notify_payload_t
, critical
) },
314 /* 7 Bit reserved bits, nowhere stored */
315 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[0]) },
316 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[1]) },
317 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[2]) },
318 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[3]) },
319 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[4]) },
320 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[5]) },
321 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[6]) },
322 /* Length of the whole payload*/
323 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
324 /* Protocol ID as 8 bit field*/
325 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
326 /* SPI Size as 8 bit field*/
327 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
328 /* Notify message type as 16 bit field*/
329 { U_INT_16
, offsetof(private_notify_payload_t
, notify_type
) },
330 /* SPI as variable length field*/
331 { SPI
, offsetof(private_notify_payload_t
, spi
) },
332 /* Key Exchange Data is from variable size */
333 { CHUNK_DATA
, offsetof(private_notify_payload_t
, notify_data
) },
338 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
339 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
340 ! Next Payload !C! RESERVED ! Payload Length !
341 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
342 ! Protocol ID ! SPI Size ! Notify Message Type !
343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
345 ~ Security Parameter Index (SPI) ~
347 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
349 ~ Notification Data ~
351 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
354 * Encoding rules for an IKEv1 notification payload
356 static encoding_rule_t encodings_v1
[] = {
357 /* 1 Byte next payload type, stored in the field next_payload */
358 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
359 /* 8 reserved bits */
360 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[0]) },
361 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[1]) },
362 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[2]) },
363 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[3]) },
364 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[4]) },
365 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[5]) },
366 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[6]) },
367 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[7]) },
368 /* Length of the whole payload*/
369 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
370 /* DOI as 32 bit field*/
371 { U_INT_32
, offsetof(private_notify_payload_t
, doi
) },
372 /* Protocol ID as 8 bit field*/
373 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
374 /* SPI Size as 8 bit field*/
375 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
376 /* Notify message type as 16 bit field*/
377 { U_INT_16
, offsetof(private_notify_payload_t
, notify_type
) },
378 /* SPI as variable length field*/
379 { SPI
, offsetof(private_notify_payload_t
, spi
) },
380 /* Key Exchange Data is from variable size */
381 { CHUNK_DATA
, offsetof(private_notify_payload_t
, notify_data
) },
386 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
387 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
388 ! Next Payload ! RESERVED ! Payload Length !
389 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392 ! Protocol ID ! SPI Size ! Notify Message Type !
393 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
395 ~ Security Parameter Index (SPI) ~
397 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
399 ~ Notification Data ~
401 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
405 METHOD(payload_t
, verify
, status_t
,
406 private_notify_payload_t
*this)
408 bool bad_length
= FALSE
;
410 switch (this->protocol_id
)
418 DBG1(DBG_ENC
, "Unknown protocol (%d)", this->protocol_id
);
422 switch (this->notify_type
)
424 case INVALID_KE_PAYLOAD
:
426 if (this->type
== NOTIFY
&& this->notify_data
.len
!= 2)
432 case NAT_DETECTION_SOURCE_IP
:
433 case NAT_DETECTION_DESTINATION_IP
:
436 if (this->notify_data
.len
!= HASH_SIZE_SHA1
)
443 case INVALID_MAJOR_VERSION
:
444 case NO_PROPOSAL_CHOSEN
:
446 if (this->type
== NOTIFY
&& this->notify_data
.len
!= 0)
452 case ADDITIONAL_IP4_ADDRESS
:
454 if (this->notify_data
.len
!= 4)
460 case ADDITIONAL_IP6_ADDRESS
:
462 if (this->notify_data
.len
!= 16)
470 if (this->notify_data
.len
!= 4)
476 case IPCOMP_SUPPORTED
:
478 if (this->notify_data
.len
!= 3)
485 if (this->notify_data
.len
!= 8 &&
486 this->notify_data
.len
!= 12 &&
487 this->notify_data
.len
!= 24)
493 if (this->notify_data
.len
< 4 ||
494 this->notify_data
.len
> 16)
500 if (this->notify_data
.len
< 16 ||
501 this->notify_data
.len
> 32)
507 case DPD_R_U_THERE_ACK
:
508 if (this->notify_data
.len
!= 4)
519 DBG1(DBG_ENC
, "invalid notify data length for %N (%d)",
520 notify_type_names
, this->notify_type
,
521 this->notify_data
.len
);
527 METHOD(payload_t
, get_encoding_rules
, int,
528 private_notify_payload_t
*this, encoding_rule_t
**rules
)
530 if (this->type
== NOTIFY
)
532 *rules
= encodings_v2
;
533 return countof(encodings_v2
);
535 *rules
= encodings_v1
;
536 return countof(encodings_v1
);
539 METHOD(payload_t
, get_header_length
, int,
540 private_notify_payload_t
*this)
542 if (this->type
== NOTIFY
)
544 return 8 + this->spi_size
;
546 return 12 + this->spi_size
;
549 METHOD(payload_t
, get_type
, payload_type_t
,
550 private_notify_payload_t
*this)
555 METHOD(payload_t
, get_next_type
, payload_type_t
,
556 private_notify_payload_t
*this)
558 return this->next_payload
;
561 METHOD(payload_t
, set_next_type
, void,
562 private_notify_payload_t
*this, payload_type_t type
)
564 this->next_payload
= type
;
568 * recompute the payloads length.
570 static void compute_length(private_notify_payload_t
*this)
572 this->payload_length
= get_header_length(this) + this->notify_data
.len
;
575 METHOD(payload_t
, get_length
, size_t,
576 private_notify_payload_t
*this)
578 return this->payload_length
;
581 METHOD(notify_payload_t
, get_protocol_id
, u_int8_t
,
582 private_notify_payload_t
*this)
584 return this->protocol_id
;
587 METHOD(notify_payload_t
, set_protocol_id
, void,
588 private_notify_payload_t
*this, u_int8_t protocol_id
)
590 this->protocol_id
= protocol_id
;
593 METHOD(notify_payload_t
, get_notify_type
, notify_type_t
,
594 private_notify_payload_t
*this)
596 return this->notify_type
;
599 METHOD(notify_payload_t
, set_notify_type
, void,
600 private_notify_payload_t
*this, notify_type_t notify_type
)
602 this->notify_type
= notify_type
;
605 METHOD(notify_payload_t
, get_spi
, u_int32_t
,
606 private_notify_payload_t
*this)
608 switch (this->protocol_id
)
612 if (this->spi
.len
== 4)
614 return *((u_int32_t
*)this->spi
.ptr
);
622 METHOD(notify_payload_t
, set_spi
, void,
623 private_notify_payload_t
*this, u_int32_t spi
)
625 chunk_free(&this->spi
);
626 switch (this->protocol_id
)
630 this->spi
= chunk_alloc(4);
631 *((u_int32_t
*)this->spi
.ptr
) = spi
;
636 this->spi_size
= this->spi
.len
;
637 compute_length(this);
640 METHOD(notify_payload_t
, get_spi_data
, chunk_t
,
641 private_notify_payload_t
*this)
643 switch (this->protocol_id
)
646 if (this->spi
.len
== 16)
656 METHOD(notify_payload_t
, set_spi_data
, void,
657 private_notify_payload_t
*this, chunk_t spi
)
659 chunk_free(&this->spi
);
660 switch (this->protocol_id
)
663 this->spi
= chunk_clone(spi
);
667 this->spi_size
= this->spi
.len
;
668 compute_length(this);
671 METHOD(notify_payload_t
, get_notification_data
, chunk_t
,
672 private_notify_payload_t
*this)
674 return this->notify_data
;
677 METHOD(notify_payload_t
, set_notification_data
, void,
678 private_notify_payload_t
*this, chunk_t data
)
680 free(this->notify_data
.ptr
);
681 this->notify_data
= chunk_clone(data
);
682 compute_length(this);
685 METHOD2(payload_t
, notify_payload_t
, destroy
, void,
686 private_notify_payload_t
*this)
688 free(this->notify_data
.ptr
);
694 * Described in header
696 notify_payload_t
*notify_payload_create(payload_type_t type
)
698 private_notify_payload_t
*this;
702 .payload_interface
= {
704 .get_encoding_rules
= _get_encoding_rules
,
705 .get_header_length
= _get_header_length
,
706 .get_length
= _get_length
,
707 .get_next_type
= _get_next_type
,
708 .set_next_type
= _set_next_type
,
709 .get_type
= _get_type
,
712 .get_protocol_id
= _get_protocol_id
,
713 .set_protocol_id
= _set_protocol_id
,
714 .get_notify_type
= _get_notify_type
,
715 .set_notify_type
= _set_notify_type
,
718 .get_spi_data
= _get_spi_data
,
719 .set_spi_data
= _set_spi_data
,
720 .get_notification_data
= _get_notification_data
,
721 .set_notification_data
= _set_notification_data
,
724 .doi
= IKEV1_DOI_IPSEC
,
725 .next_payload
= NO_PAYLOAD
,
728 compute_length(this);
729 return &this->public;
733 * Described in header.
735 notify_payload_t
*notify_payload_create_from_protocol_and_type(
736 payload_type_t type
, protocol_id_t protocol
, notify_type_t notify
)
738 notify_payload_t
*this = notify_payload_create(type
);
740 this->set_notify_type(this, notify
);
741 this->set_protocol_id(this, protocol
);