Annotation of embedaddon/strongswan/src/libcharon/encoding/parser.c, revision 1.1.1.1
1.1 misho 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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>