8f524b5c6d1a8b07f1eb98facd60e07ad1daeff6
[strongswan.git] / src / libstrongswan / asn1 / asn1_parser.c
1 /*
2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2008 Andreas Steffen
4 *
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <time.h>
21
22 #include <debug.h>
23
24 #include "asn1.h"
25 #include "asn1_parser.h"
26
27 #define ASN1_MAX_LEVEL 10
28
29 typedef struct private_asn1_parser_t private_asn1_parser_t;
30
31 /**
32 * Private data of an asn1_cxt_t object.
33 */
34 struct private_asn1_parser_t {
35 /**
36 * Public interface.
37 */
38 asn1_parser_t public;
39
40 /**
41 * Syntax definition of ASN.1 object
42 */
43 asn1Object_t const *objects;
44
45 /**
46 * Current syntax definition line
47 */
48 int line;
49
50 /**
51 * Current stat of the parsing operation
52 */
53 bool success;
54
55 /**
56 * Declare object data as private - use debug level 4 to log it
57 */
58 bool private;
59
60 /**
61 * Top-most type is implicit - ignore it
62 */
63 bool implicit;
64
65 /**
66 * Top-most parsing level - defaults to 0
67 */
68 u_int level0;
69
70 /**
71 * Jump back address for loops for each level
72 */
73 int loopAddr[ASN1_MAX_LEVEL + 1];
74
75 /**
76 * Current parsing pointer for each level
77 */
78 chunk_t blobs[ASN1_MAX_LEVEL + 2];
79 };
80
81 /**
82 * Implementation of asn1_parser_t.iterate
83 */
84 static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
85 {
86 chunk_t *blob, *blob1;
87 u_char *start_ptr;
88 u_int level;
89 asn1Object_t obj;
90
91 *object = chunk_empty;
92
93 /* Advance to the next object syntax definition line */
94 obj = this->objects[++(this->line)];
95
96 /* Terminate if the end of the object syntax definition has been reached */
97 if (obj.flags & ASN1_EXIT)
98 {
99 return FALSE;
100 }
101
102 if (obj.flags & ASN1_END) /* end of loop or option found */
103 {
104 if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
105 {
106 this->line = this->loopAddr[obj.level]; /* another iteration */
107 obj = this->objects[this->line];
108 }
109 else
110 {
111 this->loopAddr[obj.level] = 0; /* exit loop or option*/
112 goto end;
113 }
114 }
115
116 level = this->level0 + obj.level;
117 blob = this->blobs + obj.level;
118 blob1 = blob + 1;
119 start_ptr = blob->ptr;
120
121 /* handle ASN.1 defaults values */
122 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
123 {
124 /* field is missing */
125 DBG2("L%d - %s:", level, obj.name);
126 if (obj.type & ASN1_CONSTRUCTED)
127 {
128 this->line++ ; /* skip context-specific tag */
129 }
130 goto end;
131 }
132
133 /* handle ASN.1 options */
134
135 if ((obj.flags & ASN1_OPT)
136 && (blob->len == 0 || *start_ptr != obj.type))
137 {
138 /* advance to end of missing option field */
139 do
140 {
141 this->line++;
142 }
143 while (!((this->objects[this->line].flags & ASN1_END) &&
144 (this->objects[this->line].level == obj.level)));
145 goto end;
146 }
147
148 /* an ASN.1 object must possess at least a tag and length field */
149
150 if (blob->len < 2)
151 {
152 DBG1("L%d - %s: ASN.1 object smaller than 2 octets",
153 level, obj.name);
154 this->success = FALSE;
155 goto end;
156 }
157
158 blob1->len = asn1_length(blob);
159
160 if (blob1->len == ASN1_INVALID_LENGTH)
161 {
162 DBG1("L%d - %s: length of ASN.1 object invalid or too large",
163 level, obj.name);
164 this->success = FALSE;
165 }
166
167 blob1->ptr = blob->ptr;
168 blob->ptr += blob1->len;
169 blob->len -= blob1->len;
170
171 /* return raw ASN.1 object without prior type checking */
172
173 if (obj.flags & ASN1_RAW)
174 {
175 DBG2("L%d - %s:", level, obj.name);
176 object->ptr = start_ptr;
177 object->len = (size_t)(blob->ptr - start_ptr);
178 goto end;
179 }
180
181 if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
182 {
183 DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
184 level, obj.name, obj.type, *start_ptr);
185 DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
186 this->success = FALSE;
187 goto end;
188 }
189
190 DBG2("L%d - %s:", level, obj.name);
191
192 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
193 if (obj.flags & ASN1_LOOP)
194 {
195 if (blob1->len > 0)
196 {
197 /* at least one item, start the loop */
198 this->loopAddr[obj.level] = this->line + 1;
199 }
200 else
201 {
202 /* no items, advance directly to end of loop */
203 do
204 {
205 this->line++;
206 }
207 while (!((this->objects[this->line].flags & ASN1_END) &&
208 (this->objects[this->line].level == obj.level)));
209 goto end;
210 }
211 }
212
213 if (obj.flags & ASN1_OBJ)
214 {
215 object->ptr = start_ptr;
216 object->len = (size_t)(blob->ptr - start_ptr);
217 if (this->private)
218 {
219 DBG4("%B", object);
220 }
221 else
222 {
223 DBG3("%B", object);
224 }
225 }
226 else if (obj.flags & ASN1_BODY)
227 {
228 *object = *blob1;
229 asn1_debug_simple_object(*object, obj.type, this->private);
230 }
231
232 end:
233 *objectID = this->line;
234 return this->success;
235 }
236
237 /**
238 * Implementation of asn1_parser_t.get_level
239 */
240 static u_int get_level(private_asn1_parser_t *this)
241 {
242 return this->level0 + this->objects[this->line].level;
243 }
244
245 /**
246 * Implementation of asn1_parser_t.set_top_level
247 */
248 static void set_top_level(private_asn1_parser_t *this, u_int level0)
249 {
250 this->level0 = level0;
251 }
252
253 /**
254 * Implementation of asn1_parser_t.set_flags
255 */
256 static void set_flags(private_asn1_parser_t *this, bool implicit, bool private)
257 {
258 this->implicit = implicit;
259 this->private = private;
260 }
261
262 /**
263 * Implementation of asn1_parser_t.success
264 */
265 static bool success(private_asn1_parser_t *this)
266 {
267 return this->success;
268 }
269
270 /**
271 * Implementation of asn1_parser_t.destroy
272 */
273 static void destroy(private_asn1_parser_t *this)
274 {
275 free(this);
276 }
277
278 /**
279 * Defined in header.
280 */
281 asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
282 {
283 private_asn1_parser_t *this = malloc_thing(private_asn1_parser_t);
284
285 memset(this, '\0', sizeof(private_asn1_parser_t));
286 this->objects = objects;
287 this->blobs[0] = blob;
288 this->line = -1;
289 this->success = TRUE;
290
291 this->public.iterate = (bool (*)(asn1_parser_t*, int*, chunk_t*))iterate;
292 this->public.get_level = (u_int (*)(asn1_parser_t*))get_level;
293 this->public.set_top_level = (void (*)(asn1_parser_t*, u_int))set_top_level;
294 this->public.set_flags = (void (*)(asn1_parser_t*, bool, bool))set_flags;
295 this->public.success = (bool (*)(asn1_parser_t*))success;
296 this->public.destroy = (void (*)(asn1_parser_t*))destroy;
297
298 return &this->public;
299 }