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