Annotation of embedaddon/strongswan/src/libstrongswan/asn1/asn1_parser.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2006 Martin Will
3: * Copyright (C) 2000-2017 Andreas Steffen
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 <stdio.h>
18: #include <string.h>
19: #include <time.h>
20:
21: #include <utils/debug.h>
22:
23: #include "asn1.h"
24: #include "asn1_parser.h"
25:
26: #define ASN1_MAX_LEVEL 10
27:
28: typedef struct private_asn1_parser_t private_asn1_parser_t;
29:
30: /**
31: * Private data of an asn1_cxt_t object.
32: */
33: struct private_asn1_parser_t {
34: /**
35: * Public interface.
36: */
37: asn1_parser_t public;
38:
39: /**
40: * Syntax definition of ASN.1 object
41: */
42: asn1Object_t const *objects;
43:
44: /**
45: * Current syntax definition line
46: */
47: int line;
48:
49: /**
50: * Current stat of the parsing operation
51: */
52: bool success;
53:
54: /**
55: * Declare object data as private - use debug level 4 to log it
56: */
57: bool private;
58:
59: /**
60: * Top-most type is implicit - ignore it
61: */
62: bool implicit;
63:
64: /**
65: * Top-most parsing level - defaults to 0
66: */
67: u_int level0;
68:
69: /**
70: * Jump back address for loops for each level
71: */
72: int loopAddr[ASN1_MAX_LEVEL + 1];
73:
74: /**
75: * Current parsing pointer for each level
76: */
77: chunk_t blobs[ASN1_MAX_LEVEL + 2];
78:
79: /**
80: * Parsing a CHOICE on the current level ?
81: */
82: bool choice[ASN1_MAX_LEVEL + 2];
83:
84: };
85:
86: METHOD(asn1_parser_t, iterate, bool,
87: private_asn1_parser_t *this, int *objectID, chunk_t *object)
88: {
89: chunk_t *blob, *blob1, blob_ori;
90: u_char *start_ptr;
91: u_int level;
92: asn1Object_t obj;
93:
94: *object = chunk_empty;
95:
96: /* Advance to the next object syntax definition line */
97: obj = this->objects[++(this->line)];
98:
99: /* Terminate if the end of the object syntax definition has been reached */
100: if (obj.flags & ASN1_EXIT)
101: {
102: return FALSE;
103: }
104:
105: if (obj.flags & ASN1_END) /* end of loop or choice or option found */
106: {
107: if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
108: {
109: this->line = this->loopAddr[obj.level]; /* another iteration */
110: obj = this->objects[this->line];
111: }
112: else
113: {
114: this->loopAddr[obj.level] = 0; /* exit loop */
115:
116: if (obj.flags & ASN1_CHOICE) /* end of choices */
117: {
118: if (this->choice[obj.level+1])
119: {
120: DBG1(DBG_ASN, "L%d - %s: incorrect choice encoding",
121: this->level0 + obj.level, obj.name);
122: this->success = FALSE;
123: goto end;
124: }
125: }
126:
127: if (obj.flags & ASN1_CH) /* end of choice */
128: {
129: /* parsed a valid choice */
130: this->choice[obj.level] = FALSE;
131:
132: /* advance to end of choices */
133: do
134: {
135: this->line++;
136: }
137: while (!((this->objects[this->line].flags & ASN1_END) &&
138: (this->objects[this->line].flags & ASN1_CHOICE) &&
139: (this->objects[this->line].level == obj.level-1)));
140: this->line--;
141: }
142:
143: goto end;
144: }
145: }
146:
147: level = this->level0 + obj.level;
148: blob = this->blobs + obj.level;
149: blob_ori = *blob;
150: blob1 = blob + 1;
151: start_ptr = blob->ptr;
152:
153: /* handle ASN.1 defaults values */
154: if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
155: {
156: /* field is missing */
157: DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
158: if (obj.type & ASN1_CONSTRUCTED)
159: {
160: this->line++ ; /* skip context-specific tag */
161: }
162: goto end;
163: }
164:
165: /* handle ASN.1 options */
166: if ((obj.flags & ASN1_OPT)
167: && (blob->len == 0 || *start_ptr != obj.type))
168: {
169: /* advance to end of missing option field */
170: do
171: {
172: this->line++;
173: }
174: while (!((this->objects[this->line].flags & ASN1_END) &&
175: (this->objects[this->line].level == obj.level)));
176: goto end;
177: }
178:
179: /* an ASN.1 object must possess at least a tag and length field */
180: if (blob->len < 2)
181: {
182: DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
183: level, obj.name);
184: this->success = FALSE;
185: goto end;
186: }
187:
188: blob1->len = asn1_length(blob);
189:
190: if (blob1->len == ASN1_INVALID_LENGTH)
191: {
192: DBG1(DBG_ASN, "L%d - %s: length of ASN.1 object invalid or too large",
193: level, obj.name);
194: this->success = FALSE;
195: goto end;
196: }
197:
198: blob1->ptr = blob->ptr;
199: blob->ptr += blob1->len;
200: blob->len -= blob1->len;
201:
202: /* handle ASN.1 choice without explicit context encoding */
203: if ((obj.flags & ASN1_CHOICE) && obj.type == ASN1_EOC)
204: {
205: DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
206: this->choice[obj.level+1] = TRUE;
207: *blob1 = blob_ori;
208: goto end;
209: }
210:
211: /* return raw ASN.1 object without prior type checking */
212: if (obj.flags & ASN1_RAW)
213: {
214: DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
215: object->ptr = start_ptr;
216: object->len = (size_t)(blob->ptr - start_ptr);
217: goto end;
218: }
219:
220: if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
221: {
222: DBG2(DBG_ASN, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
223: level, obj.name, obj.type, *start_ptr);
224: DBG3(DBG_ASN, "%b", start_ptr, (u_int)(blob->ptr - start_ptr));
225: this->success = FALSE;
226: goto end;
227: }
228:
229: DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
230:
231: /* In case of "SEQUENCE OF" or "SET OF" start a loop */
232: if (obj.flags & ASN1_LOOP)
233: {
234: if (blob1->len > 0)
235: {
236: /* at least one item, start the loop */
237: this->loopAddr[obj.level] = this->line + 1;
238: }
239: else
240: {
241: /* no items, advance directly to end of loop */
242: do
243: {
244: this->line++;
245: }
246: while (!((this->objects[this->line].flags & ASN1_END) &&
247: (this->objects[this->line].level == obj.level)));
248: goto end;
249: }
250: }
251:
252: /* In case of a "CHOICE" start to scan for exactly one valid choice */
253: if (obj.flags & ASN1_CHOICE)
254: {
255: if (blob1->len == 0)
256: {
257: DBG1(DBG_ASN, "L%d - %s: contains no choice", level, obj.name);
258: this->success = FALSE;
259: goto end;
260: }
261: this->choice[obj.level+1] = TRUE;
262: }
263:
264: if (obj.flags & ASN1_OBJ)
265: {
266: object->ptr = start_ptr;
267: object->len = (size_t)(blob->ptr - start_ptr);
268: if (this->private)
269: {
270: DBG4(DBG_ASN, "%B", object);
271: }
272: else
273: {
274: DBG3(DBG_ASN, "%B", object);
275: }
276: }
277: else if (obj.flags & ASN1_BODY)
278: {
279: *object = *blob1;
280: asn1_debug_simple_object(*object, obj.type, this->private);
281: }
282:
283: end:
284: *objectID = this->line;
285: return this->success;
286: }
287:
288: METHOD(asn1_parser_t, get_level, u_int,
289: private_asn1_parser_t *this)
290: {
291: return this->level0 + this->objects[this->line].level;
292: }
293:
294: METHOD(asn1_parser_t, set_top_level, void,
295: private_asn1_parser_t *this, u_int level0)
296: {
297: this->level0 = level0;
298: }
299:
300: METHOD(asn1_parser_t, set_flags, void,
301: private_asn1_parser_t *this, bool implicit, bool private)
302: {
303: this->implicit = implicit;
304: this->private = private;
305: }
306:
307: METHOD(asn1_parser_t, success, bool,
308: private_asn1_parser_t *this)
309: {
310: return this->success;
311: }
312:
313: METHOD(asn1_parser_t, destroy, void,
314: private_asn1_parser_t *this)
315: {
316: free(this);
317: }
318:
319: /**
320: * Defined in header.
321: */
322: asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
323: {
324: private_asn1_parser_t *this;
325:
326: INIT(this,
327: .public = {
328: .iterate = _iterate,
329: .get_level = _get_level,
330: .set_top_level = _set_top_level,
331: .set_flags = _set_flags,
332: .success = _success,
333: .destroy = _destroy,
334: },
335: .objects = objects,
336: .blobs[0] = blob,
337: .line = -1,
338: .success = TRUE,
339: );
340:
341: return &this->public;
342: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>