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 /* base pointer for output, avoids casting in every rule */
393 /* parse the payload with its own rulse */
394 pld
->get_encoding_rules(pld
, &this->rules
, &rule_count
);
395 for (rule_number
= 0; rule_number
< rule_count
; rule_number
++)
397 rule
= &(this->rules
[rule_number
]);
398 DBG2(DBG_ENC
, " parsing rule %d %N",
399 rule_number
, encoding_type_names
, rule
->type
);
404 if (!parse_uint4(this, rule_number
, output
+ rule
->offset
))
413 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
422 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
431 if (!parse_uint32(this, rule_number
, output
+ rule
->offset
))
440 if (!parse_bytes(this, rule_number
, output
+ rule
->offset
, 8))
449 if (!parse_bit(this, rule_number
, NULL
))
458 if (!parse_uint8(this, rule_number
, NULL
))
467 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
476 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
481 /* parsed u_int16 should be aligned */
482 payload_length
= *(u_int16_t
*)(output
+ rule
->offset
);
483 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
)
492 if (!parse_uint32(this, rule_number
, output
+ rule
->offset
))
501 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
506 spi_size
= *(u_int8_t
*)(output
+ rule
->offset
);
511 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
521 if (payload_length
< SA_PAYLOAD_HEADER_LENGTH
||
522 !parse_list(this, rule_number
, output
+ rule
->offset
,
523 PROPOSAL_SUBSTRUCTURE
,
524 payload_length
- SA_PAYLOAD_HEADER_LENGTH
))
534 spi_size
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
||
535 !parse_list(this, rule_number
, output
+ rule
->offset
,
536 TRANSFORM_SUBSTRUCTURE
, payload_length
- spi_size
-
537 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
))
544 case TRANSFORM_ATTRIBUTES
:
546 if (payload_length
< TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
||
547 !parse_list(this, rule_number
, output
+ rule
->offset
,
549 payload_length
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
))
556 case CONFIGURATION_ATTRIBUTES
:
558 if (payload_length
< CP_PAYLOAD_HEADER_LENGTH
||
559 !parse_list(this, rule_number
, output
+ rule
->offset
,
560 CONFIGURATION_ATTRIBUTE
,
561 payload_length
- CP_PAYLOAD_HEADER_LENGTH
))
568 case ATTRIBUTE_FORMAT
:
570 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
575 attribute_format
= *(bool*)(output
+ rule
->offset
);
580 if (!parse_uint15(this, rule_number
, output
+ rule
->offset
))
587 case CONFIGURATION_ATTRIBUTE_LENGTH
:
589 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
594 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
597 case ATTRIBUTE_LENGTH_OR_VALUE
:
599 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
604 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
607 case ATTRIBUTE_VALUE
:
609 if (attribute_format
== FALSE
&&
610 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
620 if (payload_length
< NONCE_PAYLOAD_HEADER_LENGTH
||
621 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
622 payload_length
- NONCE_PAYLOAD_HEADER_LENGTH
))
631 if (payload_length
< ID_PAYLOAD_HEADER_LENGTH
||
632 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
633 payload_length
- ID_PAYLOAD_HEADER_LENGTH
))
642 if (payload_length
< AUTH_PAYLOAD_HEADER_LENGTH
||
643 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
644 payload_length
- AUTH_PAYLOAD_HEADER_LENGTH
))
653 if (payload_length
< CERT_PAYLOAD_HEADER_LENGTH
||
654 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
655 payload_length
- CERT_PAYLOAD_HEADER_LENGTH
))
664 if (payload_length
< CERTREQ_PAYLOAD_HEADER_LENGTH
||
665 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
666 payload_length
- CERTREQ_PAYLOAD_HEADER_LENGTH
))
675 if (payload_length
< EAP_PAYLOAD_HEADER_LENGTH
||
676 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
677 payload_length
- EAP_PAYLOAD_HEADER_LENGTH
))
686 if (payload_length
< DELETE_PAYLOAD_HEADER_LENGTH
||
687 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
688 payload_length
- DELETE_PAYLOAD_HEADER_LENGTH
))
697 if (payload_length
< VENDOR_ID_PAYLOAD_HEADER_LENGTH
||
698 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
699 payload_length
- VENDOR_ID_PAYLOAD_HEADER_LENGTH
))
706 case CONFIGURATION_ATTRIBUTE_VALUE
:
708 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
716 case KEY_EXCHANGE_DATA
:
718 if (payload_length
< KE_PAYLOAD_HEADER_LENGTH
||
719 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
720 payload_length
- KE_PAYLOAD_HEADER_LENGTH
))
727 case NOTIFICATION_DATA
:
729 if (payload_length
< NOTIFY_PAYLOAD_HEADER_LENGTH
+ spi_size
||
730 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
731 payload_length
- NOTIFY_PAYLOAD_HEADER_LENGTH
- spi_size
))
740 if (payload_length
< ENCRYPTION_PAYLOAD_HEADER_LENGTH
||
741 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
742 payload_length
- ENCRYPTION_PAYLOAD_HEADER_LENGTH
))
751 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
756 ts_type
= *(u_int8_t
*)(output
+ rule
->offset
);
761 int address_length
= (ts_type
== TS_IPV4_ADDR_RANGE
) ?
4 : 16;
763 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
771 case TRAFFIC_SELECTORS
:
773 if (payload_length
< TS_PAYLOAD_HEADER_LENGTH
||
774 !parse_list(this, rule_number
, output
+ rule
->offset
,
775 TRAFFIC_SELECTOR_SUBSTRUCTURE
,
776 payload_length
- TS_PAYLOAD_HEADER_LENGTH
))
785 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
||
786 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
787 payload_length
- UNKNOWN_PAYLOAD_HEADER_LENGTH
))
796 DBG1(DBG_ENC
, " no rule to parse rule %d %N",
797 rule_number
, encoding_type_names
, rule
->type
);
802 /* process next rulue */
807 DBG2(DBG_ENC
, "parsing %N payload finished",
808 payload_type_names
, payload_type
);
813 * Implementation of parser_t.get_remaining_byte_count.
815 static int get_remaining_byte_count (private_parser_t
*this)
817 return this->input_roof
- this->byte_pos
;
821 * Implementation of parser_t.reset_context.
823 static void reset_context (private_parser_t
*this)
825 this->byte_pos
= this->input
;
830 * Implementation of parser_t.destroy.
832 static void destroy(private_parser_t
*this)
838 * Described in header.
840 parser_t
*parser_create(chunk_t data
)
842 private_parser_t
*this = malloc_thing(private_parser_t
);
844 this->public.parse_payload
= (status_t(*)(parser_t
*,payload_type_t
,payload_t
**))parse_payload
;
845 this->public.reset_context
= (void(*)(parser_t
*)) reset_context
;
846 this->public.get_remaining_byte_count
= (int (*) (parser_t
*))get_remaining_byte_count
;
847 this->public.destroy
= (void(*)(parser_t
*)) destroy
;
849 this->input
= data
.ptr
;
850 this->byte_pos
= data
.ptr
;
852 this->input_roof
= data
.ptr
+ data
.len
;
854 return &this->public;