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