2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include <arpa/inet.h>
27 #include <utils/linked_list.h>
28 #include <encoding/payloads/encodings.h>
29 #include <encoding/payloads/payload.h>
30 #include <encoding/payloads/sa_payload.h>
31 #include <encoding/payloads/proposal_substructure.h>
32 #include <encoding/payloads/transform_substructure.h>
33 #include <encoding/payloads/transform_attribute.h>
34 #include <encoding/payloads/ke_payload.h>
35 #include <encoding/payloads/nonce_payload.h>
36 #include <encoding/payloads/id_payload.h>
37 #include <encoding/payloads/notify_payload.h>
38 #include <encoding/payloads/encryption_payload.h>
39 #include <encoding/payloads/auth_payload.h>
40 #include <encoding/payloads/cert_payload.h>
41 #include <encoding/payloads/certreq_payload.h>
42 #include <encoding/payloads/ts_payload.h>
43 #include <encoding/payloads/delete_payload.h>
44 #include <encoding/payloads/vendor_id_payload.h>
45 #include <encoding/payloads/cp_payload.h>
46 #include <encoding/payloads/configuration_attribute.h>
47 #include <encoding/payloads/eap_payload.h>
48 #include <encoding/payloads/unknown_payload.h>
51 typedef struct private_parser_t private_parser_t
;
54 * Private data stored in a context.
56 * Contains pointers and counters to store current state.
58 struct private_parser_t
{
60 * Public members, see parser_t.
65 * Current bit for reading in input data.
70 * Current byte for reading in input data.
75 * Input data to parse.
80 * Roof of input, used for length-checking.
85 * Set of encoding rules for this parsing session.
87 encoding_rule_t
*rules
;
91 * Parse a 4-Bit unsigned integer from the current parsing position.
93 static status_t
parse_uint4(private_parser_t
*this, int rule_number
, u_int8_t
*output_pos
)
95 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
97 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
98 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
101 switch (this->bit_pos
)
104 /* caller interested in result ? */
105 if (output_pos
!= NULL
)
107 *output_pos
= *(this->byte_pos
) >> 4;
112 /* caller interested in result ? */
113 if (output_pos
!= NULL
)
115 *output_pos
= *(this->byte_pos
) & 0x0F;
121 DBG2(DBG_ENC
, " found rule %d %N on bitpos %d",
122 rule_number
, encoding_type_names
,
123 this->rules
[rule_number
].type
, this->bit_pos
);
127 if (output_pos
!= NULL
)
129 DBG3(DBG_ENC
, " => %d", *output_pos
);
136 * Parse a 8-Bit unsigned integer from the current parsing position.
138 static status_t
parse_uint8(private_parser_t
*this, int rule_number
, u_int8_t
*output_pos
)
140 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
142 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
143 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
148 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d",
149 rule_number
, encoding_type_names
,
150 this->rules
[rule_number
].type
, this->bit_pos
);
154 /* caller interested in result ? */
155 if (output_pos
!= NULL
)
157 *output_pos
= *(this->byte_pos
);
158 DBG3(DBG_ENC
, " => %d", *output_pos
);
166 * Parse a 15-Bit unsigned integer from the current parsing position.
168 static status_t
parse_uint15(private_parser_t
*this, int rule_number
, u_int16_t
*output_pos
)
170 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
172 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
173 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
176 if (this->bit_pos
!= 1)
178 DBG2(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
179 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
182 /* caller interested in result ? */
183 if (output_pos
!= NULL
)
185 *output_pos
= ntohs(*((u_int16_t
*)this->byte_pos
)) & ~0x8000;
186 DBG3(DBG_ENC
, " => %d", *output_pos
);
195 * Parse a 16-Bit unsigned integer from the current parsing position.
197 static status_t
parse_uint16(private_parser_t
*this, int rule_number
, u_int16_t
*output_pos
)
199 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
201 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
202 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
207 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
208 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
211 /* caller interested in result ? */
212 if (output_pos
!= NULL
)
214 *output_pos
= ntohs(*((u_int16_t
*)this->byte_pos
));
216 DBG3(DBG_ENC
, " => %d", *output_pos
);
223 * Parse a 32-Bit unsigned integer from the current parsing position.
225 static status_t
parse_uint32(private_parser_t
*this, int rule_number
, u_int32_t
*output_pos
)
227 if (this->byte_pos
+ sizeof(u_int32_t
) > this->input_roof
)
229 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
230 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
235 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
236 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
239 /* caller interested in result ? */
240 if (output_pos
!= NULL
)
242 *output_pos
= ntohl(*((u_int32_t
*)this->byte_pos
));
244 DBG3(DBG_ENC
, " => %d", *output_pos
);
252 * Parse a 64-Bit unsigned integer from the current parsing position.
254 static status_t
parse_uint64(private_parser_t
*this, int rule_number
, u_int64_t
*output_pos
)
256 if (this->byte_pos
+ sizeof(u_int64_t
) > this->input_roof
)
258 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
259 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
264 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
265 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
268 /* caller interested in result ? */
269 if (output_pos
!= NULL
)
271 /* assuming little endian host order */
272 *(output_pos
+ 1) = ntohl(*((u_int32_t
*)this->byte_pos
));
273 *output_pos
= ntohl(*(((u_int32_t
*)this->byte_pos
) + 1));
275 DBG3(DBG_ENC
, " => %b", (void*)output_pos
, sizeof(u_int64_t
));
283 * Parse a given amount of bytes and writes them to a specific location
285 static status_t
parse_bytes (private_parser_t
*this, int rule_number
, u_int8_t
*output_pos
,size_t bytes
)
287 if (this->byte_pos
+ bytes
> this->input_roof
)
289 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
290 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
295 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
296 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
300 /* caller interested in result ? */
301 if (output_pos
!= NULL
)
303 memcpy(output_pos
,this->byte_pos
,bytes
);
305 DBG3(DBG_ENC
, " => %b", (void*)output_pos
, bytes
);
307 this->byte_pos
+= bytes
;
313 * Parse a single Bit from the current parsing position
315 static status_t
parse_bit(private_parser_t
*this, int rule_number
, bool *output_pos
)
317 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
319 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
320 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
323 /* caller interested in result ? */
324 if (output_pos
!= NULL
)
327 mask
= 0x01 << (7 - this->bit_pos
);
328 *output_pos
= *this->byte_pos
& mask
;
332 /* set to a "clean", comparable true */
336 DBG3(DBG_ENC
, " => %d", *output_pos
);
338 this->bit_pos
= (this->bit_pos
+ 1) % 8;
339 if (this->bit_pos
== 0)
348 * Parse substructures in a list.
350 static status_t
parse_list(private_parser_t
*this, int rule_number
, linked_list_t
**output_pos
, payload_type_t payload_type
, size_t length
)
352 linked_list_t
* list
= *output_pos
;
356 DBG1(DBG_ENC
, " invalid length for rule %d %N",
357 rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
363 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
364 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
370 u_int8_t
*pos_before
= this->byte_pos
;
373 DBG2(DBG_ENC
, " %d bytes left, parsing recursively %N",
374 length
, payload_type_names
, payload_type
);
375 status
= this->public.parse_payload((parser_t
*)this, payload_type
, &payload
);
376 if (status
!= SUCCESS
)
378 DBG1(DBG_ENC
, " parsing of a %N substructure failed",
379 payload_type_names
, payload_type
);
382 list
->insert_last(list
, payload
);
383 length
-= this->byte_pos
- pos_before
;
390 * Parse data from current parsing position in a chunk.
392 static status_t
parse_chunk(private_parser_t
*this, int rule_number
, chunk_t
*output_pos
, size_t length
)
394 if (this->byte_pos
+ length
> this->input_roof
)
396 DBG1(DBG_ENC
, " not enough input (%d bytes) to parse rule %d %N",
397 length
, rule_number
, encoding_type_names
, this->rules
[rule_number
].type
);
402 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d", rule_number
,
403 encoding_type_names
, this->rules
[rule_number
].type
, this->bit_pos
);
406 if (output_pos
!= NULL
)
408 output_pos
->len
= length
;
409 output_pos
->ptr
= malloc(length
);
410 memcpy(output_pos
->ptr
, this->byte_pos
, length
);
412 this->byte_pos
+= length
;
413 DBG3(DBG_ENC
, " => %b", (void*)output_pos
->ptr
, length
);
419 * Implementation of parser_t.parse_payload.
421 static status_t
parse_payload(private_parser_t
*this, payload_type_t payload_type
, payload_t
**payload
)
425 size_t rule_count
, payload_length
= 0, spi_size
= 0, attribute_length
= 0;
426 u_int16_t ts_type
= 0;
427 bool attribute_format
= FALSE
;
429 encoding_rule_t
*rule
;
431 /* create instance of the payload to parse */
432 pld
= payload_create(payload_type
);
434 DBG2(DBG_ENC
, "parsing %N payload, %d bytes left",
435 payload_type_names
, payload_type
, this->input_roof
- this->byte_pos
);
437 DBG3(DBG_ENC
, "parsing payload from %b",
438 this->byte_pos
, this->input_roof
-this->byte_pos
);
440 if (pld
->get_type(pld
) == UNKNOWN_PAYLOAD
)
442 DBG1(DBG_ENC
, " payload type %d is unknown, handling as %N",
443 payload_type
, payload_type_names
, UNKNOWN_PAYLOAD
);
446 /* base pointer for output, avoids casting in every rule */
449 /* parse the payload with its own rulse */
450 pld
->get_encoding_rules(pld
, &(this->rules
), &rule_count
);
451 for (rule_number
= 0; rule_number
< rule_count
; rule_number
++)
453 rule
= &(this->rules
[rule_number
]);
454 DBG2(DBG_ENC
, " parsing rule %d %N",
455 rule_number
, encoding_type_names
, rule
->type
);
460 if (parse_uint4(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
469 if (parse_uint8(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
478 if (parse_uint16(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
487 if (parse_uint32(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
496 if (parse_uint64(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
505 if (parse_bytes(this, rule_number
, output
+ rule
->offset
,8) != SUCCESS
)
514 if (parse_bit(this, rule_number
, NULL
) != SUCCESS
)
523 if (parse_uint8(this, rule_number
, NULL
) != SUCCESS
)
532 if (parse_bit(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
541 if (parse_uint16(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
546 payload_length
= *(u_int16_t
*)(output
+ rule
->offset
);
547 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
)
556 if (parse_uint32(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
565 if (parse_uint8(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
570 spi_size
= *(u_int8_t
*)(output
+ rule
->offset
);
575 if (parse_chunk(this, rule_number
, output
+ rule
->offset
, spi_size
) != SUCCESS
)
584 if (payload_length
< SA_PAYLOAD_HEADER_LENGTH
||
585 parse_list(this, rule_number
, output
+ rule
->offset
, PROPOSAL_SUBSTRUCTURE
,
586 payload_length
- SA_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
595 if (payload_length
< spi_size
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
||
596 parse_list(this, rule_number
, output
+ rule
->offset
, TRANSFORM_SUBSTRUCTURE
,
597 payload_length
- spi_size
- PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
) != SUCCESS
)
604 case TRANSFORM_ATTRIBUTES
:
606 if (payload_length
< TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
||
607 parse_list(this, rule_number
, output
+ rule
->offset
, TRANSFORM_ATTRIBUTE
,
608 payload_length
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
) != SUCCESS
)
615 case CONFIGURATION_ATTRIBUTES
:
617 if (payload_length
< CP_PAYLOAD_HEADER_LENGTH
||
618 parse_list(this, rule_number
, output
+ rule
->offset
, CONFIGURATION_ATTRIBUTE
,
619 payload_length
- CP_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
626 case ATTRIBUTE_FORMAT
:
628 if (parse_bit(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
633 attribute_format
= *(bool*)(output
+ rule
->offset
);
638 if (parse_uint15(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
643 attribute_format
= *(bool*)(output
+ rule
->offset
);
646 case CONFIGURATION_ATTRIBUTE_LENGTH
:
648 if (parse_uint16(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
653 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
656 case ATTRIBUTE_LENGTH_OR_VALUE
:
658 if (parse_uint16(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
663 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
666 case ATTRIBUTE_VALUE
:
668 if (attribute_format
== FALSE
)
670 if (parse_chunk(this, rule_number
, output
+ rule
->offset
, attribute_length
) != SUCCESS
)
680 if (payload_length
< NONCE_PAYLOAD_HEADER_LENGTH
||
681 parse_chunk(this, rule_number
, output
+ rule
->offset
,
682 payload_length
- NONCE_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
691 if (payload_length
< ID_PAYLOAD_HEADER_LENGTH
||
692 parse_chunk(this, rule_number
, output
+ rule
->offset
,
693 payload_length
- ID_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
702 if (payload_length
< AUTH_PAYLOAD_HEADER_LENGTH
||
703 parse_chunk(this, rule_number
, output
+ rule
->offset
,
704 payload_length
- AUTH_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
713 if (payload_length
< CERT_PAYLOAD_HEADER_LENGTH
||
714 parse_chunk(this, rule_number
, output
+ rule
->offset
,
715 payload_length
- CERT_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
724 if (payload_length
< CERTREQ_PAYLOAD_HEADER_LENGTH
||
725 parse_chunk(this, rule_number
, output
+ rule
->offset
,
726 payload_length
- CERTREQ_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
735 if (payload_length
< EAP_PAYLOAD_HEADER_LENGTH
||
736 parse_chunk(this, rule_number
, output
+ rule
->offset
,
737 payload_length
- EAP_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
746 if (payload_length
< DELETE_PAYLOAD_HEADER_LENGTH
||
747 parse_chunk(this, rule_number
, output
+ rule
->offset
,
748 payload_length
- DELETE_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
757 if (payload_length
< VENDOR_ID_PAYLOAD_HEADER_LENGTH
||
758 parse_chunk(this, rule_number
, output
+ rule
->offset
,
759 payload_length
- VENDOR_ID_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
766 case CONFIGURATION_ATTRIBUTE_VALUE
:
768 size_t data_length
= attribute_length
;
769 if (parse_chunk(this, rule_number
, output
+ rule
->offset
, data_length
) != SUCCESS
)
776 case KEY_EXCHANGE_DATA
:
778 if (payload_length
< KE_PAYLOAD_HEADER_LENGTH
||
779 parse_chunk(this, rule_number
, output
+ rule
->offset
,
780 payload_length
- KE_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
787 case NOTIFICATION_DATA
:
789 if (payload_length
< NOTIFY_PAYLOAD_HEADER_LENGTH
+ spi_size
||
790 parse_chunk(this, rule_number
, output
+ rule
->offset
,
791 payload_length
- NOTIFY_PAYLOAD_HEADER_LENGTH
- spi_size
) != SUCCESS
)
800 if (payload_length
< ENCRYPTION_PAYLOAD_HEADER_LENGTH
||
801 parse_chunk(this, rule_number
, output
+ rule
->offset
,
802 payload_length
- ENCRYPTION_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
811 if (parse_uint8(this, rule_number
, output
+ rule
->offset
) != SUCCESS
)
816 ts_type
= *(u_int8_t
*)(output
+ rule
->offset
);
821 size_t address_length
= (ts_type
== TS_IPV4_ADDR_RANGE
) ?
4 : 16;
822 if (parse_chunk(this, rule_number
, output
+ rule
->offset
,address_length
) != SUCCESS
)
829 case TRAFFIC_SELECTORS
:
831 if (payload_length
< TS_PAYLOAD_HEADER_LENGTH
||
832 parse_list(this, rule_number
, output
+ rule
->offset
, TRAFFIC_SELECTOR_SUBSTRUCTURE
,
833 payload_length
- TS_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
842 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
||
843 parse_chunk(this, rule_number
, output
+ rule
->offset
,
844 payload_length
- UNKNOWN_PAYLOAD_HEADER_LENGTH
) != SUCCESS
)
853 DBG1(DBG_ENC
, " no rule to parse rule %d %N",
854 rule_number
, encoding_type_names
, rule
->type
);
859 /* process next rulue */
864 DBG2(DBG_ENC
, "parsing %N payload finished",
865 payload_type_names
, payload_type
);
870 * Implementation of parser_t.get_remaining_byte_count.
872 static int get_remaining_byte_count (private_parser_t
*this)
874 int count
= (this->input_roof
- this->byte_pos
);
879 * Implementation of parser_t.reset_context.
881 static void reset_context (private_parser_t
*this)
883 this->byte_pos
= this->input
;
888 * Implementation of parser_t.destroy.
890 static void destroy(private_parser_t
*this)
896 * Described in header.
898 parser_t
*parser_create(chunk_t data
)
900 private_parser_t
*this = malloc_thing(private_parser_t
);
902 this->public.parse_payload
= (status_t(*)(parser_t
*,payload_type_t
,payload_t
**)) parse_payload
;
903 this->public.reset_context
= (void(*)(parser_t
*)) reset_context
;
904 this->public.get_remaining_byte_count
= (int (*) (parser_t
*))get_remaining_byte_count
;
905 this->public.destroy
= (void(*)(parser_t
*)) destroy
;
907 this->input
= data
.ptr
;
908 this->byte_pos
= data
.ptr
;
910 this->input_roof
= data
.ptr
+ data
.len
;
912 return (parser_t
*)this;