OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 #include "secutil.h" | 4 #include "secutil.h" |
5 | 5 |
6 typedef enum { | 6 typedef enum { |
7 tagDone, lengthDone, leafDone, compositeDone, | 7 tagDone, |
8 notDone, | 8 lengthDone, |
9 parseError, parseComplete | 9 leafDone, |
| 10 compositeDone, |
| 11 notDone, |
| 12 parseError, |
| 13 parseComplete |
10 } ParseState; | 14 } ParseState; |
11 | 15 |
12 typedef unsigned char Byte; | 16 typedef unsigned char Byte; |
13 typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len); | 17 typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len); |
14 typedef struct { | 18 typedef struct { |
15 SECArb arb; | 19 SECArb arb; |
16 int pos;» » » /* length from global start to item start */ | 20 int pos; /* length from global start to item start */ |
17 SECArb *parent; | 21 SECArb *parent; |
18 } ParseStackElem; | 22 } ParseStackElem; |
19 | 23 |
20 struct BERParseStr { | 24 struct BERParseStr { |
21 PLArenaPool *his; | 25 PLArenaPool *his; |
22 PLArenaPool *mine; | 26 PLArenaPool *mine; |
23 ParseProc proc; | 27 ParseProc proc; |
24 int stackDepth; | 28 int stackDepth; |
25 ParseStackElem *stackPtr; | 29 ParseStackElem *stackPtr; |
26 ParseStackElem *stack; | 30 ParseStackElem *stack; |
27 int pending;» » /* bytes remaining to complete this part */ | 31 int pending; /* bytes remaining to complete this part */ |
28 int pos;» » » /* running length of consumed characters */ | 32 int pos; /* running length of consumed characters */ |
29 ParseState state; | 33 ParseState state; |
30 PRBool keepLeaves; | 34 PRBool keepLeaves; |
31 PRBool derOnly; | 35 PRBool derOnly; |
32 BERFilterProc filter; | 36 BERFilterProc filter; |
33 void *filterArg; | 37 void *filterArg; |
34 BERNotifyProc before; | 38 BERNotifyProc before; |
35 void *beforeArg; | 39 void *beforeArg; |
36 BERNotifyProc after; | 40 BERNotifyProc after; |
37 void *afterArg; | 41 void *afterArg; |
38 }; | 42 }; |
39 | 43 |
40 #define UNKNOWN -1 | 44 #define UNKNOWN -1 |
41 | 45 |
42 static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len) | 46 static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len) { |
43 { | 47 unsigned char c = *(*buf)++; |
44 unsigned char c = *(*buf)++; | 48 (*len)--; |
45 (*len)--; | 49 h->pos++; |
46 h->pos++; | 50 if (h->filter) (*h->filter)(h->filterArg, &c, 1); |
47 if (h->filter) | 51 return c; |
48 » (*h->filter)(h->filterArg, &c, 1); | 52 } |
49 return c; | 53 |
50 } | 54 static void ParseTag(BERParse *h, unsigned char **buf, int *len) { |
51 | 55 SECArb *arb = &(h->stackPtr->arb); |
52 static void ParseTag(BERParse *h, unsigned char **buf, int *len) | 56 arb->tag = NextChar(h, buf, len); |
53 { | 57 |
54 SECArb* arb = &(h->stackPtr->arb); | 58 PORT_Assert(h->state == notDone); |
55 arb->tag = NextChar(h, buf, len); | |
56 | |
57 PORT_Assert(h->state == notDone); | |
58 | 59 |
59 /* | 60 /* |
60 * NOTE: This does not handle the high-tag-number form | 61 * NOTE: This does not handle the high-tag-number form |
61 */ | 62 */ |
62 if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) { | 63 if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) { |
63 PORT_SetError(SEC_ERROR_BAD_DER); | 64 PORT_SetError(SEC_ERROR_BAD_DER); |
64 » h->state = parseError; | 65 h->state = parseError; |
65 » return; | 66 return; |
| 67 } |
| 68 |
| 69 h->pending = UNKNOWN; |
| 70 arb->length = UNKNOWN; |
| 71 if (arb->tag & DER_CONSTRUCTED) { |
| 72 arb->body.cons.numSubs = 0; |
| 73 arb->body.cons.subs = NULL; |
| 74 } else { |
| 75 arb->body.item.len = UNKNOWN; |
| 76 arb->body.item.data = NULL; |
| 77 } |
| 78 |
| 79 h->state = tagDone; |
| 80 } |
| 81 |
| 82 static void ParseLength(BERParse *h, unsigned char **buf, int *len) { |
| 83 Byte b; |
| 84 SECArb *arb = &(h->stackPtr->arb); |
| 85 |
| 86 PORT_Assert(h->state == notDone); |
| 87 |
| 88 if (h->pending == UNKNOWN) { |
| 89 b = NextChar(h, buf, len); |
| 90 if ((b & 0x80) == 0) {/* short form */ |
| 91 arb->length = b; |
| 92 /* |
| 93 * if the tag and the length are both zero bytes, then this |
| 94 * should be the marker showing end of list for the |
| 95 * indefinite length composite |
| 96 */ |
| 97 if (arb->length == 0 && arb->tag == 0) |
| 98 h->state = compositeDone; |
| 99 else |
| 100 h->state = lengthDone; |
| 101 return; |
66 } | 102 } |
67 | 103 |
| 104 h->pending = b & 0x7f; |
| 105 /* 0 implies this is an indefinite length */ |
| 106 if (h->pending > 4) { |
| 107 PORT_SetError(SEC_ERROR_BAD_DER); |
| 108 h->state = parseError; |
| 109 return; |
| 110 } |
| 111 arb->length = 0; |
| 112 } |
| 113 |
| 114 while ((*len > 0) && (h->pending > 0)) { |
| 115 b = NextChar(h, buf, len); |
| 116 arb->length = (arb->length << 8) + b; |
| 117 h->pending--; |
| 118 } |
| 119 if (h->pending == 0) { |
| 120 if (h->derOnly && (arb->length == 0)) |
| 121 h->state = parseError; |
| 122 else |
| 123 h->state = lengthDone; |
| 124 } |
| 125 return; |
| 126 } |
| 127 |
| 128 static void ParseLeaf(BERParse *h, unsigned char **buf, int *len) { |
| 129 int count; |
| 130 SECArb *arb = &(h->stackPtr->arb); |
| 131 |
| 132 PORT_Assert(h->state == notDone); |
| 133 PORT_Assert(h->pending >= 0); |
| 134 |
| 135 if (*len < h->pending) |
| 136 count = *len; |
| 137 else |
| 138 count = h->pending; |
| 139 |
| 140 if (h->keepLeaves) |
| 141 memcpy(arb->body.item.data + arb->body.item.len, *buf, count); |
| 142 if (h->filter) (*h->filter)(h->filterArg, *buf, count); |
| 143 *buf += count; |
| 144 *len -= count; |
| 145 arb->body.item.len += count; |
| 146 h->pending -= count; |
| 147 h->pos += count; |
| 148 if (h->pending == 0) { |
| 149 h->state = leafDone; |
| 150 } |
| 151 return; |
| 152 } |
| 153 |
| 154 static void CreateArbNode(BERParse *h) { |
| 155 SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); |
| 156 |
| 157 *arb = h->stackPtr->arb; |
| 158 |
| 159 /* |
| 160 * Special case closing the root |
| 161 */ |
| 162 if (h->stackPtr == h->stack) { |
| 163 PORT_Assert(arb->tag & DER_CONSTRUCTED); |
| 164 h->state = parseComplete; |
| 165 } else { |
| 166 SECArb *parent = h->stackPtr->parent; |
| 167 parent->body.cons.subs = |
| 168 DS_ArenaGrow(h->his, parent->body.cons.subs, |
| 169 (parent->body.cons.numSubs) * sizeof(SECArb *), |
| 170 (parent->body.cons.numSubs + 1) * sizeof(SECArb *)); |
| 171 parent->body.cons.subs[parent->body.cons.numSubs] = arb; |
| 172 parent->body.cons.numSubs++; |
| 173 h->proc = ParseTag; |
| 174 h->state = notDone; |
68 h->pending = UNKNOWN; | 175 h->pending = UNKNOWN; |
69 arb->length = UNKNOWN; | 176 } |
70 if (arb->tag & DER_CONSTRUCTED) { | 177 if (h->after) (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE); |
71 » arb->body.cons.numSubs = 0; | 178 } |
72 » arb->body.cons.subs = NULL; | 179 |
73 } else { | 180 SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len) { |
74 » arb->body.item.len = UNKNOWN; | 181 if (h->state == parseError) return PR_TRUE; |
75 » arb->body.item.data = NULL; | 182 |
| 183 while (len) { |
| 184 (*h->proc)(h, &buf, &len); |
| 185 if (h->state == parseComplete) { |
| 186 PORT_SetError(SEC_ERROR_BAD_DER); |
| 187 h->state = parseError; |
| 188 return PR_TRUE; |
76 } | 189 } |
77 | 190 if (h->state == parseError) return PR_TRUE; |
78 h->state = tagDone; | 191 PORT_Assert(h->state != parseComplete); |
79 } | 192 |
80 | 193 if (h->state <= compositeDone) { |
81 static void ParseLength(BERParse *h, unsigned char **buf, int *len) | 194 if (h->proc == ParseTag) { |
82 { | 195 PORT_Assert(h->state == tagDone); |
83 Byte b; | 196 h->proc = ParseLength; |
84 SECArb *arb = &(h->stackPtr->arb); | 197 h->state = notDone; |
85 | 198 } else if (h->proc == ParseLength) { |
86 PORT_Assert(h->state == notDone); | 199 SECArb *arb = &(h->stackPtr->arb); |
87 | 200 PORT_Assert(h->state == lengthDone || h->state == compositeDone); |
88 if (h->pending == UNKNOWN) { | 201 |
89 » b = NextChar(h, buf, len); | 202 if (h->before) |
90 » if ((b & 0x80) == 0) {» /* short form */ | 203 (*h->before)(h->beforeArg, arb, h->stackPtr - h->stack, PR_TRUE); |
91 » arb->length = b; | 204 |
92 » /* | 205 /* |
93 » * if the tag and the length are both zero bytes, then this | 206 * Check to see if this is the end of an indefinite |
94 » * should be the marker showing end of list for the | 207 * length composite |
95 » * indefinite length composite | 208 */ |
96 » */ | 209 if (h->state == compositeDone) { |
97 » if (arb->length == 0 && arb->tag == 0) | 210 SECArb *parent = h->stackPtr->parent; |
98 » » h->state = compositeDone; | 211 PORT_Assert(parent); |
99 » else | 212 PORT_Assert(parent->tag & DER_CONSTRUCTED); |
100 » » h->state = lengthDone; | 213 if (parent->length != 0) { |
101 » return; | 214 PORT_SetError(SEC_ERROR_BAD_DER); |
102 » } | 215 h->state = parseError; |
103 | 216 return PR_TRUE; |
104 » h->pending = b & 0x7f; | 217 } |
105 » /* 0 implies this is an indefinite length */ | 218 /* |
106 » if (h->pending > 4) { | 219 * NOTE: This does not check for an indefinite length |
107 » PORT_SetError(SEC_ERROR_BAD_DER); | 220 * composite being contained inside a definite length |
108 » h->state = parseError; | 221 * composite. It is not clear that is legal. |
109 » return; | 222 */ |
110 » } | 223 h->stackPtr--; |
111 » arb->length = 0; | 224 CreateArbNode(h); |
| 225 } else { |
| 226 h->stackPtr->pos = h->pos; |
| 227 |
| 228 if (arb->tag & DER_CONSTRUCTED) { |
| 229 SECArb *parent; |
| 230 /* |
| 231 * Make sure there is room on the stack before we |
| 232 * stick anything else there. |
| 233 */ |
| 234 PORT_Assert(h->stackPtr - h->stack < h->stackDepth); |
| 235 if (h->stackPtr - h->stack == h->stackDepth - 1) { |
| 236 int newDepth = h->stackDepth * 2; |
| 237 h->stack = DS_ArenaGrow(h->mine, h->stack, |
| 238 sizeof(ParseStackElem) * h->stackDepth, |
| 239 sizeof(ParseStackElem) * newDepth); |
| 240 h->stackPtr = h->stack + h->stackDepth + 1; |
| 241 h->stackDepth = newDepth; |
| 242 } |
| 243 parent = &(h->stackPtr->arb); |
| 244 h->stackPtr++; |
| 245 h->stackPtr->parent = parent; |
| 246 h->proc = ParseTag; |
| 247 h->state = notDone; |
| 248 h->pending = UNKNOWN; |
| 249 } else { |
| 250 if (arb->length < 0) { |
| 251 PORT_SetError(SEC_ERROR_BAD_DER); |
| 252 h->state = parseError; |
| 253 return PR_TRUE; |
| 254 } |
| 255 arb->body.item.len = 0; |
| 256 if (arb->length > 0 && h->keepLeaves) { |
| 257 arb->body.item.data = PORT_ArenaAlloc(h->his, arb->length); |
| 258 } else { |
| 259 arb->body.item.data = NULL; |
| 260 } |
| 261 h->proc = ParseLeaf; |
| 262 h->state = notDone; |
| 263 h->pending = arb->length; |
| 264 } |
| 265 } |
| 266 } else { |
| 267 ParseStackElem *parent; |
| 268 PORT_Assert(h->state = leafDone); |
| 269 PORT_Assert(h->proc == ParseLeaf); |
| 270 |
| 271 for (;;) { |
| 272 CreateArbNode(h); |
| 273 if (h->stackPtr == h->stack) break; |
| 274 parent = (h->stackPtr - 1); |
| 275 PORT_Assert(parent->arb.tag & DER_CONSTRUCTED); |
| 276 if (parent->arb.length == 0) /* need explicit end */ |
| 277 break; |
| 278 if (parent->pos + parent->arb.length > h->pos) break; |
| 279 if (parent->pos + parent->arb.length < h->pos) { |
| 280 PORT_SetError(SEC_ERROR_BAD_DER); |
| 281 h->state = parseError; |
| 282 return PR_TRUE; |
| 283 } |
| 284 h->stackPtr = parent; |
| 285 } |
| 286 } |
112 } | 287 } |
113 | 288 } |
114 while ((*len > 0) && (h->pending > 0)) { | 289 return PR_FALSE; |
115 » b = NextChar(h, buf, len); | 290 } |
116 » arb->length = (arb->length << 8) + b; | 291 BERParse *BER_ParseInit(PLArenaPool *arena, PRBool derOnly) { |
117 » h->pending--; | 292 BERParse *h; |
118 } | 293 PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
119 if (h->pending == 0) { | 294 if (temp == NULL) { |
120 » if (h->derOnly && (arb->length == 0)) | 295 PORT_SetError(SEC_ERROR_NO_MEMORY); |
121 » h->state = parseError; | 296 return NULL; |
122 » else | 297 } |
123 » h->state = lengthDone; | 298 h = PORT_ArenaAlloc(temp, sizeof(BERParse)); |
124 } | 299 if (h == NULL) { |
125 return; | 300 PORT_FreeArena(temp, PR_FALSE); |
126 } | 301 PORT_SetError(SEC_ERROR_NO_MEMORY); |
127 | 302 return NULL; |
128 static void ParseLeaf(BERParse *h, unsigned char **buf, int *len) | 303 } |
129 { | 304 h->his = arena; |
130 int count; | 305 h->mine = temp; |
131 SECArb *arb = &(h->stackPtr->arb); | 306 h->proc = ParseTag; |
132 | 307 h->stackDepth = 20; |
133 PORT_Assert(h->state == notDone); | 308 h->stack = PORT_ArenaZAlloc(h->mine, sizeof(ParseStackElem) * h->stackDepth); |
134 PORT_Assert(h->pending >= 0); | 309 h->stackPtr = h->stack; |
135 | 310 h->state = notDone; |
136 if (*len < h->pending) | 311 h->pos = 0; |
137 » count = *len; | 312 h->keepLeaves = PR_TRUE; |
138 else | 313 h->before = NULL; |
139 » count = h->pending; | 314 h->after = NULL; |
140 | 315 h->filter = NULL; |
141 if (h->keepLeaves) | 316 h->derOnly = derOnly; |
142 » memcpy(arb->body.item.data + arb->body.item.len, *buf, count); | 317 return h; |
143 if (h->filter) | 318 } |
144 » (*h->filter)(h->filterArg, *buf, count); | 319 |
145 *buf += count; | 320 SECArb *BER_ParseFini(BERParse *h) { |
146 *len -= count; | 321 PLArenaPool *myArena = h->mine; |
147 arb->body.item.len += count; | 322 SECArb *arb; |
148 h->pending -= count; | 323 |
149 h->pos += count; | 324 if (h->state != parseComplete) { |
150 if (h->pending == 0) { | 325 arb = NULL; |
151 » h->state = leafDone; | 326 } else { |
152 } | 327 arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); |
153 return; | |
154 } | |
155 | |
156 static void CreateArbNode(BERParse *h) | |
157 { | |
158 SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); | |
159 | |
160 *arb = h->stackPtr->arb; | 328 *arb = h->stackPtr->arb; |
161 | 329 } |
162 /*· | 330 |
163 * Special case closing the root | 331 PORT_FreeArena(myArena, PR_FALSE); |
164 */» | 332 |
165 if (h->stackPtr == h->stack) { | 333 return arb; |
166 » PORT_Assert(arb->tag & DER_CONSTRUCTED); | 334 } |
167 » h->state = parseComplete; | 335 |
168 } else { | 336 void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance) { |
169 » SECArb *parent = h->stackPtr->parent; | 337 h->filter = proc; |
170 » parent->body.cons.subs = DS_ArenaGrow( | 338 h->filterArg = instance; |
171 » h->his, parent->body.cons.subs, | 339 } |
172 » (parent->body.cons.numSubs) * sizeof(SECArb*), | 340 |
173 » (parent->body.cons.numSubs + 1) * sizeof(SECArb*)); | 341 void BER_SetLeafStorage(BERParse *h, PRBool keep) { h->keepLeaves = keep; } |
174 » parent->body.cons.subs[parent->body.cons.numSubs] = arb; | |
175 » parent->body.cons.numSubs++; | |
176 » h->proc = ParseTag; | |
177 » h->state = notDone; | |
178 » h->pending = UNKNOWN; | |
179 } | |
180 if (h->after) | |
181 » (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE); | |
182 } | |
183 | |
184 SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len) | |
185 { | |
186 if (h->state == parseError) return PR_TRUE; | |
187 | |
188 while (len) { | |
189 (*h->proc)(h, &buf, &len); | |
190 » if (h->state == parseComplete) { | |
191 » PORT_SetError(SEC_ERROR_BAD_DER); | |
192 » h->state = parseError; | |
193 » return PR_TRUE; | |
194 » } | |
195 » if (h->state == parseError) return PR_TRUE; | |
196 » PORT_Assert(h->state != parseComplete); | |
197 | |
198 if (h->state <= compositeDone) { | |
199 » if (h->proc == ParseTag) { | |
200 » » PORT_Assert(h->state == tagDone); | |
201 » » h->proc = ParseLength; | |
202 » » h->state = notDone; | |
203 » } else if (h->proc == ParseLength) { | |
204 » » SECArb *arb = &(h->stackPtr->arb); | |
205 » » PORT_Assert(h->state == lengthDone || h->state == compositeDone)
; | |
206 | |
207 » » if (h->before) | |
208 » » (*h->before)(h->beforeArg, arb, | |
209 » » » » h->stackPtr - h->stack, PR_TRUE); | |
210 | |
211 » » /* | |
212 » » * Check to see if this is the end of an indefinite | |
213 » » * length composite | |
214 » » */ | |
215 » » if (h->state == compositeDone) { | |
216 » » SECArb *parent = h->stackPtr->parent; | |
217 » » PORT_Assert(parent); | |
218 » » PORT_Assert(parent->tag & DER_CONSTRUCTED); | |
219 » » if (parent->length != 0) { | |
220 » » » PORT_SetError(SEC_ERROR_BAD_DER); | |
221 » » » h->state = parseError; | |
222 » » » return PR_TRUE; | |
223 » » } | |
224 » » /* | |
225 » » * NOTE: This does not check for an indefinite length | |
226 » » * composite being contained inside a definite length | |
227 » » * composite. It is not clear that is legal. | |
228 » » */ | |
229 » » h->stackPtr--; | |
230 » » CreateArbNode(h); | |
231 » » } else { | |
232 » » h->stackPtr->pos = h->pos; | |
233 | |
234 | |
235 » » if (arb->tag & DER_CONSTRUCTED) { | |
236 » » » SECArb *parent; | |
237 » » » /* | |
238 » » » * Make sure there is room on the stack before we | |
239 » » » * stick anything else there. | |
240 » » » */ | |
241 » » » PORT_Assert(h->stackPtr - h->stack < h->stackDepth); | |
242 » » » if (h->stackPtr - h->stack == h->stackDepth - 1) { | |
243 » » » int newDepth = h->stackDepth * 2; | |
244 » » » h->stack = DS_ArenaGrow(h->mine, h->stack, | |
245 » » » » sizeof(ParseStackElem) * h->stackDepth, | |
246 » » » » sizeof(ParseStackElem) * newDepth); | |
247 » » » h->stackPtr = h->stack + h->stackDepth + 1; | |
248 » » » h->stackDepth = newDepth; | |
249 » » » } | |
250 » » » parent = &(h->stackPtr->arb); | |
251 » » » h->stackPtr++; | |
252 » » » h->stackPtr->parent = parent; | |
253 » » » h->proc = ParseTag; | |
254 » » » h->state = notDone; | |
255 » » » h->pending = UNKNOWN; | |
256 » » } else { | |
257 » » » if (arb->length < 0) { | |
258 » » » PORT_SetError(SEC_ERROR_BAD_DER); | |
259 » » » h->state = parseError; | |
260 » » » return PR_TRUE; | |
261 » » » } | |
262 » » » arb->body.item.len = 0; | |
263 » » » if (arb->length > 0 && h->keepLeaves) { | |
264 » » » arb->body.item.data = | |
265 » » » » PORT_ArenaAlloc(h->his, arb->length); | |
266 » » » } else { | |
267 » » » arb->body.item.data = NULL; | |
268 » » » } | |
269 » » » h->proc = ParseLeaf; | |
270 » » » h->state = notDone; | |
271 » » » h->pending = arb->length; | |
272 » » } | |
273 » » } | |
274 » } else { | |
275 » » ParseStackElem *parent; | |
276 » » PORT_Assert(h->state = leafDone); | |
277 » » PORT_Assert(h->proc == ParseLeaf); | |
278 | |
279 » » for (;;) { | |
280 » » CreateArbNode(h); | |
281 » » if (h->stackPtr == h->stack) | |
282 » » » break; | |
283 » » parent = (h->stackPtr - 1); | |
284 » » PORT_Assert(parent->arb.tag & DER_CONSTRUCTED); | |
285 » » if (parent->arb.length == 0) /* need explicit end */ | |
286 » » » break; | |
287 » » if (parent->pos + parent->arb.length > h->pos) | |
288 » » » break; | |
289 » » if (parent->pos + parent->arb.length < h->pos) { | |
290 » » » PORT_SetError(SEC_ERROR_BAD_DER); | |
291 » » » h->state = parseError; | |
292 » » » return PR_TRUE; | |
293 » » } | |
294 » » h->stackPtr = parent; | |
295 » » } | |
296 » } | |
297 | |
298 » } | |
299 } | |
300 return PR_FALSE; | |
301 } | |
302 BERParse *BER_ParseInit(PLArenaPool *arena, PRBool derOnly) | |
303 { | |
304 BERParse *h; | |
305 PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
306 if (temp == NULL) { | |
307 » PORT_SetError(SEC_ERROR_NO_MEMORY); | |
308 » return NULL; | |
309 } | |
310 h = PORT_ArenaAlloc(temp, sizeof(BERParse)); | |
311 if (h == NULL) { | |
312 » PORT_FreeArena(temp, PR_FALSE); | |
313 » PORT_SetError(SEC_ERROR_NO_MEMORY); | |
314 » return NULL; | |
315 } | |
316 h->his = arena; | |
317 h->mine = temp; | |
318 h->proc = ParseTag; | |
319 h->stackDepth = 20; | |
320 h->stack = PORT_ArenaZAlloc(h->mine, | |
321 » » » sizeof(ParseStackElem) * h->stackDepth); | |
322 h->stackPtr = h->stack; | |
323 h->state = notDone; | |
324 h->pos = 0; | |
325 h->keepLeaves = PR_TRUE; | |
326 h->before = NULL; | |
327 h->after = NULL; | |
328 h->filter = NULL; | |
329 h->derOnly = derOnly; | |
330 return h; | |
331 } | |
332 | |
333 SECArb *BER_ParseFini(BERParse *h) | |
334 { | |
335 PLArenaPool *myArena = h->mine; | |
336 SECArb *arb; | |
337 | |
338 if (h->state != parseComplete) { | |
339 » arb = NULL; | |
340 } else { | |
341 » arb = PORT_ArenaAlloc(h->his, sizeof(SECArb)); | |
342 » *arb = h->stackPtr->arb; | |
343 } | |
344 | |
345 PORT_FreeArena(myArena, PR_FALSE); | |
346 | |
347 return arb; | |
348 } | |
349 | |
350 | |
351 void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance) | |
352 { | |
353 h->filter = proc; | |
354 h->filterArg = instance; | |
355 } | |
356 | |
357 void BER_SetLeafStorage(BERParse *h, PRBool keep) | |
358 { | |
359 h->keepLeaves = keep; | |
360 } | |
361 | 342 |
362 void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance, | 343 void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance, |
363 » » » PRBool beforeData) | 344 PRBool beforeData) { |
364 { | 345 if (beforeData) { |
365 if (beforeData) { | 346 h->before = proc; |
366 » h->before = proc; | 347 h->beforeArg = instance; |
367 » h->beforeArg = instance; | 348 } else { |
368 } else { | 349 h->after = proc; |
369 » h->after = proc; | 350 h->afterArg = instance; |
370 » h->afterArg = instance; | 351 } |
371 } | 352 } |
372 } | |
373 | |
374 | |
375 | |
OLD | NEW |