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