4 * @brief Class message_t. Object of this type represents an IKEv2-Message.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 #include "ike_sa_id.h"
30 #include "generator.h"
31 #include "utils/linked_list.h"
32 #include "utils/allocator.h"
33 #include "utils/logger_manager.h"
34 #include "payloads/encodings.h"
35 #include "payloads/payload.h"
40 * Supported payload entry used in message_rule_t
43 typedef struct supported_payload_entry_s supported_payload_entry_t
;
45 struct supported_payload_entry_s
{
49 payload_type_t payload_type
;
52 * Minimal occurence of this payload
57 * Max occurence of this payload
63 * Message Rule used to find out which payloads are supported by each message type
66 typedef struct message_rule_s message_rule_t
;
68 struct message_rule_s
{
72 exchange_type_t exchange_type
;
75 * Is message a request or response
79 * Number of supported payloads
81 size_t supported_payloads_count
;
83 * Pointer to first supported payload entry
85 supported_payload_entry_t
*supported_payloads
;
89 * message rule for ike_sa_init from initiator
91 static supported_payload_entry_t supported_ike_sa_init_i_payloads
[] =
93 {SECURITY_ASSOCIATION
,1,1},
99 * message rule for ike_sa_init from responder
101 static supported_payload_entry_t supported_ike_sa_init_r_payloads
[] =
103 {SECURITY_ASSOCIATION
,1,1},
110 * message rules, defines allowed payloads
112 static message_rule_t message_rules
[] = {
113 {IKE_SA_INIT
,TRUE
,(sizeof(supported_ike_sa_init_i_payloads
)/sizeof(supported_payload_entry_t
)),supported_ike_sa_init_i_payloads
},
114 {IKE_SA_INIT
,FALSE
,(sizeof(supported_ike_sa_init_r_payloads
)/sizeof(supported_payload_entry_t
)),supported_ike_sa_init_r_payloads
}
118 * Entry for a payload in the internal used linked list
121 typedef struct payload_entry_s payload_entry_t
;
123 struct payload_entry_s
{
127 payload_type_t payload_type
;
129 * Data struct holding the data of given payload
136 * Private data of an message_t object
138 typedef struct private_message_s private_message_t
;
140 struct private_message_s
{
143 * Public part of a message_t object
149 * Minor version of message
151 u_int8_t major_version
;
154 * Major version of message
156 u_int8_t minor_version
;
159 * First Payload in message
161 payload_type_t first_payload
;
164 * Assigned exchange type
166 exchange_type_t exchange_type
;
170 * TRUE if message is request.
171 * FALSE if message is reply.
176 * Message ID of this message
178 u_int32_t message_id
;
181 * ID of assigned IKE_SA
183 ike_sa_id_t
*ike_sa_id
;
186 * Assigned UDP packet.
188 * Stores incoming packet or last generated one.
193 * Linked List where payload data are stored in
195 linked_list_t
*payloads
;
198 * Assigned parser to parse Header and Body of this message
203 * logger for this message
208 * Gets a list of supported payloads of this message type
210 * @param this calling object
211 * @param[out] supported_payloads first entry of supported payloads
212 * @param[out] supported_payloads_count number of supported payload entries
215 * NOT_FOUND if no supported payload definition could be found
217 status_t (*get_supported_payloads
) (private_message_t
*this, supported_payload_entry_t
**supported_payloads
,size_t *supported_payloads_count
);
222 * Implements private_message_t's get_supported_payloads function.
223 * See #private_message_t.get_supported_payloads.
225 status_t
get_supported_payloads (private_message_t
*this, supported_payload_entry_t
**supported_payloads
,size_t *supported_payloads_count
)
228 exchange_type_t exchange_type
= this->public.get_exchange_type(&(this->public));
229 bool is_request
= this->public.get_request(&(this->public));
232 for (i
= 0; i
< (sizeof(message_rules
) / sizeof(message_rule_t
)); i
++)
234 if ((exchange_type
== message_rules
[i
].exchange_type
) &&
235 (is_request
== message_rules
[i
].is_request
))
237 /* found rule for given exchange_type*/
238 *supported_payloads
= message_rules
[i
].supported_payloads
;
239 *supported_payloads_count
= message_rules
[i
].supported_payloads_count
;
246 *supported_payloads
= NULL
;
247 *supported_payloads_count
= 0;
252 * Implements message_t's set_ike_sa_id function.
253 * See #message_s.set_ike_sa_id.
255 static status_t
set_ike_sa_id (private_message_t
*this,ike_sa_id_t
*ike_sa_id
)
258 status
= ike_sa_id
->clone(ike_sa_id
,&(this->ike_sa_id
));
263 * Implements message_t's get_ike_sa_id function.
264 * See #message_s.get_ike_sa_id.
266 static status_t
get_ike_sa_id (private_message_t
*this,ike_sa_id_t
**ike_sa_id
)
269 if (this->ike_sa_id
== NULL
)
273 status
= this->ike_sa_id
->clone(this->ike_sa_id
,ike_sa_id
);
279 * Implements message_t's set_message_id function.
280 * See #message_s.set_message_id.
282 static status_t
set_message_id (private_message_t
*this,u_int32_t message_id
)
284 this->message_id
= message_id
;
290 * Implements message_t's set_message_id function.
291 * See #message_s.set_message_id.
293 static u_int32_t
get_message_id (private_message_t
*this)
295 return this->message_id
;
299 * Implements message_t's set_major_version function.
300 * See #message_s.set_major_version.
302 static status_t
set_major_version (private_message_t
*this,u_int8_t major_version
)
304 this->major_version
= major_version
;
310 * Implements message_t's get_major_version function.
311 * See #message_s.get_major_version.
313 static u_int8_t
get_major_version (private_message_t
*this)
315 return this->major_version
;
319 * Implements message_t's set_minor_version function.
320 * See #message_s.set_minor_version.
322 static status_t
set_minor_version (private_message_t
*this,u_int8_t minor_version
)
324 this->minor_version
= minor_version
;
330 * Implements message_t's get_minor_version function.
331 * See #message_s.get_minor_version.
333 static u_int8_t
get_minor_version (private_message_t
*this)
335 return this->minor_version
;
339 * Implements message_t's set_exchange_type function.
340 * See #message_s.set_exchange_type.
342 static status_t
set_exchange_type (private_message_t
*this,exchange_type_t exchange_type
)
344 this->exchange_type
= exchange_type
;
350 * Implements message_t's get_exchange_type function.
351 * See #message_s.get_exchange_type.
353 static exchange_type_t
get_exchange_type (private_message_t
*this)
355 return this->exchange_type
;
360 * Implements message_t's set_request function.
361 * See #message_s.set_request.
363 static status_t
set_request (private_message_t
*this,bool request
)
365 this->is_request
= request
;
370 * Implements message_t's get_request function.
371 * See #message_s.get_request.
373 static exchange_type_t
get_request (private_message_t
*this)
375 return this->is_request
;
378 static status_t
add_payload(private_message_t
*this, payload_t
*payload
)
380 payload_t
*last_payload
;
381 if ((this->payloads
->get_count(this->payloads
) > 0) &&
382 (this->payloads
->get_last(this->payloads
,(void **) &last_payload
) != SUCCESS
))
387 if (this->payloads
->insert_last(this->payloads
, payload
) != SUCCESS
)
391 if (this->payloads
->get_count(this->payloads
) == 1)
393 this->first_payload
= payload
->get_type(payload
);
397 last_payload
->set_next_type(last_payload
,payload
->get_type(payload
));
400 this->logger
->log(this->logger
, CONTROL
|MORE
, "added payload of type %s to message",
401 mapping_find(payload_type_m
, payload
->get_type(payload
)));
406 static status_t
set_source(private_message_t
*this, host_t
*host
)
408 if (this->packet
->source
!= NULL
)
410 this->packet
->source
->destroy(this->packet
->source
);
412 this->packet
->source
= host
;
416 static status_t
set_destination(private_message_t
*this, host_t
*host
)
418 if (this->packet
->destination
!= NULL
)
420 this->packet
->destination
->destroy(this->packet
->destination
);
422 this->packet
->destination
= host
;
426 static status_t
get_source(private_message_t
*this, host_t
**host
)
428 *host
= this->packet
->source
;
432 static status_t
get_destination(private_message_t
*this, host_t
**host
)
434 *host
= this->packet
->destination
;
439 static status_t
get_payload_iterator(private_message_t
*this, linked_list_iterator_t
**iterator
)
441 return this->payloads
->create_iterator(this->payloads
, iterator
, TRUE
);
446 * Implements message_t's generate function.
447 * See #message_s.generate.
449 static status_t
generate(private_message_t
*this, packet_t
**packet
)
451 generator_t
*generator
;
452 ike_header_t
*ike_header
;
453 payload_t
*payload
, *next_payload
;
454 linked_list_iterator_t
*iterator
;
458 this->logger
->log(this->logger
, CONTROL
, "generating message, contains %d payloads",
459 this->payloads
->get_count(this->payloads
));
461 if (this->exchange_type
== EXCHANGE_TYPE_UNDEFINED
)
463 this->logger
->log(this->logger
, ERROR
, "exchange type is not defined");
464 return INVALID_STATE
;
467 if (this->packet
->source
== NULL
||
468 this->packet
->destination
== NULL
)
470 this->logger
->log(this->logger
, ERROR
, "source/destination not defined");
471 return INVALID_STATE
;
475 ike_header
= ike_header_create();
476 if (ike_header
== NULL
)
482 ike_header
->set_exchange_type(ike_header
, this->exchange_type
);
483 ike_header
->set_message_id(ike_header
, this->message_id
);
484 ike_header
->set_response_flag(ike_header
, !this->is_request
);
485 ike_header
->set_initiator_flag(ike_header
, this->ike_sa_id
->is_initiator(this->ike_sa_id
));
486 ike_header
->set_initiator_spi(ike_header
, this->ike_sa_id
->get_initiator_spi(this->ike_sa_id
));
487 ike_header
->set_responder_spi(ike_header
, this->ike_sa_id
->get_responder_spi(this->ike_sa_id
));
489 generator
= generator_create();
490 if (generator
== NULL
)
495 payload
= (payload_t
*)ike_header
;
497 if (this->payloads
->create_iterator(this->payloads
, &iterator
, TRUE
) != SUCCESS
)
499 generator
->destroy(generator
);
500 ike_header
->destroy(ike_header
);
503 while(iterator
->has_next(iterator
))
505 iterator
->current(iterator
, (void**)&next_payload
);
506 payload
->set_next_type(payload
, next_payload
->get_type(next_payload
));
507 status
= generator
->generate_payload(generator
, payload
);
508 if (status
!= SUCCESS
)
510 generator
->destroy(generator
);
511 ike_header
->destroy(ike_header
);
514 payload
= next_payload
;
516 iterator
->destroy(iterator
);
518 payload
->set_next_type(payload
, NO_PAYLOAD
);
519 status
= generator
->generate_payload(generator
, payload
);
520 if (status
!= SUCCESS
)
522 generator
->destroy(generator
);
523 ike_header
->destroy(ike_header
);
527 ike_header
->destroy(ike_header
);
531 if (this->packet
->data
.ptr
!= NULL
)
533 allocator_free(this->packet
->data
.ptr
);
536 status
= generator
->write_to_chunk(generator
, &(this->packet
->data
));
537 if (status
!= SUCCESS
)
539 generator
->destroy(generator
);
543 this->packet
->clone(this->packet
, packet
);
545 generator
->destroy(generator
);
548 this->logger
->log(this->logger
, CONTROL
, "message generated successfully");
553 * Implements message_t's parse_header function.
554 * See #message_s.parse_header.
556 static status_t
parse_header(private_message_t
*this)
558 ike_header_t
*ike_header
;
562 this->logger
->log(this->logger
, CONTROL
, "parsing header of message");
564 this->parser
->reset_context(this->parser
);
565 status
= this->parser
->parse_payload(this->parser
,HEADER
,(payload_t
**) &ike_header
);
566 if (status
!= SUCCESS
)
568 this->logger
->log(this->logger
, ERROR
, "Header could not be parsed");
574 status
= ike_header
->payload_interface
.verify(&(ike_header
->payload_interface
));
575 if (status
!= SUCCESS
)
577 this->logger
->log(this->logger
, ERROR
, "Header verification failed");
578 ike_header
->destroy(ike_header
);
582 if (this->ike_sa_id
!= NULL
)
584 this->ike_sa_id
->destroy(this->ike_sa_id
);
587 this->ike_sa_id
= ike_sa_id_create(ike_header
->get_initiator_spi(ike_header
),
588 ike_header
->get_responder_spi(ike_header
),
589 ike_header
->get_initiator_flag(ike_header
));
590 if (this->ike_sa_id
== NULL
)
592 this->logger
->log(this->logger
, ERROR
, "could not create ike_sa_id object");
593 ike_header
->destroy(ike_header
);
596 this->exchange_type
= ike_header
->get_exchange_type(ike_header
);
597 this->message_id
= ike_header
->get_message_id(ike_header
);
598 this->is_request
= (!(ike_header
->get_response_flag(ike_header
)));
599 this->major_version
= ike_header
->get_maj_version(ike_header
);
600 this->minor_version
= ike_header
->get_min_version(ike_header
);
601 this->first_payload
= ike_header
->payload_interface
.get_next_type(&(ike_header
->payload_interface
));
604 this->logger
->log(this->logger
, CONTROL
, "parsing header successfully");
606 ike_header
->destroy(ike_header
);
611 * Implements message_t's parse_body function.
612 * See #message_s.parse_body.
614 static status_t
parse_body (private_message_t
*this)
616 status_t status
= SUCCESS
;
618 payload_type_t current_payload_type
= this->first_payload
;
619 supported_payload_entry_t
*supported_payloads
;
620 size_t supported_payloads_count
;
623 this->logger
->log(this->logger
, CONTROL
, "parsing body of message");
625 if (this->get_supported_payloads (this, &supported_payloads
, &supported_payloads_count
) != SUCCESS
)
627 this->logger
->log(this->logger
, ERROR
, "could not get supported payloads");
631 while (current_payload_type
!= NO_PAYLOAD
)
633 payload_t
*current_payload
;
634 bool supported
= FALSE
;
636 this->logger
->log(this->logger
, CONTROL
|MORE
, "start parsing payload of type %s",
637 mapping_find(payload_type_m
, current_payload_type
));
638 for (i
= 0; i
< supported_payloads_count
;i
++)
640 if (supported_payloads
[i
].payload_type
== current_payload_type
)
646 if (!supported
&& (current_payload_type
!= NO_PAYLOAD
))
648 /* type not supported */
649 status
= NOT_SUPPORTED
;
650 this->logger
->log(this->logger
, ERROR
, "payload type %s not supported",mapping_find(payload_type_m
,current_payload_type
));
654 status
= this->parser
->parse_payload(this->parser
,current_payload_type
,(payload_t
**) ¤t_payload
);
655 if (status
!= SUCCESS
)
657 this->logger
->log(this->logger
, ERROR
, "payload type %s could not be parsed",mapping_find(payload_type_m
,current_payload_type
));
661 status
= current_payload
->verify(current_payload
);
662 if (status
!= SUCCESS
)
664 this->logger
->log(this->logger
, ERROR
, "payload type %s could not be verified",mapping_find(payload_type_m
,current_payload_type
));
665 status
= VERIFY_ERROR
;
669 /* get next payload type */
670 current_payload_type
= current_payload
->get_next_type(current_payload
);
672 status
= this->payloads
->insert_last(this->payloads
,current_payload
);
673 if (status
!= SUCCESS
)
675 this->logger
->log(this->logger
, ERROR
, "Could not insert current payload to internal list cause of ressource exhausting");
680 if (status
!= SUCCESS
)
682 /* already parsed payload is destroyed later in destroy call from outside this object */
686 linked_list_iterator_t
*iterator
;
688 status
= this->payloads
->create_iterator(this->payloads
,&iterator
,TRUE
);
689 if (status
!= SUCCESS
)
691 this->logger
->log(this->logger
, ERROR
, "Could not create iterator to check supported payloads");
695 /* check for payloads with wrong count*/
696 for (i
= 0; i
< supported_payloads_count
;i
++)
698 size_t min_occurence
= supported_payloads
[i
].min_occurence
;
699 size_t max_occurence
= supported_payloads
[i
].max_occurence
;
700 payload_type_t payload_type
= supported_payloads
[i
].payload_type
;
701 size_t found_payloads
= 0;
703 iterator
->reset(iterator
);
705 while(iterator
->has_next(iterator
))
707 payload_t
*current_payload
;
708 status
= iterator
->current(iterator
,(void **)¤t_payload
);
709 if (status
!= SUCCESS
)
711 this->logger
->log(this->logger
, ERROR
, "Could not get payload from internal list");
712 iterator
->destroy(iterator
);
715 if (current_payload
->get_type(current_payload
) == payload_type
)
718 if (found_payloads
> max_occurence
)
720 this->logger
->log(this->logger
, ERROR
, "Payload of type %s more than %d times (%d) occured in current message",
721 mapping_find(payload_type_m
,current_payload
->get_type(current_payload
)),max_occurence
,found_payloads
);
722 iterator
->destroy(iterator
);
723 return NOT_SUPPORTED
;
728 if (found_payloads
< min_occurence
)
730 this->logger
->log(this->logger
, ERROR
, "Payload of type %s not occured %d times",
731 mapping_find(payload_type_m
,payload_type
),min_occurence
);
732 iterator
->destroy(iterator
);
733 return NOT_SUPPORTED
;
737 iterator
->destroy(iterator
);
745 * Implements message_t's destroy function.
746 * See #message_s.destroy.
748 static status_t
destroy (private_message_t
*this)
750 linked_list_iterator_t
*iterator
;
752 this->packet
->destroy(this->packet
);
754 if (this->ike_sa_id
!= NULL
)
756 this->ike_sa_id
->destroy(this->ike_sa_id
);
759 this->payloads
->create_iterator(this->payloads
, &iterator
, TRUE
);
760 while (iterator
->has_next(iterator
))
763 iterator
->current(iterator
, (void**)&payload
);
764 this->logger
->log(this->logger
, CONTROL
|MOST
, "Destroying payload of type %s",
765 mapping_find(payload_type_m
, payload
->get_type(payload
)));
766 payload
->destroy(payload
);
768 iterator
->destroy(iterator
);
769 this->payloads
->destroy(this->payloads
);
770 this->parser
->destroy(this->parser
);
771 global_logger_manager
->destroy_logger(global_logger_manager
, this->logger
);
773 allocator_free(this);
778 * Described in Header-File
780 message_t
*message_create_from_packet(packet_t
*packet
)
782 private_message_t
*this = allocator_alloc_thing(private_message_t
);
788 /* public functions */
789 this->public.set_major_version
= (status_t(*)(message_t
*, u_int8_t
))set_major_version
;
790 this->public.get_major_version
= (u_int8_t(*)(message_t
*))get_major_version
;
791 this->public.set_minor_version
= (status_t(*)(message_t
*, u_int8_t
))set_minor_version
;
792 this->public.get_minor_version
= (u_int8_t(*)(message_t
*))get_minor_version
;
793 this->public.set_message_id
= (status_t(*)(message_t
*, u_int32_t
))set_message_id
;
794 this->public.get_message_id
= (u_int32_t(*)(message_t
*))get_message_id
;
795 this->public.set_ike_sa_id
= (status_t(*)(message_t
*, ike_sa_id_t
*))set_ike_sa_id
;
796 this->public.get_ike_sa_id
= (status_t(*)(message_t
*, ike_sa_id_t
**))get_ike_sa_id
;
797 this->public.set_exchange_type
= (status_t(*)(message_t
*, exchange_type_t
))set_exchange_type
;
798 this->public.get_exchange_type
= (exchange_type_t(*)(message_t
*))get_exchange_type
;
799 this->public.set_request
= (status_t(*)(message_t
*, bool))set_request
;
800 this->public.get_request
= (bool(*)(message_t
*))get_request
;
801 this->public.add_payload
= (status_t(*)(message_t
*,payload_t
*))add_payload
;
802 this->public.generate
= (status_t (*) (message_t
*, packet_t
**)) generate
;
803 this->public.set_source
= (status_t (*) (message_t
*,host_t
*)) set_source
;
804 this->public.get_source
= (status_t (*) (message_t
*,host_t
**)) get_source
;
805 this->public.set_destination
= (status_t (*) (message_t
*,host_t
*)) set_destination
;
806 this->public.get_destination
= (status_t (*) (message_t
*,host_t
**)) get_destination
;
807 this->public.get_payload_iterator
= (status_t (*) (message_t
*, linked_list_iterator_t
**)) get_payload_iterator
;
808 this->public.parse_header
= (status_t (*) (message_t
*)) parse_header
;
809 this->public.parse_body
= (status_t (*) (message_t
*)) parse_body
;
810 this->public.destroy
= (status_t(*)(message_t
*))destroy
;
813 this->exchange_type
= EXCHANGE_TYPE_UNDEFINED
;
814 this->is_request
= TRUE
;
815 this->ike_sa_id
= NULL
;
816 this->first_payload
= NO_PAYLOAD
;
817 this->message_id
= 0;
819 /* private functions */
820 this->get_supported_payloads
= get_supported_payloads
;
825 packet
= packet_create();
829 allocator_free(this);
832 this->packet
= packet
;
833 this->payloads
= linked_list_create();
834 if (this->payloads
== NULL
)
836 allocator_free(this);
840 /* parser is created from data of packet */
841 this->parser
= parser_create(this->packet
->data
);
842 if (this->parser
== NULL
)
844 this->payloads
->destroy(this->payloads
);
845 allocator_free(this);
849 this->logger
= global_logger_manager
->create_logger(global_logger_manager
, MESSAGE
, NULL
);
850 if (this->logger
== NULL
)
852 this->parser
->destroy(this->parser
);
853 this->payloads
->destroy(this->payloads
);
854 allocator_free(this);
858 return (&this->public);
862 * Described in Header-File
864 message_t
*message_create()
866 return message_create_from_packet(NULL
);