updated copyright information
[strongswan.git] / src / charon / encoding / parser.c
1 /**
2 * @file parser.c
3 *
4 * @brief Implementation of parser_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdlib.h>
25 #include <arpa/inet.h>
26 #include <string.h>
27
28 #include "parser.h"
29
30 #include <types.h>
31 #include <definitions.h>
32 #include <daemon.h>
33 #include <utils/logger.h>
34 #include <utils/linked_list.h>
35 #include <encoding/payloads/encodings.h>
36 #include <encoding/payloads/payload.h>
37 #include <encoding/payloads/sa_payload.h>
38 #include <encoding/payloads/proposal_substructure.h>
39 #include <encoding/payloads/transform_substructure.h>
40 #include <encoding/payloads/transform_attribute.h>
41 #include <encoding/payloads/ke_payload.h>
42 #include <encoding/payloads/nonce_payload.h>
43 #include <encoding/payloads/id_payload.h>
44 #include <encoding/payloads/notify_payload.h>
45 #include <encoding/payloads/encryption_payload.h>
46 #include <encoding/payloads/auth_payload.h>
47 #include <encoding/payloads/cert_payload.h>
48 #include <encoding/payloads/certreq_payload.h>
49 #include <encoding/payloads/ts_payload.h>
50 #include <encoding/payloads/delete_payload.h>
51 #include <encoding/payloads/vendor_id_payload.h>
52 #include <encoding/payloads/cp_payload.h>
53 #include <encoding/payloads/configuration_attribute.h>
54 #include <encoding/payloads/eap_payload.h>
55 #include <encoding/payloads/unknown_payload.h>
56
57
58 typedef struct private_parser_t private_parser_t;
59
60 /**
61 * Private data stored in a context.
62 *
63 * Contains pointers and counters to store current state.
64 */
65 struct private_parser_t {
66 /**
67 * Public members, see parser_t.
68 */
69 parser_t public;
70
71 /**
72 * @brief Parse a 4-Bit unsigned integer from the current parsing position.
73 *
74 * @param this parser_t object
75 * @param rule_number number of current rule
76 * @param[out] output_pos pointer where to write the parsed result
77 * @return
78 * - SUCCESS or
79 * - PARSE_ERROR when not successful
80 */
81 status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
82
83 /**
84 * @brief Parse a 8-Bit unsigned integer from the current parsing position.
85 *
86 * @param this parser_t object
87 * @param rule_number number of current rule
88 * @param[out] output_pos pointer where to write the parsed result
89 * @return
90 * - SUCCESS or
91 * - PARSE_ERROR when not successful
92 */
93 status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
94
95 /**
96 * @brief Parse a 15-Bit unsigned integer from the current parsing position.
97 *
98 * This is a special case used for ATTRIBUTE_TYPE.
99 * Big-/Little-endian conversion is done here.
100 *
101 * @param this parser_t object
102 * @param rule_number number of current rule
103 * @param[out] output_pos pointer where to write the parsed result
104 * @return
105 * - SUCCESS or
106 * - PARSE_ERROR when not successful
107 */
108 status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
109
110 /**
111 * @brief Parse a 16-Bit unsigned integer from the current parsing position.
112 *
113 * Big-/Little-endian conversion is done here.
114 *
115 * @param this parser_t object
116 * @param rule_number number of current rule
117 * @param[out] output_pos pointer where to write the parsed result
118 * @return
119 * - SUCCESS or
120 * - PARSE_ERROR when not successful
121 */
122 status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
123
124 /**
125 * @brief Parse a 32-Bit unsigned integer from the current parsing position.
126 *
127 * Big-/Little-endian conversion is done here.
128 *
129 * @param this parser_t object
130 * @param rule_number number of current rule
131 * @param[out] output_pos pointer where to write the parsed result
132 * @return
133 * - SUCCESS or
134 * - PARSE_ERROR when not successful
135 */
136 status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos);
137
138 /**
139 * @brief Parse a 64-Bit unsigned integer from the current parsing position.
140 *
141 * @todo add support for big-endian machines.
142 *
143 * @param this parser_t object
144 * @param rule_number number of current rule
145 * @param[out] output_pos pointer where to write the parsed result
146 * @return
147 * - SUCCESS or
148 * - PARSE_ERROR when not successful
149 */
150 status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos);
151
152 /**
153 * @brief Parse a given amount of bytes and writes them to a specific location
154 *
155 * @param this parser_t object
156 * @param rule_number number of current rule
157 * @param[out] output_pos pointer where to write the parsed result
158 * @param bytes number of bytes to parse
159 * @return
160 * - SUCCESS or
161 * - PARSE_ERROR when not successful
162 */
163 status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes);
164
165 /**
166 * @brief Parse a single Bit from the current parsing position
167 *
168 * @param this parser_t object
169 * @param rule_number number of current rule
170 * @param[out] output_pos pointer where to write the parsed result
171 * @return
172 * - SUCCESS or
173 * - PARSE_ERROR when not successful
174 */
175 status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos);
176
177 /**
178 * @brief Parse substructures in a list
179 *
180 * This function calls the parser recursivly to parse contained substructures
181 * in a linked_list_t. The list must already be created. Payload defines
182 * the type of the substructures. parsing is continued until the specified length
183 * is completely parsed.
184 *
185 * @param this parser_t object
186 * @param rule_number number of current rule
187 * @param[out] output_pos pointer of a linked_list where substructures are added
188 * @param payload_type type of the contained substructures to parse
189 * @param length number of bytes to parse in this list
190 * @return
191 * - SUCCESS or
192 * - PARSE_ERROR when not successful
193 */
194 status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length);
195
196 /**
197 * @brief Parse data from current parsing position in a chunk.
198 *
199 * This function clones length number of bytes to output_pos, without
200 * modifiyng them. Space will be allocated and must be freed by caller.
201 *
202 * @param this parser_t object
203 * @param rule_number number of current rule
204 * @param[out] output_pos pointer of a chunk which will point to the allocated data
205 * @param length number of bytes to clone
206 * @return
207 * - SUCCESS or
208 * - PARSE_ERROR when not successful
209 */
210 status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length);
211
212 /**
213 * Current bit for reading in input data.
214 */
215 u_int8_t bit_pos;
216
217 /**
218 * Current byte for reading in input data.
219 */
220 u_int8_t *byte_pos;
221
222 /**
223 * Input data to parse.
224 */
225 u_int8_t *input;
226
227 /**
228 * Roof of input, used for length-checking.
229 */
230 u_int8_t *input_roof;
231
232 /**
233 * Set of encoding rules for this parsing session.
234 */
235 encoding_rule_t *rules;
236
237 /**
238 * Assigned logger_t object.
239 */
240 logger_t *logger;
241 };
242
243 /**
244 * Implementation of private_parser_t.parse_uint4.
245 */
246 static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos)
247 {
248 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
249 {
250 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
251 rule_number, mapping_find(encoding_type_m,
252 this->rules[rule_number].type));
253 return PARSE_ERROR;
254 }
255 switch (this->bit_pos)
256 {
257 case 0:
258 /* caller interested in result ? */
259 if (output_pos != NULL)
260 {
261 *output_pos = *(this->byte_pos) >> 4;
262 }
263 this->bit_pos = 4;
264 break;
265 case 4:
266 /* caller interested in result ? */
267 if (output_pos != NULL)
268 {
269 *output_pos = *(this->byte_pos) & 0x0F;
270 }
271 this->bit_pos = 0;
272 this->byte_pos++;
273 break;
274 default:
275 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
276 rule_number, mapping_find(encoding_type_m,
277 this->rules[rule_number].type), this->bit_pos);
278 return PARSE_ERROR;
279 }
280
281 if (output_pos != NULL)
282 {
283 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
284 }
285
286 return SUCCESS;
287 }
288
289 /**
290 * Implementation of private_parser_t.parse_uint8.
291 */
292 static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos)
293 {
294 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
295 {
296 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
297 rule_number, mapping_find(encoding_type_m,
298 this->rules[rule_number].type));
299 return PARSE_ERROR;
300 }
301 if (this->bit_pos)
302 {
303 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
304 rule_number, mapping_find(encoding_type_m,
305 this->rules[rule_number].type), this->bit_pos);
306 return PARSE_ERROR;
307 }
308
309 /* caller interested in result ? */
310 if (output_pos != NULL)
311 {
312 *output_pos = *(this->byte_pos);
313 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
314 }
315 this->byte_pos++;
316
317 return SUCCESS;
318 }
319
320 /**
321 * Implementation of private_parser_t.parse_uint15.
322 */
323 static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
324 {
325 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
326 {
327 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
328 rule_number, mapping_find(encoding_type_m,
329 this->rules[rule_number].type));
330 return PARSE_ERROR;
331 }
332 if (this->bit_pos != 1)
333 {
334 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
335 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
336 this->bit_pos);
337 return PARSE_ERROR;
338 }
339 /* caller interested in result ? */
340 if (output_pos != NULL)
341 {
342 *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
343 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
344 }
345 this->byte_pos += 2;
346 this->bit_pos = 0;
347
348 return SUCCESS;
349 }
350
351 /**
352 * Implementation of private_parser_t.parse_uint16.
353 */
354 static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
355 {
356 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
357 {
358 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
359 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
360 return PARSE_ERROR;
361 }
362 if (this->bit_pos)
363 {
364 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
365 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
366 this->bit_pos);
367 return PARSE_ERROR;
368 }
369 /* caller interested in result ? */
370 if (output_pos != NULL)
371 {
372 *output_pos = ntohs(*((u_int16_t*)this->byte_pos));
373
374 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
375 }
376 this->byte_pos += 2;
377
378 return SUCCESS;
379 }
380 /**
381 * Implementation of private_parser_t.parse_uint32.
382 */
383 static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
384 {
385 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
386 {
387 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
388 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
389 return PARSE_ERROR;
390 }
391 if (this->bit_pos)
392 {
393 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
394 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
395 this->bit_pos);
396 return PARSE_ERROR;
397 }
398 /* caller interested in result ? */
399 if (output_pos != NULL)
400 {
401 *output_pos = ntohl(*((u_int32_t*)this->byte_pos));
402
403 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
404 }
405 this->byte_pos += 4;
406
407 return SUCCESS;
408 }
409
410 /**
411 * Implementation of private_parser_t.parse_uint64.
412 */
413 static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
414 {
415 if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
416 {
417 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
418 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
419 return PARSE_ERROR;
420 }
421 if (this->bit_pos)
422 {
423 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
424 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
425 this->bit_pos);
426 return PARSE_ERROR;
427 }
428 /* caller interested in result ? */
429 if (output_pos != NULL)
430 {
431 /* assuming little endian host order */
432 *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
433 *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
434
435 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, 8);
436 }
437 this->byte_pos += 8;
438
439 return SUCCESS;
440 }
441
442 /**
443 * Implementation of private_parser_t.parse_bytes.
444 */
445 static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
446 {
447 if (this->byte_pos + bytes > this->input_roof)
448 {
449 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
450 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
451 return PARSE_ERROR;
452 }
453 if (this->bit_pos)
454 {
455 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
456 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
457 this->bit_pos);
458 return PARSE_ERROR;
459 }
460
461 /* caller interested in result ? */
462 if (output_pos != NULL)
463 {
464 memcpy(output_pos,this->byte_pos,bytes);
465
466 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, bytes);
467 }
468 this->byte_pos += bytes;
469
470 return SUCCESS;
471 }
472
473 /**
474 * Implementation of private_parser_t.parse_bit.
475 */
476 static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
477 {
478 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
479 {
480 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
481 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
482 return PARSE_ERROR;
483 }
484 /* caller interested in result ? */
485 if (output_pos != NULL)
486 {
487 u_int8_t mask;
488 mask = 0x01 << (7 - this->bit_pos);
489 *output_pos = *this->byte_pos & mask;
490
491 if (*output_pos)
492 {
493 /* set to a "clean", comparable true */
494 *output_pos = TRUE;
495 }
496
497 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
498 }
499 this->bit_pos = (this->bit_pos + 1) % 8;
500 if (this->bit_pos == 0)
501 {
502 this->byte_pos++;
503 }
504
505 return SUCCESS;
506 }
507
508 /**
509 * Implementation of private_parser_t.parse_list.
510 */
511 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)
512 {
513 linked_list_t * list = *output_pos;
514
515 if (length < 0)
516 {
517 this->logger->log(this->logger, ERROR|LEVEL1, " invalid length for rule %d %s",
518 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
519 return PARSE_ERROR;
520 }
521
522 if (this->bit_pos)
523 {
524 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
525 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
526 return PARSE_ERROR;
527 }
528
529 while (length > 0)
530 {
531 u_int8_t *pos_before = this->byte_pos;
532 payload_t *payload;
533 status_t status;
534 this->logger->log(this->logger, CONTROL|LEVEL1, " %d bytes left, parsing recursivly %s",
535 length, mapping_find(payload_type_m, payload_type));
536 status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
537 if (status != SUCCESS)
538 {
539 this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed",
540 mapping_find(payload_type_m, payload_type));
541 return status;
542 }
543 list->insert_last(list, payload);
544 length -= this->byte_pos - pos_before;
545 }
546 *output_pos = list;
547 return SUCCESS;
548 }
549
550 /**
551 * Implementation of private_parser_t.parse_chunk.
552 */
553 static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
554 {
555 if (this->byte_pos + length > this->input_roof)
556 {
557 this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s",
558 length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
559 return PARSE_ERROR;
560 }
561 if (this->bit_pos)
562 {
563 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
564 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
565 return PARSE_ERROR;
566 }
567 if (output_pos != NULL)
568 {
569 output_pos->len = length;
570 output_pos->ptr = malloc(length);
571 memcpy(output_pos->ptr, this->byte_pos, length);
572 }
573 this->byte_pos += length;
574 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos->ptr, length);
575
576 return SUCCESS;
577 }
578
579 /**
580 * Implementation of parser_t.parse_payload.
581 */
582 static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
583 {
584 payload_t *pld;
585 void *output;
586 size_t rule_count, payload_length, spi_size, attribute_length;
587 u_int16_t ts_type;
588 bool attribute_format;
589 int rule_number;
590 encoding_rule_t *rule;
591
592 /* create instance of the payload to parse */
593 pld = payload_create(payload_type);
594
595 this->logger->log(this->logger, CONTROL|LEVEL1, "parsing %s payload, %d bytes left",
596 mapping_find(payload_type_m, payload_type),
597 this->input_roof-this->byte_pos);
598
599 this->logger->log_bytes(this->logger, RAW|LEVEL3, "parsing payload from", this->byte_pos,
600 this->input_roof-this->byte_pos);
601
602 if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
603 {
604 this->logger->log(this->logger, ERROR|LEVEL1, " payload type %d is unknown, handling as %s",
605 payload_type, mapping_find(payload_type_m, UNKNOWN_PAYLOAD));
606 }
607
608 /* base pointer for output, avoids casting in every rule */
609 output = pld;
610
611 /* parse the payload with its own rulse */
612 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
613 for (rule_number = 0; rule_number < rule_count; rule_number++)
614 {
615 rule = &(this->rules[rule_number]);
616 this->logger->log(this->logger, CONTROL|LEVEL2, " parsing rule %d %s",
617 rule_number, mapping_find(encoding_type_m, rule->type));
618 switch (rule->type)
619 {
620 case U_INT_4:
621 {
622 if (this->parse_uint4(this, rule_number, output + rule->offset) != SUCCESS)
623 {
624 pld->destroy(pld);
625 return PARSE_ERROR;
626 }
627 break;
628 }
629 case U_INT_8:
630 {
631 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
632 {
633 pld->destroy(pld);
634 return PARSE_ERROR;
635 }
636 break;
637 }
638 case U_INT_16:
639 {
640 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
641 {
642 pld->destroy(pld);
643 return PARSE_ERROR;
644 }
645 break;
646 }
647 case U_INT_32:
648 {
649 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
650 {
651 pld->destroy(pld);
652 return PARSE_ERROR;
653 }
654 break;
655 }
656 case U_INT_64:
657 {
658 if (this->parse_uint64(this, rule_number, output + rule->offset) != SUCCESS)
659 {
660 pld->destroy(pld);
661 return PARSE_ERROR;
662 }
663 break;
664 }
665 case IKE_SPI:
666 {
667 if (this->parse_bytes(this, rule_number, output + rule->offset,8) != SUCCESS)
668 {
669 pld->destroy(pld);
670 return PARSE_ERROR;
671 }
672 break;
673 }
674 case RESERVED_BIT:
675 {
676 if (this->parse_bit(this, rule_number, NULL) != SUCCESS)
677 {
678 pld->destroy(pld);
679 return PARSE_ERROR;
680 }
681 break;
682 }
683 case RESERVED_BYTE:
684 {
685 if (this->parse_uint8(this, rule_number, NULL) != SUCCESS)
686 {
687 pld->destroy(pld);
688 return PARSE_ERROR;
689 }
690 break;
691 }
692 case FLAG:
693 {
694 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
695 {
696 pld->destroy(pld);
697 return PARSE_ERROR;
698 }
699 break;
700 }
701 case PAYLOAD_LENGTH:
702 {
703 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
704 {
705 pld->destroy(pld);
706 return PARSE_ERROR;
707 }
708 payload_length = *(u_int16_t*)(output + rule->offset);
709 break;
710 }
711 case HEADER_LENGTH:
712 {
713 if (this->parse_uint32(this, rule_number, output + rule->offset) != SUCCESS)
714 {
715 pld->destroy(pld);
716 return PARSE_ERROR;
717 }
718 break;
719 }
720 case SPI_SIZE:
721 {
722 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
723 {
724 pld->destroy(pld);
725 return PARSE_ERROR;
726 }
727 spi_size = *(u_int8_t*)(output + rule->offset);
728 break;
729 }
730 case SPI:
731 {
732 if (this->parse_chunk(this, rule_number, output + rule->offset, spi_size) != SUCCESS)
733 {
734 pld->destroy(pld);
735 return PARSE_ERROR;
736 }
737 break;
738 }
739 case PROPOSALS:
740 {
741 size_t proposals_length = payload_length - SA_PAYLOAD_HEADER_LENGTH;
742 if (this->parse_list(this, rule_number, output + rule->offset, PROPOSAL_SUBSTRUCTURE, proposals_length) != SUCCESS)
743 {
744 pld->destroy(pld);
745 return PARSE_ERROR;
746 }
747 break;
748 }
749 case TRANSFORMS:
750 {
751 size_t transforms_length = payload_length - spi_size - PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH;
752 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_SUBSTRUCTURE, transforms_length) != SUCCESS)
753 {
754 pld->destroy(pld);
755 return PARSE_ERROR;
756 }
757 break;
758 }
759 case TRANSFORM_ATTRIBUTES:
760 {
761 size_t transform_a_length = payload_length - TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
762 if (this->parse_list(this, rule_number, output + rule->offset, TRANSFORM_ATTRIBUTE, transform_a_length) != SUCCESS)
763 {
764 pld->destroy(pld);
765 return PARSE_ERROR;
766 }
767 break;
768 }
769 case CONFIGURATION_ATTRIBUTES:
770 {
771 size_t configuration_attributes_length = payload_length - CP_PAYLOAD_HEADER_LENGTH;
772 if (this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, configuration_attributes_length) != SUCCESS)
773 {
774 pld->destroy(pld);
775 return PARSE_ERROR;
776 }
777 break;
778 }
779 case ATTRIBUTE_FORMAT:
780 {
781 if (this->parse_bit(this, rule_number, output + rule->offset) != SUCCESS)
782 {
783 pld->destroy(pld);
784 return PARSE_ERROR;
785 }
786 attribute_format = *(bool*)(output + rule->offset);
787 break;
788 }
789 case ATTRIBUTE_TYPE:
790 {
791 if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
792 {
793 pld->destroy(pld);
794 return PARSE_ERROR;
795 }
796 attribute_format = *(bool*)(output + rule->offset);
797 break;
798 }
799 case CONFIGURATION_ATTRIBUTE_LENGTH:
800 {
801 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
802 {
803 pld->destroy(pld);
804 return PARSE_ERROR;
805 }
806 attribute_length = *(u_int16_t*)(output + rule->offset);
807 break;
808 }
809 case ATTRIBUTE_LENGTH_OR_VALUE:
810 {
811 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
812 {
813 pld->destroy(pld);
814 return PARSE_ERROR;
815 }
816 attribute_length = *(u_int16_t*)(output + rule->offset);
817 break;
818 }
819 case ATTRIBUTE_VALUE:
820 {
821 if (attribute_format == FALSE)
822 {
823 if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
824 {
825 pld->destroy(pld);
826 return PARSE_ERROR;
827 }
828 }
829 break;
830 }
831 case NONCE_DATA:
832 {
833 size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH;
834 if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
835 {
836 pld->destroy(pld);
837 return PARSE_ERROR;
838 }
839 break;
840 }
841 case ID_DATA:
842 {
843 size_t data_length = payload_length - ID_PAYLOAD_HEADER_LENGTH;
844 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
845 {
846 pld->destroy(pld);
847 return PARSE_ERROR;
848 }
849 break;
850 }
851 case AUTH_DATA:
852 {
853 size_t data_length = payload_length - AUTH_PAYLOAD_HEADER_LENGTH;
854 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
855 {
856 pld->destroy(pld);
857 return PARSE_ERROR;
858 }
859 break;
860 }
861 case CERT_DATA:
862 {
863 size_t data_length = payload_length - CERT_PAYLOAD_HEADER_LENGTH;
864 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
865 {
866 pld->destroy(pld);
867 return PARSE_ERROR;
868 }
869 break;
870 }
871 case CERTREQ_DATA:
872 {
873 size_t data_length = payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH;
874 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
875 {
876 pld->destroy(pld);
877 return PARSE_ERROR;
878 }
879 break;
880 }
881 case EAP_MESSAGE:
882 {
883 size_t data_length = payload_length - EAP_PAYLOAD_HEADER_LENGTH;
884 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
885 {
886 pld->destroy(pld);
887 return PARSE_ERROR;
888 }
889 break;
890 }
891 case SPIS:
892 {
893 size_t data_length = payload_length - DELETE_PAYLOAD_HEADER_LENGTH;
894 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
895 {
896 pld->destroy(pld);
897 return PARSE_ERROR;
898 }
899 break;
900 }
901 case VID_DATA:
902 {
903 size_t data_length = payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH;
904 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
905 {
906 pld->destroy(pld);
907 return PARSE_ERROR;
908 }
909 break;
910 }
911 case CONFIGURATION_ATTRIBUTE_VALUE:
912 {
913 size_t data_length = attribute_length;
914 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
915 {
916 pld->destroy(pld);
917 return PARSE_ERROR;
918 }
919 break;
920 }
921 case KEY_EXCHANGE_DATA:
922 {
923 size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH;
924 if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS)
925 {
926 pld->destroy(pld);
927 return PARSE_ERROR;
928 }
929 break;
930 }
931 case NOTIFICATION_DATA:
932 {
933 size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size;
934 if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS)
935 {
936 pld->destroy(pld);
937 return PARSE_ERROR;
938 }
939 break;
940 }
941 case ENCRYPTED_DATA:
942 {
943 size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH;
944 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
945 {
946 pld->destroy(pld);
947 return PARSE_ERROR;
948 }
949 break;
950 }
951 case TS_TYPE:
952 {
953 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
954 {
955 pld->destroy(pld);
956 return PARSE_ERROR;
957 }
958 ts_type = *(u_int8_t*)(output + rule->offset);
959 break;
960 }
961 case ADDRESS:
962 {
963 size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
964 if (this->parse_chunk(this, rule_number, output + rule->offset,address_length) != SUCCESS)
965 {
966 pld->destroy(pld);
967 return PARSE_ERROR;
968 }
969 break;
970 }
971 case TRAFFIC_SELECTORS:
972 {
973 size_t traffic_selectors_length = payload_length - TS_PAYLOAD_HEADER_LENGTH;
974 if (this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic_selectors_length) != SUCCESS)
975 {
976 pld->destroy(pld);
977 return PARSE_ERROR;
978 }
979 break;
980 }
981 case UNKNOWN_PAYLOAD:
982 {
983 size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH;
984 if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS)
985 {
986 pld->destroy(pld);
987 return PARSE_ERROR;
988 }
989 break;
990 }
991 default:
992 {
993 this->logger->log(this->logger, ERROR, " no rule to parse rule %d %s (%d)", rule_number, mapping_find(encoding_type_m, rule->type), rule->type);
994 pld->destroy(pld);
995 return PARSE_ERROR;
996 }
997 }
998 /* process next rulue */
999 rule++;
1000 }
1001
1002 *payload = pld;
1003 this->logger->log(this->logger, CONTROL|LEVEL2, "parsing %s payload finished.",
1004 mapping_find(payload_type_m, payload_type));
1005 return SUCCESS;
1006 }
1007
1008 /**
1009 * Implementation of parser_t.get_remaining_byte_count.
1010 */
1011 static int get_remaining_byte_count (private_parser_t *this)
1012 {
1013 int count = (this->input_roof - this->byte_pos);
1014 return count;
1015 }
1016
1017 /**
1018 * Implementation of parser_t.reset_context.
1019 */
1020 static void reset_context (private_parser_t *this)
1021 {
1022 this->byte_pos = this->input;
1023 this->bit_pos = 0;
1024 }
1025
1026 /**
1027 * Implementation of parser_t.destroy.
1028 */
1029 static void destroy(private_parser_t *this)
1030 {
1031 free(this);
1032 }
1033
1034 /*
1035 * Described in header.
1036 */
1037 parser_t *parser_create(chunk_t data)
1038 {
1039 private_parser_t *this = malloc_thing(private_parser_t);
1040
1041 this->logger = logger_manager->get_logger(logger_manager, PARSER);
1042
1043 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
1044 this->public.reset_context = (void(*)(parser_t*)) reset_context;
1045 this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count;
1046 this->public.destroy = (void(*)(parser_t*)) destroy;
1047
1048 this->parse_uint4 = parse_uint4;
1049 this->parse_uint8 = parse_uint8;
1050 this->parse_uint15 = parse_uint15;
1051 this->parse_uint16 = parse_uint16;
1052 this->parse_uint32 = parse_uint32;
1053 this->parse_uint64 = parse_uint64;
1054 this->parse_bytes = parse_bytes;
1055 this->parse_bit = parse_bit;
1056 this->parse_list = parse_list;
1057 this->parse_chunk = parse_chunk;
1058
1059 this->input = data.ptr;
1060 this->byte_pos = data.ptr;
1061 this->bit_pos = 0;
1062 this->input_roof = data.ptr + data.len;
1063
1064 return (parser_t*)this;
1065 }
1066