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
, ERX_SUPPORTED
, 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",
113 ENUM_NEXT(notify_type_names
, INITIAL_CONTACT_IKEV1
, INITIAL_CONTACT_IKEV1
, ERX_SUPPORTED
,
115 ENUM_NEXT(notify_type_names
, DPD_R_U_THERE
, DPD_R_U_THERE_ACK
, INITIAL_CONTACT_IKEV1
,
117 "DPD_R_U_THERE_ACK");
118 ENUM_NEXT(notify_type_names
, UNITY_LOAD_BALANCE
, UNITY_LOAD_BALANCE
, DPD_R_U_THERE_ACK
,
119 "UNITY_LOAD_BALANCE");
120 ENUM_NEXT(notify_type_names
, USE_BEET_MODE
, USE_BEET_MODE
, UNITY_LOAD_BALANCE
,
122 ENUM_NEXT(notify_type_names
, ME_MEDIATION
, RADIUS_ATTRIBUTE
, USE_BEET_MODE
,
130 "RADIUS_ATTRIBUTE",);
131 ENUM_END(notify_type_names
, RADIUS_ATTRIBUTE
);
134 ENUM_BEGIN(notify_type_short_names
, UNSUPPORTED_CRITICAL_PAYLOAD
, UNSUPPORTED_CRITICAL_PAYLOAD
,
136 ENUM_NEXT(notify_type_short_names
, INVALID_IKE_SPI
, INVALID_MAJOR_VERSION
, UNSUPPORTED_CRITICAL_PAYLOAD
,
139 ENUM_NEXT(notify_type_short_names
, INVALID_SYNTAX
, INVALID_SYNTAX
, INVALID_MAJOR_VERSION
,
141 ENUM_NEXT(notify_type_short_names
, INVALID_MESSAGE_ID
, INVALID_MESSAGE_ID
, INVALID_SYNTAX
,
143 ENUM_NEXT(notify_type_short_names
, INVALID_SPI
, INVALID_SPI
, INVALID_MESSAGE_ID
,
145 ENUM_NEXT(notify_type_short_names
, ATTRIBUTES_NOT_SUPPORTED
, NO_PROPOSAL_CHOSEN
, INVALID_SPI
,
148 ENUM_NEXT(notify_type_short_names
, PAYLOAD_MALFORMED
, AUTHENTICATION_FAILED
, NO_PROPOSAL_CHOSEN
,
158 ENUM_NEXT(notify_type_short_names
, SINGLE_PAIR_REQUIRED
, CHILD_SA_NOT_FOUND
, AUTHENTICATION_FAILED
,
170 ENUM_NEXT(notify_type_short_names
, ME_CONNECT_FAILED
, ME_CONNECT_FAILED
, CHILD_SA_NOT_FOUND
,
172 ENUM_NEXT(notify_type_short_names
, MS_NOTIFY_STATUS
, MS_NOTIFY_STATUS
, ME_CONNECT_FAILED
,
174 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT
, ERX_SUPPORTED
, MS_NOTIFY_STATUS
,
219 ENUM_NEXT(notify_type_short_names
, INITIAL_CONTACT_IKEV1
, INITIAL_CONTACT_IKEV1
, ERX_SUPPORTED
,
221 ENUM_NEXT(notify_type_short_names
, DPD_R_U_THERE
, DPD_R_U_THERE_ACK
, INITIAL_CONTACT_IKEV1
,
224 ENUM_NEXT(notify_type_short_names
, UNITY_LOAD_BALANCE
, UNITY_LOAD_BALANCE
, DPD_R_U_THERE_ACK
,
226 ENUM_NEXT(notify_type_short_names
, USE_BEET_MODE
, USE_BEET_MODE
, UNITY_LOAD_BALANCE
,
228 ENUM_NEXT(notify_type_short_names
, ME_MEDIATION
, RADIUS_ATTRIBUTE
, USE_BEET_MODE
,
237 ENUM_END(notify_type_short_names
, RADIUS_ATTRIBUTE
);
240 typedef struct private_notify_payload_t private_notify_payload_t
;
243 * Private data of an notify_payload_t object.
245 struct private_notify_payload_t
{
248 * Public notify_payload_t interface.
250 notify_payload_t
public;
255 u_int8_t next_payload
;
268 * Length of this payload.
270 u_int16_t payload_length
;
273 * Domain of interpretation, IKEv1 only.
280 u_int8_t protocol_id
;
288 * Notify message type.
290 u_int16_t notify_type
;
293 * Security parameter index (spi).
303 * Type of payload, NOTIFY or NOTIFY_V1
309 * Encoding rules for an IKEv2 notification payload
311 static encoding_rule_t encodings_v2
[] = {
312 /* 1 Byte next payload type, stored in the field next_payload */
313 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
314 /* the critical bit */
315 { FLAG
, offsetof(private_notify_payload_t
, critical
) },
316 /* 7 Bit reserved bits, nowhere stored */
317 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[0]) },
318 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[1]) },
319 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[2]) },
320 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[3]) },
321 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[4]) },
322 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[5]) },
323 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[6]) },
324 /* Length of the whole payload*/
325 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
326 /* Protocol ID as 8 bit field*/
327 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
328 /* SPI Size as 8 bit field*/
329 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
330 /* Notify message type as 16 bit field*/
331 { U_INT_16
, offsetof(private_notify_payload_t
, notify_type
) },
332 /* SPI as variable length field*/
333 { SPI
, offsetof(private_notify_payload_t
, spi
) },
334 /* Key Exchange Data is from variable size */
335 { CHUNK_DATA
, offsetof(private_notify_payload_t
, notify_data
) },
340 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
341 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
342 ! Next Payload !C! RESERVED ! Payload Length !
343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
344 ! Protocol ID ! SPI Size ! Notify Message Type !
345 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
347 ~ Security Parameter Index (SPI) ~
349 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351 ~ Notification Data ~
353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
356 * Encoding rules for an IKEv1 notification payload
358 static encoding_rule_t encodings_v1
[] = {
359 /* 1 Byte next payload type, stored in the field next_payload */
360 { U_INT_8
, offsetof(private_notify_payload_t
, next_payload
) },
361 /* 8 reserved bits */
362 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[0]) },
363 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[1]) },
364 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[2]) },
365 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[3]) },
366 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[4]) },
367 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[5]) },
368 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[6]) },
369 { RESERVED_BIT
, offsetof(private_notify_payload_t
, reserved
[7]) },
370 /* Length of the whole payload*/
371 { PAYLOAD_LENGTH
, offsetof(private_notify_payload_t
, payload_length
) },
372 /* DOI as 32 bit field*/
373 { U_INT_32
, offsetof(private_notify_payload_t
, doi
) },
374 /* Protocol ID as 8 bit field*/
375 { U_INT_8
, offsetof(private_notify_payload_t
, protocol_id
) },
376 /* SPI Size as 8 bit field*/
377 { SPI_SIZE
, offsetof(private_notify_payload_t
, spi_size
) },
378 /* Notify message type as 16 bit field*/
379 { U_INT_16
, offsetof(private_notify_payload_t
, notify_type
) },
380 /* SPI as variable length field*/
381 { SPI
, offsetof(private_notify_payload_t
, spi
) },
382 /* Key Exchange Data is from variable size */
383 { CHUNK_DATA
, offsetof(private_notify_payload_t
, notify_data
) },
388 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
389 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390 ! Next Payload ! RESERVED ! Payload Length !
391 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
393 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394 ! Protocol ID ! SPI Size ! Notify Message Type !
395 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
397 ~ Security Parameter Index (SPI) ~
399 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
401 ~ Notification Data ~
403 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
407 METHOD(payload_t
, verify
, status_t
,
408 private_notify_payload_t
*this)
410 bool bad_length
= FALSE
;
412 switch (this->protocol_id
)
420 DBG1(DBG_ENC
, "Unknown protocol (%d)", this->protocol_id
);
424 switch (this->notify_type
)
426 case INVALID_KE_PAYLOAD
:
428 if (this->type
== NOTIFY
&& this->notify_data
.len
!= 2)
434 case NAT_DETECTION_SOURCE_IP
:
435 case NAT_DETECTION_DESTINATION_IP
:
438 if (this->notify_data
.len
!= HASH_SIZE_SHA1
)
445 case INVALID_MAJOR_VERSION
:
446 case NO_PROPOSAL_CHOSEN
:
448 if (this->type
== NOTIFY
&& this->notify_data
.len
!= 0)
454 case ADDITIONAL_IP4_ADDRESS
:
456 if (this->notify_data
.len
!= 4)
462 case ADDITIONAL_IP6_ADDRESS
:
464 if (this->notify_data
.len
!= 16)
472 if (this->notify_data
.len
!= 4)
478 case IPCOMP_SUPPORTED
:
480 if (this->notify_data
.len
!= 3)
487 if (this->notify_data
.len
!= 8 &&
488 this->notify_data
.len
!= 12 &&
489 this->notify_data
.len
!= 24)
495 if (this->notify_data
.len
< 4 ||
496 this->notify_data
.len
> 16)
502 if (this->notify_data
.len
< 16 ||
503 this->notify_data
.len
> 32)
509 case DPD_R_U_THERE_ACK
:
510 if (this->notify_data
.len
!= 4)
521 DBG1(DBG_ENC
, "invalid notify data length for %N (%d)",
522 notify_type_names
, this->notify_type
,
523 this->notify_data
.len
);
529 METHOD(payload_t
, get_encoding_rules
, int,
530 private_notify_payload_t
*this, encoding_rule_t
**rules
)
532 if (this->type
== NOTIFY
)
534 *rules
= encodings_v2
;
535 return countof(encodings_v2
);
537 *rules
= encodings_v1
;
538 return countof(encodings_v1
);
541 METHOD(payload_t
, get_header_length
, int,
542 private_notify_payload_t
*this)
544 if (this->type
== NOTIFY
)
546 return 8 + this->spi_size
;
548 return 12 + this->spi_size
;
551 METHOD(payload_t
, get_type
, payload_type_t
,
552 private_notify_payload_t
*this)
557 METHOD(payload_t
, get_next_type
, payload_type_t
,
558 private_notify_payload_t
*this)
560 return this->next_payload
;
563 METHOD(payload_t
, set_next_type
, void,
564 private_notify_payload_t
*this, payload_type_t type
)
566 this->next_payload
= type
;
570 * recompute the payloads length.
572 static void compute_length(private_notify_payload_t
*this)
574 this->payload_length
= get_header_length(this) + this->notify_data
.len
;
577 METHOD(payload_t
, get_length
, size_t,
578 private_notify_payload_t
*this)
580 return this->payload_length
;
583 METHOD(notify_payload_t
, get_protocol_id
, u_int8_t
,
584 private_notify_payload_t
*this)
586 return this->protocol_id
;
589 METHOD(notify_payload_t
, set_protocol_id
, void,
590 private_notify_payload_t
*this, u_int8_t protocol_id
)
592 this->protocol_id
= protocol_id
;
595 METHOD(notify_payload_t
, get_notify_type
, notify_type_t
,
596 private_notify_payload_t
*this)
598 return this->notify_type
;
601 METHOD(notify_payload_t
, set_notify_type
, void,
602 private_notify_payload_t
*this, notify_type_t notify_type
)
604 this->notify_type
= notify_type
;
607 METHOD(notify_payload_t
, get_spi
, u_int32_t
,
608 private_notify_payload_t
*this)
610 switch (this->protocol_id
)
614 if (this->spi
.len
== 4)
616 return *((u_int32_t
*)this->spi
.ptr
);
624 METHOD(notify_payload_t
, set_spi
, void,
625 private_notify_payload_t
*this, u_int32_t spi
)
627 chunk_free(&this->spi
);
628 switch (this->protocol_id
)
632 this->spi
= chunk_alloc(4);
633 *((u_int32_t
*)this->spi
.ptr
) = spi
;
638 this->spi_size
= this->spi
.len
;
639 compute_length(this);
642 METHOD(notify_payload_t
, get_spi_data
, chunk_t
,
643 private_notify_payload_t
*this)
645 switch (this->protocol_id
)
648 if (this->spi
.len
== 16)
658 METHOD(notify_payload_t
, set_spi_data
, void,
659 private_notify_payload_t
*this, chunk_t spi
)
661 chunk_free(&this->spi
);
662 switch (this->protocol_id
)
665 this->spi
= chunk_clone(spi
);
669 this->spi_size
= this->spi
.len
;
670 compute_length(this);
673 METHOD(notify_payload_t
, get_notification_data
, chunk_t
,
674 private_notify_payload_t
*this)
676 return this->notify_data
;
679 METHOD(notify_payload_t
, set_notification_data
, void,
680 private_notify_payload_t
*this, chunk_t data
)
682 free(this->notify_data
.ptr
);
683 this->notify_data
= chunk_clone(data
);
684 compute_length(this);
687 METHOD2(payload_t
, notify_payload_t
, destroy
, void,
688 private_notify_payload_t
*this)
690 free(this->notify_data
.ptr
);
696 * Described in header
698 notify_payload_t
*notify_payload_create(payload_type_t type
)
700 private_notify_payload_t
*this;
704 .payload_interface
= {
706 .get_encoding_rules
= _get_encoding_rules
,
707 .get_header_length
= _get_header_length
,
708 .get_length
= _get_length
,
709 .get_next_type
= _get_next_type
,
710 .set_next_type
= _set_next_type
,
711 .get_type
= _get_type
,
714 .get_protocol_id
= _get_protocol_id
,
715 .set_protocol_id
= _set_protocol_id
,
716 .get_notify_type
= _get_notify_type
,
717 .set_notify_type
= _set_notify_type
,
720 .get_spi_data
= _get_spi_data
,
721 .set_spi_data
= _set_spi_data
,
722 .get_notification_data
= _get_notification_data
,
723 .set_notification_data
= _set_notification_data
,
726 .doi
= IKEV1_DOI_IPSEC
,
727 .next_payload
= NO_PAYLOAD
,
730 compute_length(this);
731 return &this->public;
735 * Described in header.
737 notify_payload_t
*notify_payload_create_from_protocol_and_type(
738 payload_type_t type
, protocol_id_t protocol
, notify_type_t notify
)
740 notify_payload_t
*this = notify_payload_create(type
);
742 this->set_notify_type(this, notify
);
743 this->set_protocol_id(this, protocol
);