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