2 * Copyright (C) 2005-2009 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
18 #include <arpa/inet.h>
25 #include <utils/linked_list.h>
26 #include <encoding/payloads/encodings.h>
27 #include <encoding/payloads/payload.h>
28 #include <encoding/payloads/sa_payload.h>
29 #include <encoding/payloads/proposal_substructure.h>
30 #include <encoding/payloads/transform_substructure.h>
31 #include <encoding/payloads/transform_attribute.h>
32 #include <encoding/payloads/ke_payload.h>
33 #include <encoding/payloads/nonce_payload.h>
34 #include <encoding/payloads/id_payload.h>
35 #include <encoding/payloads/notify_payload.h>
36 #include <encoding/payloads/encryption_payload.h>
37 #include <encoding/payloads/auth_payload.h>
38 #include <encoding/payloads/cert_payload.h>
39 #include <encoding/payloads/certreq_payload.h>
40 #include <encoding/payloads/ts_payload.h>
41 #include <encoding/payloads/delete_payload.h>
42 #include <encoding/payloads/vendor_id_payload.h>
43 #include <encoding/payloads/cp_payload.h>
44 #include <encoding/payloads/configuration_attribute.h>
45 #include <encoding/payloads/eap_payload.h>
46 #include <encoding/payloads/unknown_payload.h>
49 typedef struct private_parser_t private_parser_t
;
52 * Private data stored in a context.
54 * Contains pointers and counters to store current state.
56 struct private_parser_t
{
58 * Public members, see parser_t.
63 * Current bit for reading in input data.
68 * Current byte for reading in input data.
73 * Input data to parse.
78 * Roof of input, used for length-checking.
83 * Set of encoding rules for this parsing session.
85 encoding_rule_t
*rules
;
91 static status_t
parse_payload(private_parser_t
*this,
92 payload_type_t payload_type
, payload_t
**payload
);
95 * Log invalid length error
97 static bool short_input(private_parser_t
*this, int number
)
99 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
100 number
, encoding_type_names
, this->rules
[number
].type
);
105 * Log unaligned rules
107 static bool bad_bitpos(private_parser_t
*this, int number
)
109 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d",
110 number
, encoding_type_names
, this->rules
[number
].type
, this->bit_pos
);
115 * Parse a 4-Bit unsigned integer from the current parsing position.
117 static bool parse_uint4(private_parser_t
*this, int rule_number
,
118 u_int8_t
*output_pos
)
120 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
122 return short_input(this, rule_number
);
124 switch (this->bit_pos
)
129 *output_pos
= *(this->byte_pos
) >> 4;
136 *output_pos
= *(this->byte_pos
) & 0x0F;
142 return bad_bitpos(this, rule_number
);
146 DBG3(DBG_ENC
, " => %d", *output_pos
);
152 * Parse a 8-Bit unsigned integer from the current parsing position.
154 static bool parse_uint8(private_parser_t
*this, int rule_number
,
155 u_int8_t
*output_pos
)
157 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
159 return short_input(this, rule_number
);
163 return bad_bitpos(this, rule_number
);
167 *output_pos
= *(this->byte_pos
);
168 DBG3(DBG_ENC
, " => %d", *output_pos
);
175 * Parse a 15-Bit unsigned integer from the current parsing position.
177 static bool parse_uint15(private_parser_t
*this, int rule_number
,
178 u_int16_t
*output_pos
)
180 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
182 return short_input(this, rule_number
);
184 if (this->bit_pos
!= 1)
186 return bad_bitpos(this, rule_number
);
190 memcpy(output_pos
, this->byte_pos
, sizeof(u_int16_t
));
191 *output_pos
= ntohs(*output_pos
) & ~0x8000;
192 DBG3(DBG_ENC
, " => %d", *output_pos
);
194 this->byte_pos
+= sizeof(u_int16_t
);
200 * Parse a 16-Bit unsigned integer from the current parsing position.
202 static bool parse_uint16(private_parser_t
*this, int rule_number
,
203 u_int16_t
*output_pos
)
205 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
207 return short_input(this, rule_number
);
211 return bad_bitpos(this, rule_number
);
215 memcpy(output_pos
, this->byte_pos
, sizeof(u_int16_t
));
216 *output_pos
= ntohs(*output_pos
);
217 DBG3(DBG_ENC
, " => %d", *output_pos
);
219 this->byte_pos
+= sizeof(u_int16_t
);
223 * Parse a 32-Bit unsigned integer from the current parsing position.
225 static bool parse_uint32(private_parser_t
*this, int rule_number
,
226 u_int32_t
*output_pos
)
228 if (this->byte_pos
+ sizeof(u_int32_t
) > this->input_roof
)
230 return short_input(this, rule_number
);
234 return bad_bitpos(this, rule_number
);
238 memcpy(output_pos
, this->byte_pos
, sizeof(u_int32_t
));
239 *output_pos
= ntohl(*output_pos
);
240 DBG3(DBG_ENC
, " => %d", *output_pos
);
242 this->byte_pos
+= sizeof(u_int32_t
);
247 * Parse a given amount of bytes and writes them to a specific location
249 static bool parse_bytes(private_parser_t
*this, int rule_number
,
250 u_int8_t
*output_pos
, int bytes
)
252 if (this->byte_pos
+ bytes
> this->input_roof
)
254 return short_input(this, rule_number
);
258 return bad_bitpos(this, rule_number
);
262 memcpy(output_pos
, this->byte_pos
, bytes
);
263 DBG3(DBG_ENC
, " => %b", output_pos
, bytes
);
265 this->byte_pos
+= bytes
;
270 * Parse a single Bit from the current parsing position
272 static bool parse_bit(private_parser_t
*this, int rule_number
,
275 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
277 return short_input(this, rule_number
);
282 mask
= 0x01 << (7 - this->bit_pos
);
283 *output_pos
= *this->byte_pos
& mask
;
286 { /* set to a "clean", comparable true */
289 DBG3(DBG_ENC
, " => %d", *output_pos
);
291 this->bit_pos
= (this->bit_pos
+ 1) % 8;
292 if (this->bit_pos
== 0)
300 * Parse substructures in a list.
302 static bool parse_list(private_parser_t
*this, int rule_number
,
303 linked_list_t
**output_pos
, payload_type_t payload_type
, int length
)
305 linked_list_t
*list
= *output_pos
;
309 return short_input(this, rule_number
);
313 return bad_bitpos(this, rule_number
);
317 u_int8_t
*pos_before
= this->byte_pos
;
320 DBG2(DBG_ENC
, " %d bytes left, parsing recursively %N",
321 length
, payload_type_names
, payload_type
);
323 if (parse_payload(this, payload_type
, &payload
) != SUCCESS
)
325 DBG1(DBG_ENC
, " parsing of a %N substructure failed",
326 payload_type_names
, payload_type
);
329 list
->insert_last(list
, payload
);
330 length
-= this->byte_pos
- pos_before
;
333 { /* must yield exactly to zero */
334 DBG1(DBG_ENC
, " length of %N substructure list invalid",
335 payload_type_names
, payload_type
);
343 * Parse data from current parsing position in a chunk.
345 static bool parse_chunk(private_parser_t
*this, int rule_number
,
346 chunk_t
*output_pos
, int length
)
348 if (this->byte_pos
+ length
> this->input_roof
)
350 return short_input(this, rule_number
);
354 return bad_bitpos(this, rule_number
);
358 *output_pos
= chunk_alloc(length
);
359 memcpy(output_pos
->ptr
, this->byte_pos
, length
);
360 DBG3(DBG_ENC
, " => %b", output_pos
->ptr
, length
);
362 this->byte_pos
+= length
;
367 * Implementation of parser_t.parse_payload.
369 static status_t
parse_payload(private_parser_t
*this,
370 payload_type_t payload_type
, payload_t
**payload
)
375 int payload_length
= 0, spi_size
= 0, attribute_length
= 0;
376 u_int16_t ts_type
= 0;
377 bool attribute_format
= FALSE
;
379 encoding_rule_t
*rule
;
381 /* create instance of the payload to parse */
382 pld
= payload_create(payload_type
);
384 DBG2(DBG_ENC
, "parsing %N payload, %d bytes left",
385 payload_type_names
, payload_type
, this->input_roof
- this->byte_pos
);
387 DBG3(DBG_ENC
, "parsing payload from %b",
388 this->byte_pos
, this->input_roof
- this->byte_pos
);
390 if (pld
->get_type(pld
) == UNKNOWN_PAYLOAD
)
392 DBG1(DBG_ENC
, " payload type %d is unknown, handling as %N",
393 payload_type
, payload_type_names
, UNKNOWN_PAYLOAD
);
396 /* base pointer for output, avoids casting in every rule */
399 /* parse the payload with its own rulse */
400 pld
->get_encoding_rules(pld
, &this->rules
, &rule_count
);
401 for (rule_number
= 0; rule_number
< rule_count
; rule_number
++)
403 rule
= &(this->rules
[rule_number
]);
404 DBG2(DBG_ENC
, " parsing rule %d %N",
405 rule_number
, encoding_type_names
, rule
->type
);
410 if (!parse_uint4(this, rule_number
, output
+ rule
->offset
))
419 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
428 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
437 if (!parse_uint32(this, rule_number
, output
+ rule
->offset
))
446 if (!parse_bytes(this, rule_number
, output
+ rule
->offset
, 8))
455 if (!parse_bit(this, rule_number
, NULL
))
464 if (!parse_uint8(this, rule_number
, NULL
))
473 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
482 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
487 /* parsed u_int16 should be aligned */
488 payload_length
= *(u_int16_t
*)(output
+ rule
->offset
);
489 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
)
498 if (!parse_uint32(this, rule_number
, output
+ rule
->offset
))
507 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
512 spi_size
= *(u_int8_t
*)(output
+ rule
->offset
);
517 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
527 if (payload_length
< SA_PAYLOAD_HEADER_LENGTH
||
528 !parse_list(this, rule_number
, output
+ rule
->offset
,
529 PROPOSAL_SUBSTRUCTURE
,
530 payload_length
- SA_PAYLOAD_HEADER_LENGTH
))
540 spi_size
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
||
541 !parse_list(this, rule_number
, output
+ rule
->offset
,
542 TRANSFORM_SUBSTRUCTURE
, payload_length
- spi_size
-
543 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
))
550 case TRANSFORM_ATTRIBUTES
:
552 if (payload_length
< TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
||
553 !parse_list(this, rule_number
, output
+ rule
->offset
,
555 payload_length
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
))
562 case CONFIGURATION_ATTRIBUTES
:
564 if (payload_length
< CP_PAYLOAD_HEADER_LENGTH
||
565 !parse_list(this, rule_number
, output
+ rule
->offset
,
566 CONFIGURATION_ATTRIBUTE
,
567 payload_length
- CP_PAYLOAD_HEADER_LENGTH
))
574 case ATTRIBUTE_FORMAT
:
576 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
581 attribute_format
= *(bool*)(output
+ rule
->offset
);
586 if (!parse_uint15(this, rule_number
, output
+ rule
->offset
))
593 case CONFIGURATION_ATTRIBUTE_LENGTH
:
595 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
600 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
603 case ATTRIBUTE_LENGTH_OR_VALUE
:
605 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
610 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
613 case ATTRIBUTE_VALUE
:
615 if (attribute_format
== FALSE
&&
616 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
626 if (payload_length
< NONCE_PAYLOAD_HEADER_LENGTH
||
627 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
628 payload_length
- NONCE_PAYLOAD_HEADER_LENGTH
))
637 if (payload_length
< ID_PAYLOAD_HEADER_LENGTH
||
638 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
639 payload_length
- ID_PAYLOAD_HEADER_LENGTH
))
648 if (payload_length
< AUTH_PAYLOAD_HEADER_LENGTH
||
649 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
650 payload_length
- AUTH_PAYLOAD_HEADER_LENGTH
))
659 if (payload_length
< CERT_PAYLOAD_HEADER_LENGTH
||
660 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
661 payload_length
- CERT_PAYLOAD_HEADER_LENGTH
))
670 if (payload_length
< CERTREQ_PAYLOAD_HEADER_LENGTH
||
671 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
672 payload_length
- CERTREQ_PAYLOAD_HEADER_LENGTH
))
681 if (payload_length
< EAP_PAYLOAD_HEADER_LENGTH
||
682 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
683 payload_length
- EAP_PAYLOAD_HEADER_LENGTH
))
692 if (payload_length
< DELETE_PAYLOAD_HEADER_LENGTH
||
693 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
694 payload_length
- DELETE_PAYLOAD_HEADER_LENGTH
))
703 if (payload_length
< VENDOR_ID_PAYLOAD_HEADER_LENGTH
||
704 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
705 payload_length
- VENDOR_ID_PAYLOAD_HEADER_LENGTH
))
712 case CONFIGURATION_ATTRIBUTE_VALUE
:
714 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
722 case KEY_EXCHANGE_DATA
:
724 if (payload_length
< KE_PAYLOAD_HEADER_LENGTH
||
725 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
726 payload_length
- KE_PAYLOAD_HEADER_LENGTH
))
733 case NOTIFICATION_DATA
:
735 if (payload_length
< NOTIFY_PAYLOAD_HEADER_LENGTH
+ spi_size
||
736 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
737 payload_length
- NOTIFY_PAYLOAD_HEADER_LENGTH
- spi_size
))
746 if (payload_length
< ENCRYPTION_PAYLOAD_HEADER_LENGTH
||
747 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
748 payload_length
- ENCRYPTION_PAYLOAD_HEADER_LENGTH
))
757 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
762 ts_type
= *(u_int8_t
*)(output
+ rule
->offset
);
767 int address_length
= (ts_type
== TS_IPV4_ADDR_RANGE
) ?
4 : 16;
769 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
777 case TRAFFIC_SELECTORS
:
779 if (payload_length
< TS_PAYLOAD_HEADER_LENGTH
||
780 !parse_list(this, rule_number
, output
+ rule
->offset
,
781 TRAFFIC_SELECTOR_SUBSTRUCTURE
,
782 payload_length
- TS_PAYLOAD_HEADER_LENGTH
))
791 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
||
792 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
793 payload_length
- UNKNOWN_PAYLOAD_HEADER_LENGTH
))
802 DBG1(DBG_ENC
, " no rule to parse rule %d %N",
803 rule_number
, encoding_type_names
, rule
->type
);
808 /* process next rulue */
813 DBG2(DBG_ENC
, "parsing %N payload finished",
814 payload_type_names
, payload_type
);
819 * Implementation of parser_t.get_remaining_byte_count.
821 static int get_remaining_byte_count (private_parser_t
*this)
823 return this->input_roof
- this->byte_pos
;
827 * Implementation of parser_t.reset_context.
829 static void reset_context (private_parser_t
*this)
831 this->byte_pos
= this->input
;
836 * Implementation of parser_t.destroy.
838 static void destroy(private_parser_t
*this)
844 * Described in header.
846 parser_t
*parser_create(chunk_t data
)
848 private_parser_t
*this = malloc_thing(private_parser_t
);
850 this->public.parse_payload
= (status_t(*)(parser_t
*,payload_type_t
,payload_t
**))parse_payload
;
851 this->public.reset_context
= (void(*)(parser_t
*)) reset_context
;
852 this->public.get_remaining_byte_count
= (int (*) (parser_t
*))get_remaining_byte_count
;
853 this->public.destroy
= (void(*)(parser_t
*)) destroy
;
855 this->input
= data
.ptr
;
856 this->byte_pos
= data
.ptr
;
858 this->input_roof
= data
.ptr
+ data
.len
;
860 return &this->public;