Merge from the 5.3 branch (security fix). Tagged as merge_53_src, merge_53_dst, merge...
[mod_auth_kerb.git] / spnegokrb5 / der_get.c
1 /*
2  * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright 
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the distribution. 
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors 
18  *    may be used to endorse or promote products derived from this software 
19  *    without specific prior written permission. 
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31  * SUCH DAMAGE. 
32  */
33
34 #include "der_locl.h"
35
36 #if 0
37 RCSID("$Id$");
38
39 #include <version.h>
40 #endif
41
42 /* 
43  * All decoding functions take a pointer `p' to first position in
44  * which to read, from the left, `len' which means the maximum number
45  * of characters we are able to read, `ret' were the value will be
46  * returned and `size' where the number of used bytes is stored.
47  * Either 0 or an error code is returned.
48  */
49
50 static int
51 der_get_unsigned (const unsigned char *p, size_t len,
52                   unsigned *ret, size_t *size)
53 {
54     unsigned val = 0;
55     size_t oldlen = len;
56
57     while (len--)
58         val = val * 256 + *p++;
59     *ret = val;
60     if(size) *size = oldlen;
61     return 0;
62 }
63
64 int
65 der_get_int (const unsigned char *p, size_t len,
66              int *ret, size_t *size)
67 {
68     int val = 0;
69     size_t oldlen = len;
70
71     if (len > 0) {
72         val = (signed char)*p++;
73         while (--len)
74             val = val * 256 + *p++;
75     }
76     *ret = val;
77     if(size) *size = oldlen;
78     return 0;
79 }
80
81 int
82 der_get_length (const unsigned char *p, size_t len,
83                 size_t *val, size_t *size)
84 {
85     size_t v;
86
87     if (len <= 0)
88         return ASN1_OVERRUN;
89     --len;
90     v = *p++;
91     if (v < 128) {
92         *val = v;
93         if(size) *size = 1;
94     } else {
95         int e;
96         size_t l;
97         unsigned tmp;
98
99         if(v == 0x80){
100             *val = ASN1_INDEFINITE;
101             if(size) *size = 1;
102             return 0;
103         }
104         v &= 0x7F;
105         if (len < v)
106             return ASN1_OVERRUN;
107         e = der_get_unsigned (p, v, &tmp, &l);
108         if(e) return e;
109         *val = tmp;
110         if(size) *size = l + 1;
111     }
112     return 0;
113 }
114
115 int
116 der_get_general_string (const unsigned char *p, size_t len, 
117                         general_string *str, size_t *size)
118 {
119     char *s;
120
121     s = malloc (len + 1);
122     if (s == NULL)
123         return ENOMEM;
124     memcpy (s, p, len);
125     s[len] = '\0';
126     *str = s;
127     if(size) *size = len;
128     return 0;
129 }
130
131 int
132 der_get_octet_string (const unsigned char *p, size_t len, 
133                       octet_string *data, size_t *size)
134 {
135     data->length = len;
136     data->data = malloc(len);
137     if (data->data == NULL && data->length != 0)
138         return ENOMEM;
139     memcpy (data->data, p, len);
140     if(size) *size = len;
141     return 0;
142 }
143
144 int
145 der_get_oid (const unsigned char *p, size_t len,
146              oid *data, size_t *size)
147 {
148     int n;
149     size_t oldlen = len;
150
151     if (len < 1)
152         return ASN1_OVERRUN;
153
154     data->components = malloc((len + 1) * sizeof(*data->components));
155     if (data->components == NULL && len != 0)
156         return ENOMEM;
157     data->components[0] = (*p) / 40;
158     data->components[1] = (*p) % 40;
159     --len;
160     ++p;
161     for (n = 2; len > 0; ++n) {
162         unsigned u = 0;
163
164         do {
165             --len;
166             u = u * 128 + (*p++ % 128);
167         } while (len > 0 && p[-1] & 0x80);
168         data->components[n] = u;
169     }
170     if (p[-1] & 0x80) {
171         free_oid (data);
172         return ASN1_OVERRUN;
173     }
174     data->length = n;
175     if (size)
176         *size = oldlen;
177     return 0;
178 }
179
180 int
181 der_get_tag (const unsigned char *p, size_t len,
182              Der_class *class, Der_type *type,
183              int *tag, size_t *size)
184 {
185     if (len < 1)
186         return ASN1_OVERRUN;
187     *class = (Der_class)(((*p) >> 6) & 0x03);
188     *type = (Der_type)(((*p) >> 5) & 0x01);
189     *tag = (*p) & 0x1F;
190     if(size) *size = 1;
191     return 0;
192 }
193
194 int
195 der_match_tag (const unsigned char *p, size_t len,
196                Der_class class, Der_type type,
197                int tag, size_t *size)
198 {
199     size_t l;
200     Der_class thisclass;
201     Der_type thistype;
202     int thistag;
203     int e;
204
205     e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
206     if (e) return e;
207     if (class != thisclass || type != thistype)
208         return ASN1_BAD_ID;
209     if(tag > thistag)
210         return ASN1_MISPLACED_FIELD;
211     if(tag < thistag)
212         return ASN1_MISSING_FIELD;
213     if(size) *size = l;
214     return 0;
215 }
216
217 int
218 der_match_tag_and_length (const unsigned char *p, size_t len,
219                           Der_class class, Der_type type, int tag,
220                           size_t *length_ret, size_t *size)
221 {
222     size_t l, ret = 0;
223     int e;
224
225     e = der_match_tag (p, len, class, type, tag, &l);
226     if (e) return e;
227     p += l;
228     len -= l;
229     ret += l;
230     e = der_get_length (p, len, length_ret, &l);
231     if (e) return e;
232     p += l;
233     len -= l;
234     ret += l;
235     if(size) *size = ret;
236     return 0;
237 }
238
239 int
240 decode_integer (const unsigned char *p, size_t len,
241                 int *num, size_t *size)
242 {
243     size_t ret = 0;
244     size_t l, reallen;
245     int e;
246
247     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
248     if (e) return e;
249     p += l;
250     len -= l;
251     ret += l;
252     e = der_get_length (p, len, &reallen, &l);
253     if (e) return e;
254     p += l;
255     len -= l;
256     ret += l;
257     if (reallen > len)
258         return ASN1_OVERRUN;
259     e = der_get_int (p, reallen, num, &l);
260     if (e) return e;
261     p += l;
262     len -= l;
263     ret += l;
264     if(size) *size = ret;
265     return 0;
266 }
267
268 int
269 decode_unsigned (const unsigned char *p, size_t len,
270                  unsigned *num, size_t *size)
271 {
272     size_t ret = 0;
273     size_t l, reallen;
274     int e;
275
276     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
277     if (e) return e;
278     p += l;
279     len -= l;
280     ret += l;
281     e = der_get_length (p, len, &reallen, &l);
282     if (e) return e;
283     p += l;
284     len -= l;
285     ret += l;
286     if (reallen > len)
287         return ASN1_OVERRUN;
288     e = der_get_unsigned (p, reallen, num, &l);
289     if (e) return e;
290     p += l;
291     len -= l;
292     ret += l;
293     if(size) *size = ret;
294     return 0;
295 }
296
297 int
298 decode_enumerated (const unsigned char *p, size_t len,
299                    unsigned *num, size_t *size)
300 {
301     size_t ret = 0;
302     size_t l, reallen;
303     int e;
304
305     e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l);
306     if (e) return e;
307     p += l;
308     len -= l;
309     ret += l;
310     e = der_get_length (p, len, &reallen, &l);
311     if (e) return e;
312     p += l;
313     len -= l;
314     ret += l;
315     e = der_get_int (p, reallen, num, &l);
316     if (e) return e;
317     p += l;
318     len -= l;
319     ret += l;
320     if(size) *size = ret;
321     return 0;
322 }
323
324 int
325 decode_general_string (const unsigned char *p, size_t len, 
326                        general_string *str, size_t *size)
327 {
328     size_t ret = 0;
329     size_t l;
330     int e;
331     size_t slen;
332
333     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l);
334     if (e) return e;
335     p += l;
336     len -= l;
337     ret += l;
338
339     e = der_get_length (p, len, &slen, &l);
340     if (e) return e;
341     p += l;
342     len -= l;
343     ret += l;
344     if (len < slen)
345         return ASN1_OVERRUN;
346
347     e = der_get_general_string (p, slen, str, &l);
348     if (e) return e;
349     p += l;
350     len -= l;
351     ret += l;
352     if(size) *size = ret;
353     return 0;
354 }
355
356 int
357 decode_octet_string (const unsigned char *p, size_t len, 
358                      octet_string *k, size_t *size)
359 {
360     size_t ret = 0;
361     size_t l;
362     int e;
363     size_t slen;
364
365     e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l);
366     if (e) return e;
367     p += l;
368     len -= l;
369     ret += l;
370
371     e = der_get_length (p, len, &slen, &l);
372     if (e) return e;
373     p += l;
374     len -= l;
375     ret += l;
376     if (len < slen)
377         return ASN1_OVERRUN;
378
379     e = der_get_octet_string (p, slen, k, &l);
380     if (e) return e;
381     p += l;
382     len -= l;
383     ret += l;
384     if(size) *size = ret;
385     return 0;
386 }
387
388 int
389 decode_oid (const unsigned char *p, size_t len, 
390             oid *k, size_t *size)
391 {
392     size_t ret = 0;
393     size_t l;
394     int e;
395     size_t slen;
396
397     e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l);
398     if (e) return e;
399     p += l;
400     len -= l;
401     ret += l;
402
403     e = der_get_length (p, len, &slen, &l);
404     if (e) return e;
405     p += l;
406     len -= l;
407     ret += l;
408     if (len < slen)
409         return ASN1_OVERRUN;
410
411     e = der_get_oid (p, slen, k, &l);
412     if (e) return e;
413     p += l;
414     len -= l;
415     ret += l;
416     if(size) *size = ret;
417     return 0;
418 }
419
420 static void
421 generalizedtime2time (const char *s, time_t *t)
422 {
423     struct tm tm;
424
425     memset(&tm, 0, sizeof(tm));
426     sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
427             &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
428             &tm.tm_min, &tm.tm_sec);
429     tm.tm_year -= 1900;
430     tm.tm_mon -= 1;
431     *t = timegm (&tm);
432 }
433
434 int
435 decode_generalized_time (const unsigned char *p, size_t len,
436                          time_t *t, size_t *size)
437 {
438     octet_string k;
439     char *times;
440     size_t ret = 0;
441     size_t l;
442     int e;
443     size_t slen;
444
445     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l);
446     if (e) return e;
447     p += l;
448     len -= l;
449     ret += l;
450
451     e = der_get_length (p, len, &slen, &l);
452     if (e) return e;
453     p += l;
454     len -= l;
455     ret += l;
456     if (len < slen)
457         return ASN1_OVERRUN;
458     e = der_get_octet_string (p, slen, &k, &l);
459     if (e) return e;
460     p += l;
461     len -= l;
462     ret += l;
463     times = realloc(k.data, k.length + 1);
464     if (times == NULL){
465         free(k.data);
466         return ENOMEM;
467     }
468     times[k.length] = 0;
469     generalizedtime2time (times, t);
470     free (times);
471     if(size) *size = ret;
472     return 0;
473 }
474
475
476 int
477 fix_dce(size_t reallen, size_t *len)
478 {
479     if(reallen == ASN1_INDEFINITE)
480         return 1;
481     if(*len < reallen)
482         return -1;
483     *len = reallen;
484     return 0;
485 }