]> git.ipfire.org Git - thirdparty/strongswan.git/blob - programs/charon/charon/encoding/parser.c
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / charon / charon / encoding / parser.c
1 /**
2 * @file parser.c
3 *
4 * @brief Implementation of parser_t.
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 #include <string.h>
26
27 #include "parser.h"
28
29 #include <types.h>
30 #include <definitions.h>
31 #include <daemon.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/id_payload.h>
43 #include <encoding/payloads/notify_payload.h>
44 #include <encoding/payloads/encryption_payload.h>
45 #include <encoding/payloads/auth_payload.h>
46 #include <encoding/payloads/cert_payload.h>
47 #include <encoding/payloads/certreq_payload.h>
48 #include <encoding/payloads/ts_payload.h>
49 #include <encoding/payloads/delete_payload.h>
50 #include <encoding/payloads/vendor_id_payload.h>
51 #include <encoding/payloads/cp_payload.h>
52 #include <encoding/payloads/configuration_attribute.h>
53 #include <encoding/payloads/eap_payload.h>
54 #include <encoding/payloads/unknown_payload.h>
55
56
57 typedef struct private_parser_t private_parser_t;
58
59 /**
60 * Private data stored in a context.
61 *
62 * Contains pointers and counters to store current state.
63 */
64 struct private_parser_t {
65 /**
66 * Public members, see parser_t.
67 */
68 parser_t public;
69
70 /**
71 * @brief Parse a 4-Bit unsigned integer from the current parsing position.
72 *
73 * @param this parser_t object
74 * @param rule_number number of current rule
75 * @param[out] output_pos pointer where to write the parsed result
76 * @return
77 * - SUCCESS or
78 * - PARSE_ERROR when not successful
79 */
80 status_t (*parse_uint4) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
81
82 /**
83 * @brief Parse a 8-Bit unsigned integer from the current parsing position.
84 *
85 * @param this parser_t object
86 * @param rule_number number of current rule
87 * @param[out] output_pos pointer where to write the parsed result
88 * @return
89 * - SUCCESS or
90 * - PARSE_ERROR when not successful
91 */
92 status_t (*parse_uint8) (private_parser_t *this, int rule_number, u_int8_t *output_pos);
93
94 /**
95 * @brief Parse a 15-Bit unsigned integer from the current parsing position.
96 *
97 * This is a special case used for ATTRIBUTE_TYPE.
98 * Big-/Little-endian conversion is done here.
99 *
100 * @param this parser_t object
101 * @param rule_number number of current rule
102 * @param[out] output_pos pointer where to write the parsed result
103 * @return
104 * - SUCCESS or
105 * - PARSE_ERROR when not successful
106 */
107 status_t (*parse_uint15) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
108
109 /**
110 * @brief Parse a 16-Bit unsigned integer from the current parsing position.
111 *
112 * Big-/Little-endian conversion is done here.
113 *
114 * @param this parser_t object
115 * @param rule_number number of current rule
116 * @param[out] output_pos pointer where to write the parsed result
117 * @return
118 * - SUCCESS or
119 * - PARSE_ERROR when not successful
120 */
121 status_t (*parse_uint16) (private_parser_t *this, int rule_number, u_int16_t *output_pos);
122
123 /**
124 * @brief Parse a 32-Bit unsigned integer from the current parsing position.
125 *
126 * Big-/Little-endian conversion is done here.
127 *
128 * @param this parser_t object
129 * @param rule_number number of current rule
130 * @param[out] output_pos pointer where to write the parsed result
131 * @return
132 * - SUCCESS or
133 * - PARSE_ERROR when not successful
134 */
135 status_t (*parse_uint32) (private_parser_t *this, int rule_number, u_int32_t *output_pos);
136
137 /**
138 * @brief Parse a 64-Bit unsigned integer from the current parsing position.
139 *
140 * @todo add support for big-endian machines.
141 *
142 * @param this parser_t object
143 * @param rule_number number of current rule
144 * @param[out] output_pos pointer where to write the parsed result
145 * @return
146 * - SUCCESS or
147 * - PARSE_ERROR when not successful
148 */
149 status_t (*parse_uint64) (private_parser_t *this, int rule_number, u_int64_t *output_pos);
150
151 /**
152 * @brief Parse a given amount of bytes and writes them to a specific location
153 *
154 * @param this parser_t object
155 * @param rule_number number of current rule
156 * @param[out] output_pos pointer where to write the parsed result
157 * @param bytes number of bytes to parse
158 * @return
159 * - SUCCESS or
160 * - PARSE_ERROR when not successful
161 */
162 status_t (*parse_bytes) (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes);
163
164 /**
165 * @brief Parse a single Bit from the current parsing position
166 *
167 * @param this parser_t object
168 * @param rule_number number of current rule
169 * @param[out] output_pos pointer where to write the parsed result
170 * @return
171 * - SUCCESS or
172 * - PARSE_ERROR when not successful
173 */
174 status_t (*parse_bit) (private_parser_t *this, int rule_number, bool *output_pos);
175
176 /**
177 * @brief Parse substructures in a list
178 *
179 * This function calls the parser recursivly to parse contained substructures
180 * in a linked_list_t. The list must already be created. Payload defines
181 * the type of the substructures. parsing is continued until the specified length
182 * is completely parsed.
183 *
184 * @param this parser_t object
185 * @param rule_number number of current rule
186 * @param[out] output_pos pointer of a linked_list where substructures are added
187 * @param payload_type type of the contained substructures to parse
188 * @param length number of bytes to parse in this list
189 * @return
190 * - SUCCESS or
191 * - PARSE_ERROR when not successful
192 */
193 status_t (*parse_list) (private_parser_t *this, int rule_number, linked_list_t **output_pos, payload_type_t payload_ype, size_t length);
194
195 /**
196 * @brief Parse data from current parsing position in a chunk.
197 *
198 * This function clones length number of bytes to output_pos, without
199 * modifiyng them. Space will be allocated and must be freed by caller.
200 *
201 * @param this parser_t object
202 * @param rule_number number of current rule
203 * @param[out] output_pos pointer of a chunk which will point to the allocated data
204 * @param length number of bytes to clone
205 * @return
206 * - SUCCESS or
207 * - PARSE_ERROR when not successful
208 */
209 status_t (*parse_chunk) (private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length);
210
211 /**
212 * Current bit for reading in input data.
213 */
214 u_int8_t bit_pos;
215
216 /**
217 * Current byte for reading in input data.
218 */
219 u_int8_t *byte_pos;
220
221 /**
222 * Input data to parse.
223 */
224 u_int8_t *input;
225
226 /**
227 * Roof of input, used for length-checking.
228 */
229 u_int8_t *input_roof;
230
231 /**
232 * Set of encoding rules for this parsing session.
233 */
234 encoding_rule_t *rules;
235
236 /**
237 * Assigned logger_t object.
238 */
239 logger_t *logger;
240 };
241
242 /**
243 * Implementation of private_parser_t.parse_uint4.
244 */
245 static status_t parse_uint4(private_parser_t *this, int rule_number, u_int8_t *output_pos)
246 {
247 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
248 {
249 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
250 rule_number, mapping_find(encoding_type_m,
251 this->rules[rule_number].type));
252 return PARSE_ERROR;
253 }
254 switch (this->bit_pos)
255 {
256 case 0:
257 /* caller interested in result ? */
258 if (output_pos != NULL)
259 {
260 *output_pos = *(this->byte_pos) >> 4;
261 }
262 this->bit_pos = 4;
263 break;
264 case 4:
265 /* caller interested in result ? */
266 if (output_pos != NULL)
267 {
268 *output_pos = *(this->byte_pos) & 0x0F;
269 }
270 this->bit_pos = 0;
271 this->byte_pos++;
272 break;
273 default:
274 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
275 rule_number, mapping_find(encoding_type_m,
276 this->rules[rule_number].type), this->bit_pos);
277 return PARSE_ERROR;
278 }
279
280 if (output_pos != NULL)
281 {
282 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
283 }
284
285 return SUCCESS;
286 }
287
288 /**
289 * Implementation of private_parser_t.parse_uint8.
290 */
291 static status_t parse_uint8(private_parser_t *this, int rule_number, u_int8_t *output_pos)
292 {
293 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
294 {
295 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
296 rule_number, mapping_find(encoding_type_m,
297 this->rules[rule_number].type));
298 return PARSE_ERROR;
299 }
300 if (this->bit_pos)
301 {
302 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
303 rule_number, mapping_find(encoding_type_m,
304 this->rules[rule_number].type), this->bit_pos);
305 return PARSE_ERROR;
306 }
307
308 /* caller interested in result ? */
309 if (output_pos != NULL)
310 {
311 *output_pos = *(this->byte_pos);
312 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
313 }
314 this->byte_pos++;
315
316 return SUCCESS;
317 }
318
319 /**
320 * Implementation of private_parser_t.parse_uint15.
321 */
322 static status_t parse_uint15(private_parser_t *this, int rule_number, u_int16_t *output_pos)
323 {
324 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
325 {
326 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
327 rule_number, mapping_find(encoding_type_m,
328 this->rules[rule_number].type));
329 return PARSE_ERROR;
330 }
331 if (this->bit_pos != 1)
332 {
333 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
334 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
335 this->bit_pos);
336 return PARSE_ERROR;
337 }
338 /* caller interested in result ? */
339 if (output_pos != NULL)
340 {
341 *output_pos = ntohs(*((u_int16_t*)this->byte_pos)) & ~0x8000;
342 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
343 }
344 this->byte_pos += 2;
345 this->bit_pos = 0;
346
347 return SUCCESS;
348 }
349
350 /**
351 * Implementation of private_parser_t.parse_uint16.
352 */
353 static status_t parse_uint16(private_parser_t *this, int rule_number, u_int16_t *output_pos)
354 {
355 if (this->byte_pos + sizeof(u_int16_t) > this->input_roof)
356 {
357 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
358 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
359 return PARSE_ERROR;
360 }
361 if (this->bit_pos)
362 {
363 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
364 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
365 this->bit_pos);
366 return PARSE_ERROR;
367 }
368 /* caller interested in result ? */
369 if (output_pos != NULL)
370 {
371 *output_pos = ntohs(*((u_int16_t*)this->byte_pos));
372
373 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
374 }
375 this->byte_pos += 2;
376
377 return SUCCESS;
378 }
379 /**
380 * Implementation of private_parser_t.parse_uint32.
381 */
382 static status_t parse_uint32(private_parser_t *this, int rule_number, u_int32_t *output_pos)
383 {
384 if (this->byte_pos + sizeof(u_int32_t) > this->input_roof)
385 {
386 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
387 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
388 return PARSE_ERROR;
389 }
390 if (this->bit_pos)
391 {
392 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
393 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
394 this->bit_pos);
395 return PARSE_ERROR;
396 }
397 /* caller interested in result ? */
398 if (output_pos != NULL)
399 {
400 *output_pos = ntohl(*((u_int32_t*)this->byte_pos));
401
402 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
403 }
404 this->byte_pos += 4;
405
406 return SUCCESS;
407 }
408
409 /**
410 * Implementation of private_parser_t.parse_uint64.
411 */
412 static status_t parse_uint64(private_parser_t *this, int rule_number, u_int64_t *output_pos)
413 {
414 if (this->byte_pos + sizeof(u_int64_t) > this->input_roof)
415 {
416 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
417 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
418 return PARSE_ERROR;
419 }
420 if (this->bit_pos)
421 {
422 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
423 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
424 this->bit_pos);
425 return PARSE_ERROR;
426 }
427 /* caller interested in result ? */
428 if (output_pos != NULL)
429 {
430 /* assuming little endian host order */
431 *(output_pos + 1) = ntohl(*((u_int32_t*)this->byte_pos));
432 *output_pos = ntohl(*(((u_int32_t*)this->byte_pos) + 1));
433
434 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, 8);
435 }
436 this->byte_pos += 8;
437
438 return SUCCESS;
439 }
440
441 /**
442 * Implementation of private_parser_t.parse_bytes.
443 */
444 static status_t parse_bytes (private_parser_t *this, int rule_number, u_int8_t *output_pos,size_t bytes)
445 {
446 if (this->byte_pos + bytes > this->input_roof)
447 {
448 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
449 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
450 return PARSE_ERROR;
451 }
452 if (this->bit_pos)
453 {
454 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
455 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type),
456 this->bit_pos);
457 return PARSE_ERROR;
458 }
459
460 /* caller interested in result ? */
461 if (output_pos != NULL)
462 {
463 memcpy(output_pos,this->byte_pos,bytes);
464
465 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos, bytes);
466 }
467 this->byte_pos += bytes;
468
469 return SUCCESS;
470 }
471
472 /**
473 * Implementation of private_parser_t.parse_bit.
474 */
475 static status_t parse_bit(private_parser_t *this, int rule_number, bool *output_pos)
476 {
477 if (this->byte_pos + sizeof(u_int8_t) > this->input_roof)
478 {
479 this->logger->log(this->logger, ERROR|LEVEL1, " not enough input to parse rule %d %s",
480 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
481 return PARSE_ERROR;
482 }
483 /* caller interested in result ? */
484 if (output_pos != NULL)
485 {
486 u_int8_t mask;
487 mask = 0x01 << (7 - this->bit_pos);
488 *output_pos = *this->byte_pos & mask;
489
490 if (*output_pos)
491 {
492 /* set to a "clean", comparable true */
493 *output_pos = TRUE;
494 }
495
496 this->logger->log(this->logger, RAW|LEVEL2, " => %d", *output_pos);
497 }
498 this->bit_pos = (this->bit_pos + 1) % 8;
499 if (this->bit_pos == 0)
500 {
501 this->byte_pos++;
502 }
503
504 return SUCCESS;
505 }
506
507 /**
508 * Implementation of private_parser_t.parse_list.
509 */
510 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)
511 {
512 linked_list_t * list = *output_pos;
513
514 if (length < 0)
515 {
516 this->logger->log(this->logger, ERROR|LEVEL1, " invalid length for rule %d %s",
517 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
518 return PARSE_ERROR;
519 }
520
521 if (this->bit_pos)
522 {
523 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
524 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
525 return PARSE_ERROR;
526 }
527
528 while (length > 0)
529 {
530 u_int8_t *pos_before = this->byte_pos;
531 payload_t *payload;
532 status_t status;
533 this->logger->log(this->logger, CONTROL|LEVEL1, " %d bytes left, parsing recursivly %s",
534 length, mapping_find(payload_type_m, payload_type));
535 status = this->public.parse_payload((parser_t*)this, payload_type, &payload);
536 if (status != SUCCESS)
537 {
538 this->logger->log(this->logger, ERROR, " parsing of a %s substructure failed",
539 mapping_find(payload_type_m, payload_type));
540 return status;
541 }
542 list->insert_last(list, payload);
543 length -= this->byte_pos - pos_before;
544 }
545 *output_pos = list;
546 return SUCCESS;
547 }
548
549 /**
550 * Implementation of private_parser_t.parse_chunk.
551 */
552 static status_t parse_chunk(private_parser_t *this, int rule_number, chunk_t *output_pos, size_t length)
553 {
554 if (this->byte_pos + length > this->input_roof)
555 {
556 this->logger->log(this->logger, ERROR, " not enough input (%d bytes) to parse rule %d %s",
557 length, rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type));
558 return PARSE_ERROR;
559 }
560 if (this->bit_pos)
561 {
562 this->logger->log(this->logger, ERROR, " found rule %d %s on bitpos %d",
563 rule_number, mapping_find(encoding_type_m, this->rules[rule_number].type), this->bit_pos);
564 return PARSE_ERROR;
565 }
566 if (output_pos != NULL)
567 {
568 output_pos->len = length;
569 output_pos->ptr = malloc(length);
570 memcpy(output_pos->ptr, this->byte_pos, length);
571 }
572 this->byte_pos += length;
573 this->logger->log_bytes(this->logger, RAW|LEVEL2, " =>", (void*)output_pos->ptr, length);
574
575 return SUCCESS;
576 }
577
578 /**
579 * Implementation of parser_t.parse_payload.
580 */
581 static status_t parse_payload(private_parser_t *this, payload_type_t payload_type, payload_t **payload)
582 {
583 payload_t *pld;
584 void *output;
585 size_t rule_count, payload_length, spi_size, attribute_length;
586 u_int16_t ts_type;
587 bool attribute_format;
588 int rule_number;
589 encoding_rule_t *rule;
590
591 /* create instance of the payload to parse */
592 pld = payload_create(payload_type);
593
594 this->logger->log(this->logger, CONTROL|LEVEL1, "parsing %s payload, %d bytes left",
595 mapping_find(payload_type_m, payload_type),
596 this->input_roof-this->byte_pos);
597
598 this->logger->log_bytes(this->logger, RAW|LEVEL3, "parsing payload from", this->byte_pos,
599 this->input_roof-this->byte_pos);
600
601 if (pld->get_type(pld) == UNKNOWN_PAYLOAD)
602 {
603 this->logger->log(this->logger, ERROR|LEVEL1, " payload type %d is unknown, handling as %s",
604 payload_type, mapping_find(payload_type_m, UNKNOWN_PAYLOAD));
605 }
606
607 /* base pointer for output, avoids casting in every rule */
608 output = pld;
609
610 /* parse the payload with its own rulse */
611 pld->get_encoding_rules(pld, &(this->rules), &rule_count);
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|LEVEL2, " 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 CONFIGURATION_ATTRIBUTES:
769 {
770 size_t configuration_attributes_length = payload_length - CP_PAYLOAD_HEADER_LENGTH;
771 if (this->parse_list(this, rule_number, output + rule->offset, CONFIGURATION_ATTRIBUTE, configuration_attributes_length) != SUCCESS)
772 {
773 pld->destroy(pld);
774 return PARSE_ERROR;
775 }
776 break;
777 }
778 case ATTRIBUTE_FORMAT:
779 {
780 if (this->parse_bit(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_TYPE:
789 {
790 if (this->parse_uint15(this, rule_number, output + rule->offset) != SUCCESS)
791 {
792 pld->destroy(pld);
793 return PARSE_ERROR;
794 }
795 attribute_format = *(bool*)(output + rule->offset);
796 break;
797 }
798 case CONFIGURATION_ATTRIBUTE_LENGTH:
799 {
800 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
801 {
802 pld->destroy(pld);
803 return PARSE_ERROR;
804 }
805 attribute_length = *(u_int16_t*)(output + rule->offset);
806 break;
807 }
808 case ATTRIBUTE_LENGTH_OR_VALUE:
809 {
810 if (this->parse_uint16(this, rule_number, output + rule->offset) != SUCCESS)
811 {
812 pld->destroy(pld);
813 return PARSE_ERROR;
814 }
815 attribute_length = *(u_int16_t*)(output + rule->offset);
816 break;
817 }
818 case ATTRIBUTE_VALUE:
819 {
820 if (attribute_format == FALSE)
821 {
822 if (this->parse_chunk(this, rule_number, output + rule->offset, attribute_length) != SUCCESS)
823 {
824 pld->destroy(pld);
825 return PARSE_ERROR;
826 }
827 }
828 break;
829 }
830 case NONCE_DATA:
831 {
832 size_t nonce_length = payload_length - NONCE_PAYLOAD_HEADER_LENGTH;
833 if (this->parse_chunk(this, rule_number, output + rule->offset, nonce_length) != SUCCESS)
834 {
835 pld->destroy(pld);
836 return PARSE_ERROR;
837 }
838 break;
839 }
840 case ID_DATA:
841 {
842 size_t data_length = payload_length - ID_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 case AUTH_DATA:
851 {
852 size_t data_length = payload_length - AUTH_PAYLOAD_HEADER_LENGTH;
853 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
854 {
855 pld->destroy(pld);
856 return PARSE_ERROR;
857 }
858 break;
859 }
860 case CERT_DATA:
861 {
862 size_t data_length = payload_length - CERT_PAYLOAD_HEADER_LENGTH;
863 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
864 {
865 pld->destroy(pld);
866 return PARSE_ERROR;
867 }
868 break;
869 }
870 case CERTREQ_DATA:
871 {
872 size_t data_length = payload_length - CERTREQ_PAYLOAD_HEADER_LENGTH;
873 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
874 {
875 pld->destroy(pld);
876 return PARSE_ERROR;
877 }
878 break;
879 }
880 case EAP_MESSAGE:
881 {
882 size_t data_length = payload_length - EAP_PAYLOAD_HEADER_LENGTH;
883 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
884 {
885 pld->destroy(pld);
886 return PARSE_ERROR;
887 }
888 break;
889 }
890 case SPIS:
891 {
892 size_t data_length = payload_length - DELETE_PAYLOAD_HEADER_LENGTH;
893 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
894 {
895 pld->destroy(pld);
896 return PARSE_ERROR;
897 }
898 break;
899 }
900 case VID_DATA:
901 {
902 size_t data_length = payload_length - VENDOR_ID_PAYLOAD_HEADER_LENGTH;
903 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
904 {
905 pld->destroy(pld);
906 return PARSE_ERROR;
907 }
908 break;
909 }
910 case CONFIGURATION_ATTRIBUTE_VALUE:
911 {
912 size_t data_length = attribute_length;
913 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
914 {
915 pld->destroy(pld);
916 return PARSE_ERROR;
917 }
918 break;
919 }
920 case KEY_EXCHANGE_DATA:
921 {
922 size_t keydata_length = payload_length - KE_PAYLOAD_HEADER_LENGTH;
923 if (this->parse_chunk(this, rule_number, output + rule->offset, keydata_length) != SUCCESS)
924 {
925 pld->destroy(pld);
926 return PARSE_ERROR;
927 }
928 break;
929 }
930 case NOTIFICATION_DATA:
931 {
932 size_t notify_length = payload_length - NOTIFY_PAYLOAD_HEADER_LENGTH - spi_size;
933 if (this->parse_chunk(this, rule_number, output + rule->offset, notify_length) != SUCCESS)
934 {
935 pld->destroy(pld);
936 return PARSE_ERROR;
937 }
938 break;
939 }
940 case ENCRYPTED_DATA:
941 {
942 size_t data_length = payload_length - ENCRYPTION_PAYLOAD_HEADER_LENGTH;
943 if (this->parse_chunk(this, rule_number, output + rule->offset, data_length) != SUCCESS)
944 {
945 pld->destroy(pld);
946 return PARSE_ERROR;
947 }
948 break;
949 }
950 case TS_TYPE:
951 {
952 if (this->parse_uint8(this, rule_number, output + rule->offset) != SUCCESS)
953 {
954 pld->destroy(pld);
955 return PARSE_ERROR;
956 }
957 ts_type = *(u_int8_t*)(output + rule->offset);
958 break;
959 }
960 case ADDRESS:
961 {
962 size_t address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
963 if (this->parse_chunk(this, rule_number, output + rule->offset,address_length) != SUCCESS)
964 {
965 pld->destroy(pld);
966 return PARSE_ERROR;
967 }
968 break;
969 }
970 case TRAFFIC_SELECTORS:
971 {
972 size_t traffic_selectors_length = payload_length - TS_PAYLOAD_HEADER_LENGTH;
973 if (this->parse_list(this, rule_number, output + rule->offset, TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic_selectors_length) != SUCCESS)
974 {
975 pld->destroy(pld);
976 return PARSE_ERROR;
977 }
978 break;
979 }
980 case UNKNOWN_PAYLOAD:
981 {
982 size_t unknown_payload_data_length = payload_length - UNKNOWN_PAYLOAD_HEADER_LENGTH;
983 if (this->parse_chunk(this, rule_number, output + rule->offset, unknown_payload_data_length) != SUCCESS)
984 {
985 pld->destroy(pld);
986 return PARSE_ERROR;
987 }
988 break;
989 }
990 default:
991 {
992 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);
993 pld->destroy(pld);
994 return PARSE_ERROR;
995 }
996 }
997 /* process next rulue */
998 rule++;
999 }
1000
1001 *payload = pld;
1002 this->logger->log(this->logger, CONTROL|LEVEL2, "parsing %s payload finished.",
1003 mapping_find(payload_type_m, payload_type));
1004 return SUCCESS;
1005 }
1006
1007 /**
1008 * Implementation of parser_t.get_remaining_byte_count.
1009 */
1010 static int get_remaining_byte_count (private_parser_t *this)
1011 {
1012 int count = (this->input_roof - this->byte_pos);
1013 return count;
1014 }
1015
1016 /**
1017 * Implementation of parser_t.reset_context.
1018 */
1019 static void reset_context (private_parser_t *this)
1020 {
1021 this->byte_pos = this->input;
1022 this->bit_pos = 0;
1023 }
1024
1025 /**
1026 * Implementation of parser_t.destroy.
1027 */
1028 static void destroy(private_parser_t *this)
1029 {
1030 free(this);
1031 }
1032
1033 /*
1034 * Described in header.
1035 */
1036 parser_t *parser_create(chunk_t data)
1037 {
1038 private_parser_t *this = malloc_thing(private_parser_t);
1039
1040 this->logger = logger_manager->get_logger(logger_manager, PARSER);
1041
1042 this->public.parse_payload = (status_t(*)(parser_t*,payload_type_t,payload_t**)) parse_payload;
1043 this->public.reset_context = (void(*)(parser_t*)) reset_context;
1044 this->public.get_remaining_byte_count = (int (*) (parser_t *))get_remaining_byte_count;
1045 this->public.destroy = (void(*)(parser_t*)) destroy;
1046
1047 this->parse_uint4 = parse_uint4;
1048 this->parse_uint8 = parse_uint8;
1049 this->parse_uint15 = parse_uint15;
1050 this->parse_uint16 = parse_uint16;
1051 this->parse_uint32 = parse_uint32;
1052 this->parse_uint64 = parse_uint64;
1053 this->parse_bytes = parse_bytes;
1054 this->parse_bit = parse_bit;
1055 this->parse_list = parse_list;
1056 this->parse_chunk = parse_chunk;
1057
1058 this->input = data.ptr;
1059 this->byte_pos = data.ptr;
1060 this->bit_pos = 0;
1061 this->input_roof = data.ptr + data.len;
1062
1063 return (parser_t*)this;
1064 }
1065