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
;
89 * Log invalid length error
91 static bool short_input(private_parser_t
*this, int number
)
93 DBG1(DBG_ENC
, " not enough input to parse rule %d %N",
94 number
, encoding_type_names
, this->rules
[number
].type
);
101 static bool bad_bitpos(private_parser_t
*this, int number
)
103 DBG1(DBG_ENC
, " found rule %d %N on bitpos %d",
104 number
, encoding_type_names
, this->rules
[number
].type
, this->bit_pos
);
109 * Parse a 4-Bit unsigned integer from the current parsing position.
111 static bool parse_uint4(private_parser_t
*this, int rule_number
,
112 u_int8_t
*output_pos
)
114 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
116 return short_input(this, rule_number
);
118 switch (this->bit_pos
)
123 *output_pos
= *(this->byte_pos
) >> 4;
130 *output_pos
= *(this->byte_pos
) & 0x0F;
136 return bad_bitpos(this, rule_number
);
140 DBG3(DBG_ENC
, " => %d", *output_pos
);
146 * Parse a 8-Bit unsigned integer from the current parsing position.
148 static bool parse_uint8(private_parser_t
*this, int rule_number
,
149 u_int8_t
*output_pos
)
151 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
153 return short_input(this, rule_number
);
157 return bad_bitpos(this, rule_number
);
161 *output_pos
= *(this->byte_pos
);
162 DBG3(DBG_ENC
, " => %d", *output_pos
);
169 * Parse a 15-Bit unsigned integer from the current parsing position.
171 static bool parse_uint15(private_parser_t
*this, int rule_number
,
172 u_int16_t
*output_pos
)
174 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
176 return short_input(this, rule_number
);
178 if (this->bit_pos
!= 1)
180 return bad_bitpos(this, rule_number
);
184 memcpy(output_pos
, this->byte_pos
, sizeof(u_int16_t
));
185 *output_pos
= ntohs(*output_pos
) & ~0x8000;
186 DBG3(DBG_ENC
, " => %d", *output_pos
);
188 this->byte_pos
+= sizeof(u_int16_t
);
194 * Parse a 16-Bit unsigned integer from the current parsing position.
196 static bool parse_uint16(private_parser_t
*this, int rule_number
,
197 u_int16_t
*output_pos
)
199 if (this->byte_pos
+ sizeof(u_int16_t
) > this->input_roof
)
201 return short_input(this, rule_number
);
205 return bad_bitpos(this, rule_number
);
209 memcpy(output_pos
, this->byte_pos
, sizeof(u_int16_t
));
210 *output_pos
= ntohs(*output_pos
);
211 DBG3(DBG_ENC
, " => %d", *output_pos
);
213 this->byte_pos
+= sizeof(u_int16_t
);
217 * Parse a 32-Bit unsigned integer from the current parsing position.
219 static bool parse_uint32(private_parser_t
*this, int rule_number
,
220 u_int32_t
*output_pos
)
222 if (this->byte_pos
+ sizeof(u_int32_t
) > this->input_roof
)
224 return short_input(this, rule_number
);
228 return bad_bitpos(this, rule_number
);
232 memcpy(output_pos
, this->byte_pos
, sizeof(u_int32_t
));
233 *output_pos
= ntohl(*output_pos
);
234 DBG3(DBG_ENC
, " => %d", *output_pos
);
236 this->byte_pos
+= sizeof(u_int32_t
);
241 * Parse a given amount of bytes and writes them to a specific location
243 static bool parse_bytes(private_parser_t
*this, int rule_number
,
244 u_int8_t
*output_pos
, int bytes
)
246 if (this->byte_pos
+ bytes
> this->input_roof
)
248 return short_input(this, rule_number
);
252 return bad_bitpos(this, rule_number
);
256 memcpy(output_pos
, this->byte_pos
, bytes
);
257 DBG3(DBG_ENC
, " => %b", output_pos
, bytes
);
259 this->byte_pos
+= bytes
;
264 * Parse a single Bit from the current parsing position
266 static bool parse_bit(private_parser_t
*this, int rule_number
,
269 if (this->byte_pos
+ sizeof(u_int8_t
) > this->input_roof
)
271 return short_input(this, rule_number
);
276 mask
= 0x01 << (7 - this->bit_pos
);
277 *output_pos
= *this->byte_pos
& mask
;
280 { /* set to a "clean", comparable true */
283 DBG3(DBG_ENC
, " => %d", *output_pos
);
285 this->bit_pos
= (this->bit_pos
+ 1) % 8;
286 if (this->bit_pos
== 0)
294 * Parse substructures in a list.
296 static bool parse_list(private_parser_t
*this, int rule_number
,
297 linked_list_t
**output_pos
, payload_type_t payload_type
, int length
)
299 linked_list_t
*list
= *output_pos
;
303 return short_input(this, rule_number
);
307 return bad_bitpos(this, rule_number
);
311 u_int8_t
*pos_before
= this->byte_pos
;
314 DBG2(DBG_ENC
, " %d bytes left, parsing recursively %N",
315 length
, payload_type_names
, payload_type
);
317 if (this->public.parse_payload(&this->public, payload_type
,
318 &payload
) != SUCCESS
)
320 DBG1(DBG_ENC
, " parsing of a %N substructure failed",
321 payload_type_names
, payload_type
);
324 list
->insert_last(list
, payload
);
325 length
-= this->byte_pos
- pos_before
;
328 { /* must yield exactly to zero */
329 DBG1(DBG_ENC
, " length of %N substructure list invalid",
330 payload_type_names
, payload_type
);
338 * Parse data from current parsing position in a chunk.
340 static bool parse_chunk(private_parser_t
*this, int rule_number
,
341 chunk_t
*output_pos
, int length
)
343 if (this->byte_pos
+ length
> this->input_roof
)
345 return short_input(this, rule_number
);
349 return bad_bitpos(this, rule_number
);
353 *output_pos
= chunk_alloc(length
);
354 memcpy(output_pos
->ptr
, this->byte_pos
, length
);
355 DBG3(DBG_ENC
, " => %b", output_pos
->ptr
, length
);
357 this->byte_pos
+= length
;
361 METHOD(parser_t
, parse_payload
, status_t
,
362 private_parser_t
*this, payload_type_t payload_type
, payload_t
**payload
)
366 int payload_length
= 0, spi_size
= 0, attribute_length
= 0;
367 u_int16_t ts_type
= 0;
368 bool attribute_format
= FALSE
;
369 int rule_number
, rule_count
;
370 encoding_rule_t
*rule
;
372 /* create instance of the payload to parse */
373 pld
= payload_create(payload_type
);
375 DBG2(DBG_ENC
, "parsing %N payload, %d bytes left",
376 payload_type_names
, payload_type
, this->input_roof
- this->byte_pos
);
378 DBG3(DBG_ENC
, "parsing payload from %b",
379 this->byte_pos
, this->input_roof
- this->byte_pos
);
381 /* base pointer for output, avoids casting in every rule */
384 /* parse the payload with its own rulse */
385 rule_count
= pld
->get_encoding_rules(pld
, &this->rules
);
386 for (rule_number
= 0; rule_number
< rule_count
; rule_number
++)
388 rule
= &(this->rules
[rule_number
]);
389 DBG2(DBG_ENC
, " parsing rule %d %N",
390 rule_number
, encoding_type_names
, rule
->type
);
395 if (!parse_uint4(this, rule_number
, output
+ rule
->offset
))
405 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
414 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
424 if (!parse_uint32(this, rule_number
, output
+ rule
->offset
))
433 if (!parse_bytes(this, rule_number
, output
+ rule
->offset
, 8))
443 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
452 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
457 /* parsed u_int16 should be aligned */
458 payload_length
= *(u_int16_t
*)(output
+ rule
->offset
);
459 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
)
468 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
473 spi_size
= *(u_int8_t
*)(output
+ rule
->offset
);
478 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
488 if (payload_length
< SA_PAYLOAD_HEADER_LENGTH
||
489 !parse_list(this, rule_number
, output
+ rule
->offset
,
490 PROPOSAL_SUBSTRUCTURE
,
491 payload_length
- SA_PAYLOAD_HEADER_LENGTH
))
500 if (payload_length
< SA_PAYLOAD_V1_HEADER_LENGTH
||
501 !parse_list(this, rule_number
, output
+ rule
->offset
,
502 PROPOSAL_SUBSTRUCTURE_V1
,
503 payload_length
- SA_PAYLOAD_V1_HEADER_LENGTH
))
513 spi_size
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
||
514 !parse_list(this, rule_number
, output
+ rule
->offset
,
515 TRANSFORM_SUBSTRUCTURE
, payload_length
- spi_size
-
516 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
))
526 spi_size
+ PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
||
527 !parse_list(this, rule_number
, output
+ rule
->offset
,
528 TRANSFORM_SUBSTRUCTURE_V1
, payload_length
- spi_size
-
529 PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
))
536 case TRANSFORM_ATTRIBUTES
:
538 if (payload_length
< TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
||
539 !parse_list(this, rule_number
, output
+ rule
->offset
,
541 payload_length
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
))
548 case TRANSFORM_ATTRIBUTES_V1
:
550 if (payload_length
< TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
||
551 !parse_list(this, rule_number
, output
+ rule
->offset
,
552 TRANSFORM_ATTRIBUTE_V1
,
553 payload_length
- TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
))
560 case CONFIGURATION_ATTRIBUTES
:
562 if (payload_length
< CP_PAYLOAD_HEADER_LENGTH
||
563 !parse_list(this, rule_number
, output
+ rule
->offset
,
564 CONFIGURATION_ATTRIBUTE
,
565 payload_length
- CP_PAYLOAD_HEADER_LENGTH
))
572 case ATTRIBUTE_FORMAT
:
574 if (!parse_bit(this, rule_number
, output
+ rule
->offset
))
579 attribute_format
= *(bool*)(output
+ rule
->offset
);
584 if (!parse_uint15(this, rule_number
, output
+ rule
->offset
))
591 case CONFIGURATION_ATTRIBUTE_LENGTH
:
593 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
598 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
601 case ATTRIBUTE_LENGTH_OR_VALUE
:
603 if (!parse_uint16(this, rule_number
, output
+ rule
->offset
))
608 attribute_length
= *(u_int16_t
*)(output
+ rule
->offset
);
611 case ATTRIBUTE_VALUE
:
613 if (attribute_format
== FALSE
&&
614 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
624 if (payload_length
< NONCE_PAYLOAD_HEADER_LENGTH
||
625 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
626 payload_length
- NONCE_PAYLOAD_HEADER_LENGTH
))
635 if (payload_length
< ID_PAYLOAD_HEADER_LENGTH
||
636 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
637 payload_length
- ID_PAYLOAD_HEADER_LENGTH
))
646 if (payload_length
< AUTH_PAYLOAD_HEADER_LENGTH
||
647 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
648 payload_length
- AUTH_PAYLOAD_HEADER_LENGTH
))
657 if (payload_length
< CERT_PAYLOAD_HEADER_LENGTH
||
658 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
659 payload_length
- CERT_PAYLOAD_HEADER_LENGTH
))
668 if (payload_length
< CERTREQ_PAYLOAD_HEADER_LENGTH
||
669 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
670 payload_length
- CERTREQ_PAYLOAD_HEADER_LENGTH
))
679 if (payload_length
< EAP_PAYLOAD_HEADER_LENGTH
||
680 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
681 payload_length
- EAP_PAYLOAD_HEADER_LENGTH
))
690 if (payload_length
< DELETE_PAYLOAD_HEADER_LENGTH
||
691 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
692 payload_length
- DELETE_PAYLOAD_HEADER_LENGTH
))
701 if (payload_length
< VENDOR_ID_PAYLOAD_HEADER_LENGTH
||
702 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
703 payload_length
- VENDOR_ID_PAYLOAD_HEADER_LENGTH
))
710 case CONFIGURATION_ATTRIBUTE_VALUE
:
712 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
720 case KEY_EXCHANGE_DATA
:
722 if (payload_length
< KE_PAYLOAD_HEADER_LENGTH
||
723 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
724 payload_length
- KE_PAYLOAD_HEADER_LENGTH
))
731 case KEY_EXCHANGE_DATA_V1
:
733 if (payload_length
< KE_PAYLOAD_V1_HEADER_LENGTH
||
734 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
735 payload_length
- KE_PAYLOAD_V1_HEADER_LENGTH
))
742 case NOTIFICATION_DATA
:
744 if (payload_length
< NOTIFY_PAYLOAD_HEADER_LENGTH
+ spi_size
||
745 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
746 payload_length
- NOTIFY_PAYLOAD_HEADER_LENGTH
- spi_size
))
755 if (payload_length
< ENCRYPTION_PAYLOAD_HEADER_LENGTH
||
756 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
757 payload_length
- ENCRYPTION_PAYLOAD_HEADER_LENGTH
))
766 if (!parse_uint8(this, rule_number
, output
+ rule
->offset
))
771 ts_type
= *(u_int8_t
*)(output
+ rule
->offset
);
776 int address_length
= (ts_type
== TS_IPV4_ADDR_RANGE
) ?
4 : 16;
778 if (!parse_chunk(this, rule_number
, output
+ rule
->offset
,
786 case TRAFFIC_SELECTORS
:
788 if (payload_length
< TS_PAYLOAD_HEADER_LENGTH
||
789 !parse_list(this, rule_number
, output
+ rule
->offset
,
790 TRAFFIC_SELECTOR_SUBSTRUCTURE
,
791 payload_length
- TS_PAYLOAD_HEADER_LENGTH
))
800 if (payload_length
< UNKNOWN_PAYLOAD_HEADER_LENGTH
||
801 !parse_chunk(this, rule_number
, output
+ rule
->offset
,
802 payload_length
- UNKNOWN_PAYLOAD_HEADER_LENGTH
))
811 DBG1(DBG_ENC
, " no rule to parse rule %d %N",
812 rule_number
, encoding_type_names
, rule
->type
);
817 /* process next rulue */
822 DBG2(DBG_ENC
, "parsing %N payload finished",
823 payload_type_names
, payload_type
);
827 METHOD(parser_t
, get_remaining_byte_count
, int,
828 private_parser_t
*this)
830 return this->input_roof
- this->byte_pos
;
833 METHOD(parser_t
, reset_context
, void,
834 private_parser_t
*this)
836 this->byte_pos
= this->input
;
840 METHOD(parser_t
, destroy
, void,
841 private_parser_t
*this)
847 * Described in header.
849 parser_t
*parser_create(chunk_t data
)
851 private_parser_t
*this;
855 .parse_payload
= _parse_payload
,
856 .reset_context
= _reset_context
,
857 .get_remaining_byte_count
= _get_remaining_byte_count
,
861 .byte_pos
= data
.ptr
,
862 .input_roof
= data
.ptr
+ data
.len
,
865 return &this->public;