]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/encoding/parser.c
Spelling fixes
[thirdparty/strongswan.git] / src / libcharon / encoding / parser.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * HSR Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include "parser.h"
21
22 #include <library.h>
23 #include <daemon.h>
24 #include <collections/linked_list.h>
25 #include <encoding/payloads/encodings.h>
26 #include <encoding/payloads/payload.h>
27 #include <encoding/payloads/sa_payload.h>
28 #include <encoding/payloads/proposal_substructure.h>
29 #include <encoding/payloads/transform_substructure.h>
30 #include <encoding/payloads/transform_attribute.h>
31 #include <encoding/payloads/ke_payload.h>
32 #include <encoding/payloads/nonce_payload.h>
33 #include <encoding/payloads/id_payload.h>
34 #include <encoding/payloads/notify_payload.h>
35 #include <encoding/payloads/encrypted_payload.h>
36 #include <encoding/payloads/auth_payload.h>
37 #include <encoding/payloads/cert_payload.h>
38 #include <encoding/payloads/certreq_payload.h>
39 #include <encoding/payloads/ts_payload.h>
40 #include <encoding/payloads/delete_payload.h>
41 #include <encoding/payloads/vendor_id_payload.h>
42 #include <encoding/payloads/cp_payload.h>
43 #include <encoding/payloads/configuration_attribute.h>
44 #include <encoding/payloads/eap_payload.h>
45 #include <encoding/payloads/unknown_payload.h>
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 * major IKE version
63 */
64 uint8_t major_version;
65
66 /**
67 * Current bit for reading in input data.
68 */
69 uint8_t bit_pos;
70
71 /**
72 * Current byte for reading in input data.
73 */
74 uint8_t *byte_pos;
75
76 /**
77 * Input data to parse.
78 */
79 uint8_t *input;
80
81 /**
82 * Roof of input, used for length-checking.
83 */
84 uint8_t *input_roof;
85
86 /**
87 * Set of encoding rules for this parsing session.
88 */
89 encoding_rule_t *rules;
90 };
91
92 /**
93 * Log invalid length error
94 */
95 static bool short_input(private_parser_t *this, int number)
96 {
97 DBG1(DBG_ENC, " not enough input to parse rule %d %N",
98 number, encoding_type_names, this->rules[number].type);
99 return FALSE;
100 }
101
102 /**
103 * Log unaligned rules
104 */
105 static bool bad_bitpos(private_parser_t *this, int number)
106 {
107 DBG1(DBG_ENC, " found rule %d %N on bitpos %d",
108 number, encoding_type_names, this->rules[number].type, this->bit_pos);
109 return FALSE;
110 }
111
112 /**
113 * Parse a 4-Bit unsigned integer from the current parsing position.
114 */
115 static bool parse_uint4(private_parser_t *this, int rule_number,
116 uint8_t *output_pos)
117 {
118 if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
119 {
120 return short_input(this, rule_number);
121 }
122 switch (this->bit_pos)
123 {
124 case 0:
125 if (output_pos)
126 {
127 *output_pos = *(this->byte_pos) >> 4;
128 }
129 this->bit_pos = 4;
130 break;
131 case 4:
132 if (output_pos)
133 {
134 *output_pos = *(this->byte_pos) & 0x0F;
135 }
136 this->bit_pos = 0;
137 this->byte_pos++;
138 break;
139 default:
140 return bad_bitpos(this, rule_number);
141 }
142 if (output_pos)
143 {
144 DBG3(DBG_ENC, " => %hhu", *output_pos);
145 }
146 return TRUE;
147 }
148
149 /**
150 * Parse a 8-Bit unsigned integer from the current parsing position.
151 */
152 static bool parse_uint8(private_parser_t *this, int rule_number,
153 uint8_t *output_pos)
154 {
155 if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
156 {
157 return short_input(this, rule_number);
158 }
159 if (this->bit_pos)
160 {
161 return bad_bitpos(this, rule_number);
162 }
163 if (output_pos)
164 {
165 *output_pos = *(this->byte_pos);
166 DBG3(DBG_ENC, " => %hhu", *output_pos);
167 }
168 this->byte_pos++;
169 return TRUE;
170 }
171
172 /**
173 * Parse a 15-Bit unsigned integer from the current parsing position.
174 */
175 static bool parse_uint15(private_parser_t *this, int rule_number,
176 uint16_t *output_pos)
177 {
178 if (this->byte_pos + sizeof(uint16_t) > this->input_roof)
179 {
180 return short_input(this, rule_number);
181 }
182 if (this->bit_pos != 1)
183 {
184 return bad_bitpos(this, rule_number);
185 }
186 if (output_pos)
187 {
188 memcpy(output_pos, this->byte_pos, sizeof(uint16_t));
189 *output_pos = ntohs(*output_pos) & ~0x8000;
190 DBG3(DBG_ENC, " => %hu", *output_pos);
191 }
192 this->byte_pos += sizeof(uint16_t);
193 this->bit_pos = 0;
194 return TRUE;
195 }
196
197 /**
198 * Parse a 16-Bit unsigned integer from the current parsing position.
199 */
200 static bool parse_uint16(private_parser_t *this, int rule_number,
201 uint16_t *output_pos)
202 {
203 if (this->byte_pos + sizeof(uint16_t) > this->input_roof)
204 {
205 return short_input(this, rule_number);
206 }
207 if (this->bit_pos)
208 {
209 return bad_bitpos(this, rule_number);
210 }
211 if (output_pos)
212 {
213 memcpy(output_pos, this->byte_pos, sizeof(uint16_t));
214 *output_pos = ntohs(*output_pos);
215 DBG3(DBG_ENC, " => %hu", *output_pos);
216 }
217 this->byte_pos += sizeof(uint16_t);
218 return TRUE;
219 }
220 /**
221 * Parse a 32-Bit unsigned integer from the current parsing position.
222 */
223 static bool parse_uint32(private_parser_t *this, int rule_number,
224 uint32_t *output_pos)
225 {
226 if (this->byte_pos + sizeof(uint32_t) > this->input_roof)
227 {
228 return short_input(this, rule_number);
229 }
230 if (this->bit_pos)
231 {
232 return bad_bitpos(this, rule_number);
233 }
234 if (output_pos)
235 {
236 memcpy(output_pos, this->byte_pos, sizeof(uint32_t));
237 *output_pos = ntohl(*output_pos);
238 DBG3(DBG_ENC, " => %u", *output_pos);
239 }
240 this->byte_pos += sizeof(uint32_t);
241 return TRUE;
242 }
243
244 /**
245 * Parse a given amount of bytes and writes them to a specific location
246 */
247 static bool parse_bytes(private_parser_t *this, int rule_number,
248 uint8_t *output_pos, int bytes)
249 {
250 if (this->byte_pos + bytes > this->input_roof)
251 {
252 return short_input(this, rule_number);
253 }
254 if (this->bit_pos)
255 {
256 return bad_bitpos(this, rule_number);
257 }
258 if (output_pos)
259 {
260 memcpy(output_pos, this->byte_pos, bytes);
261 DBG3(DBG_ENC, " %b", output_pos, bytes);
262 }
263 this->byte_pos += bytes;
264 return TRUE;
265 }
266
267 /**
268 * Parse a single Bit from the current parsing position
269 */
270 static bool parse_bit(private_parser_t *this, int rule_number,
271 bool *output_pos)
272 {
273 if (this->byte_pos + sizeof(uint8_t) > this->input_roof)
274 {
275 return short_input(this, rule_number);
276 }
277 if (output_pos)
278 {
279 uint8_t mask;
280 mask = 0x01 << (7 - this->bit_pos);
281 *output_pos = *this->byte_pos & mask;
282
283 if (*output_pos)
284 { /* set to a "clean", comparable true */
285 *output_pos = TRUE;
286 }
287 DBG3(DBG_ENC, " => %d", *output_pos);
288 }
289 this->bit_pos = (this->bit_pos + 1) % 8;
290 if (this->bit_pos == 0)
291 {
292 this->byte_pos++;
293 }
294 return TRUE;
295 }
296
297 /**
298 * Parse substructures in a list.
299 */
300 static bool parse_list(private_parser_t *this, int rule_number,
301 linked_list_t **output_pos, payload_type_t payload_type, int length)
302 {
303 linked_list_t *list = *output_pos;
304
305 if (length < 0)
306 {
307 return short_input(this, rule_number);
308 }
309 if (this->bit_pos)
310 {
311 return bad_bitpos(this, rule_number);
312 }
313 while (length > 0)
314 {
315 uint8_t *pos_before = this->byte_pos;
316 payload_t *payload;
317
318 DBG2(DBG_ENC, " %d bytes left, parsing recursively %N",
319 length, payload_type_names, payload_type);
320
321 if (this->public.parse_payload(&this->public, payload_type,
322 &payload) != SUCCESS)
323 {
324 DBG1(DBG_ENC, " parsing of a %N substructure failed",
325 payload_type_names, payload_type);
326 return FALSE;
327 }
328 list->insert_last(list, payload);
329 length -= this->byte_pos - pos_before;
330 }
331 if (length != 0)
332 { /* must yield exactly to zero */
333 DBG1(DBG_ENC, " length of %N substructure list invalid",
334 payload_type_names, payload_type);
335 return FALSE;
336 }
337 *output_pos = list;
338 return TRUE;
339 }
340
341 /**
342 * Parse data from current parsing position in a chunk.
343 */
344 static bool parse_chunk(private_parser_t *this, int rule_number,
345 chunk_t *output_pos, int length)
346 {
347 if (this->byte_pos + length > this->input_roof)
348 {
349 return short_input(this, rule_number);
350 }
351 if (this->bit_pos)
352 {
353 return bad_bitpos(this, rule_number);
354 }
355 if (output_pos)
356 {
357 *output_pos = chunk_alloc(length);
358 memcpy(output_pos->ptr, this->byte_pos, length);
359 DBG3(DBG_ENC, " %b", output_pos->ptr, length);
360 }
361 this->byte_pos += length;
362 return TRUE;
363 }
364
365 METHOD(parser_t, parse_payload, status_t,
366 private_parser_t *this, payload_type_t payload_type, payload_t **payload)
367 {
368 payload_t *pld;
369 void *output;
370 int payload_length = 0, spi_size = 0, attribute_length = 0, header_length;
371 uint16_t ts_type = 0;
372 bool attribute_format = FALSE;
373 int rule_number, rule_count;
374 encoding_rule_t *rule;
375
376 /* create instance of the payload to parse */
377 if (payload_is_known(payload_type, this->major_version))
378 {
379 pld = payload_create(payload_type);
380 }
381 else
382 {
383 pld = (payload_t*)unknown_payload_create(payload_type);
384 }
385
386 DBG2(DBG_ENC, "parsing %N payload, %d bytes left",
387 payload_type_names, payload_type, this->input_roof - this->byte_pos);
388
389 DBG3(DBG_ENC, "parsing payload from %b",
390 this->byte_pos, (u_int)(this->input_roof - this->byte_pos));
391
392 /* base pointer for output, avoids casting in every rule */
393 output = pld;
394 /* parse the payload with its own rules */
395 rule_count = pld->get_encoding_rules(pld, &this->rules);
396 for (rule_number = 0; rule_number < rule_count; rule_number++)
397 {
398 /* update header length for each rule, as it is dynamic (SPIs) */
399 header_length = pld->get_header_length(pld);
400
401 rule = &(this->rules[rule_number]);
402 DBG2(DBG_ENC, " parsing rule %d %N",
403 rule_number, encoding_type_names, rule->type);
404 switch ((int)rule->type)
405 {
406 case U_INT_4:
407 {
408 if (!parse_uint4(this, rule_number, output + rule->offset))
409 {
410 pld->destroy(pld);
411 return PARSE_ERROR;
412 }
413 break;
414 }
415 case U_INT_8:
416 case RESERVED_BYTE:
417 {
418 if (!parse_uint8(this, rule_number, output + rule->offset))
419 {
420 pld->destroy(pld);
421 return PARSE_ERROR;
422 }
423 break;
424 }
425 case U_INT_16:
426 {
427 if (!parse_uint16(this, rule_number, output + rule->offset))
428 {
429 pld->destroy(pld);
430 return PARSE_ERROR;
431 }
432 break;
433 }
434 case U_INT_32:
435 case HEADER_LENGTH:
436 {
437 if (!parse_uint32(this, rule_number, output + rule->offset))
438 {
439 pld->destroy(pld);
440 return PARSE_ERROR;
441 }
442 break;
443 }
444 case IKE_SPI:
445 {
446 if (!parse_bytes(this, rule_number, output + rule->offset, 8))
447 {
448 pld->destroy(pld);
449 return PARSE_ERROR;
450 }
451 break;
452 }
453 case RESERVED_BIT:
454 case FLAG:
455 {
456 if (!parse_bit(this, rule_number, output + rule->offset))
457 {
458 pld->destroy(pld);
459 return PARSE_ERROR;
460 }
461 break;
462 }
463 case PAYLOAD_LENGTH:
464 {
465 if (!parse_uint16(this, rule_number, output + rule->offset))
466 {
467 pld->destroy(pld);
468 return PARSE_ERROR;
469 }
470 /* parsed u_int16 should be aligned */
471 payload_length = *(uint16_t*)(output + rule->offset);
472 /* all payloads must have at least 4 bytes header */
473 if (payload_length < 4)
474 {
475 pld->destroy(pld);
476 return PARSE_ERROR;
477 }
478 break;
479 }
480 case SPI_SIZE:
481 {
482 if (!parse_uint8(this, rule_number, output + rule->offset))
483 {
484 pld->destroy(pld);
485 return PARSE_ERROR;
486 }
487 spi_size = *(uint8_t*)(output + rule->offset);
488 break;
489 }
490 case SPI:
491 {
492 if (!parse_chunk(this, rule_number, output + rule->offset,
493 spi_size))
494 {
495 pld->destroy(pld);
496 return PARSE_ERROR;
497 }
498 break;
499 }
500 case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
501 case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
502 case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
503 case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
504 case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
505 case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
506 case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
507 case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
508 case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
509 {
510 if (payload_length < header_length ||
511 !parse_list(this, rule_number, output + rule->offset,
512 rule->type - PAYLOAD_LIST,
513 payload_length - header_length))
514 {
515 pld->destroy(pld);
516 return PARSE_ERROR;
517 }
518 break;
519 }
520 case CHUNK_DATA:
521 {
522 if (payload_length < header_length ||
523 !parse_chunk(this, rule_number, output + rule->offset,
524 payload_length - header_length))
525 {
526 pld->destroy(pld);
527 return PARSE_ERROR;
528 }
529 break;
530 }
531 case ENCRYPTED_DATA:
532 {
533 if (!parse_chunk(this, rule_number, output + rule->offset,
534 this->input_roof - this->byte_pos))
535 {
536 pld->destroy(pld);
537 return PARSE_ERROR;
538 }
539 break;
540 }
541 case ATTRIBUTE_FORMAT:
542 {
543 if (!parse_bit(this, rule_number, output + rule->offset))
544 {
545 pld->destroy(pld);
546 return PARSE_ERROR;
547 }
548 attribute_format = *(bool*)(output + rule->offset);
549 break;
550 }
551 case ATTRIBUTE_TYPE:
552 {
553 if (!parse_uint15(this, rule_number, output + rule->offset))
554 {
555 pld->destroy(pld);
556 return PARSE_ERROR;
557 }
558 break;
559 }
560 case ATTRIBUTE_LENGTH:
561 {
562 if (!parse_uint16(this, rule_number, output + rule->offset))
563 {
564 pld->destroy(pld);
565 return PARSE_ERROR;
566 }
567 attribute_length = *(uint16_t*)(output + rule->offset);
568 break;
569 }
570 case ATTRIBUTE_LENGTH_OR_VALUE:
571 {
572 if (!parse_uint16(this, rule_number, output + rule->offset))
573 {
574 pld->destroy(pld);
575 return PARSE_ERROR;
576 }
577 attribute_length = *(uint16_t*)(output + rule->offset);
578 break;
579 }
580 case ATTRIBUTE_VALUE:
581 {
582 if (attribute_format == FALSE &&
583 !parse_chunk(this, rule_number, output + rule->offset,
584 attribute_length))
585 {
586 pld->destroy(pld);
587 return PARSE_ERROR;
588 }
589 break;
590 }
591 case TS_TYPE:
592 {
593 if (!parse_uint8(this, rule_number, output + rule->offset))
594 {
595 pld->destroy(pld);
596 return PARSE_ERROR;
597 }
598 ts_type = *(uint8_t*)(output + rule->offset);
599 break;
600 }
601 case ADDRESS:
602 {
603 int address_length = (ts_type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
604
605 if (!parse_chunk(this, rule_number, output + rule->offset,
606 address_length))
607 {
608 pld->destroy(pld);
609 return PARSE_ERROR;
610 }
611 break;
612 }
613 default:
614 {
615 DBG1(DBG_ENC, " no rule to parse rule %d %N",
616 rule_number, encoding_type_names, rule->type);
617 pld->destroy(pld);
618 return PARSE_ERROR;
619 }
620 }
621 /* process next rule */
622 rule++;
623 }
624
625 *payload = pld;
626 DBG2(DBG_ENC, "parsing %N payload finished",
627 payload_type_names, payload_type);
628 return SUCCESS;
629 }
630
631 METHOD(parser_t, get_remaining_byte_count, int,
632 private_parser_t *this)
633 {
634 return this->input_roof - this->byte_pos;
635 }
636
637 METHOD(parser_t, reset_context, void,
638 private_parser_t *this)
639 {
640 this->byte_pos = this->input;
641 this->bit_pos = 0;
642 }
643
644 METHOD(parser_t, set_major_version, void,
645 private_parser_t *this, uint8_t major_version)
646 {
647 this->major_version = major_version;
648 }
649
650 METHOD(parser_t, destroy, void,
651 private_parser_t *this)
652 {
653 free(this);
654 }
655
656 /*
657 * Described in header.
658 */
659 parser_t *parser_create(chunk_t data)
660 {
661 private_parser_t *this;
662
663 INIT(this,
664 .public = {
665 .parse_payload = _parse_payload,
666 .reset_context = _reset_context,
667 .set_major_version = _set_major_version,
668 .get_remaining_byte_count = _get_remaining_byte_count,
669 .destroy = _destroy,
670 },
671 .input = data.ptr,
672 .byte_pos = data.ptr,
673 .input_roof = data.ptr + data.len,
674 );
675
676 return &this->public;
677 }
678