child-rekey: Don't change state to INSTALLED if it was already REKEYING
[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/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 METHOD(asn1_parser_t, iterate, bool,
82 private_asn1_parser_t *this, int *objectID, chunk_t *object)
83 {
84 chunk_t *blob, *blob1;
85 u_char *start_ptr;
86 u_int level;
87 asn1Object_t obj;
88
89 *object = chunk_empty;
90
91 /* Advance to the next object syntax definition line */
92 obj = this->objects[++(this->line)];
93
94 /* Terminate if the end of the object syntax definition has been reached */
95 if (obj.flags & ASN1_EXIT)
96 {
97 return FALSE;
98 }
99
100 if (obj.flags & ASN1_END) /* end of loop or option found */
101 {
102 if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
103 {
104 this->line = this->loopAddr[obj.level]; /* another iteration */
105 obj = this->objects[this->line];
106 }
107 else
108 {
109 this->loopAddr[obj.level] = 0; /* exit loop or option*/
110 goto end;
111 }
112 }
113
114 level = this->level0 + obj.level;
115 blob = this->blobs + obj.level;
116 blob1 = blob + 1;
117 start_ptr = blob->ptr;
118
119 /* handle ASN.1 defaults values */
120 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
121 {
122 /* field is missing */
123 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
124 if (obj.type & ASN1_CONSTRUCTED)
125 {
126 this->line++ ; /* skip context-specific tag */
127 }
128 goto end;
129 }
130
131 /* handle ASN.1 options */
132
133 if ((obj.flags & ASN1_OPT)
134 && (blob->len == 0 || *start_ptr != obj.type))
135 {
136 /* advance to end of missing option field */
137 do
138 {
139 this->line++;
140 }
141 while (!((this->objects[this->line].flags & ASN1_END) &&
142 (this->objects[this->line].level == obj.level)));
143 goto end;
144 }
145
146 /* an ASN.1 object must possess at least a tag and length field */
147
148 if (blob->len < 2)
149 {
150 DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
151 level, obj.name);
152 this->success = FALSE;
153 goto end;
154 }
155
156 blob1->len = asn1_length(blob);
157
158 if (blob1->len == ASN1_INVALID_LENGTH)
159 {
160 DBG1(DBG_ASN, "L%d - %s: length of ASN.1 object invalid or too large",
161 level, obj.name);
162 this->success = FALSE;
163 goto end;
164 }
165
166 blob1->ptr = blob->ptr;
167 blob->ptr += blob1->len;
168 blob->len -= blob1->len;
169
170 /* return raw ASN.1 object without prior type checking */
171
172 if (obj.flags & ASN1_RAW)
173 {
174 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
175 object->ptr = start_ptr;
176 object->len = (size_t)(blob->ptr - start_ptr);
177 goto end;
178 }
179
180 if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
181 {
182 DBG2(DBG_ASN, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
183 level, obj.name, obj.type, *start_ptr);
184 DBG3(DBG_ASN, "%b", start_ptr, (u_int)(blob->ptr - start_ptr));
185 this->success = FALSE;
186 goto end;
187 }
188
189 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
190
191 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
192 if (obj.flags & ASN1_LOOP)
193 {
194 if (blob1->len > 0)
195 {
196 /* at least one item, start the loop */
197 this->loopAddr[obj.level] = this->line + 1;
198 }
199 else
200 {
201 /* no items, advance directly to end of loop */
202 do
203 {
204 this->line++;
205 }
206 while (!((this->objects[this->line].flags & ASN1_END) &&
207 (this->objects[this->line].level == obj.level)));
208 goto end;
209 }
210 }
211
212 if (obj.flags & ASN1_OBJ)
213 {
214 object->ptr = start_ptr;
215 object->len = (size_t)(blob->ptr - start_ptr);
216 if (this->private)
217 {
218 DBG4(DBG_ASN, "%B", object);
219 }
220 else
221 {
222 DBG3(DBG_ASN, "%B", object);
223 }
224 }
225 else if (obj.flags & ASN1_BODY)
226 {
227 *object = *blob1;
228 asn1_debug_simple_object(*object, obj.type, this->private);
229 }
230
231 end:
232 *objectID = this->line;
233 return this->success;
234 }
235
236 METHOD(asn1_parser_t, get_level, u_int,
237 private_asn1_parser_t *this)
238 {
239 return this->level0 + this->objects[this->line].level;
240 }
241
242 METHOD(asn1_parser_t, set_top_level, void,
243 private_asn1_parser_t *this, u_int level0)
244 {
245 this->level0 = level0;
246 }
247
248 METHOD(asn1_parser_t, set_flags, void,
249 private_asn1_parser_t *this, bool implicit, bool private)
250 {
251 this->implicit = implicit;
252 this->private = private;
253 }
254
255 METHOD(asn1_parser_t, success, bool,
256 private_asn1_parser_t *this)
257 {
258 return this->success;
259 }
260
261 METHOD(asn1_parser_t, destroy, void,
262 private_asn1_parser_t *this)
263 {
264 free(this);
265 }
266
267 /**
268 * Defined in header.
269 */
270 asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
271 {
272 private_asn1_parser_t *this;
273
274 INIT(this,
275 .public = {
276 .iterate = _iterate,
277 .get_level = _get_level,
278 .set_top_level = _set_top_level,
279 .set_flags = _set_flags,
280 .success = _success,
281 .destroy = _destroy,
282 },
283 .objects = objects,
284 .blobs[0] = blob,
285 .line = -1,
286 .success = TRUE,
287 );
288
289 return &this->public;
290 }