Annotation of src/usr.bin/ldap/ber.c, Revision 1.14
1.14 ! rob 1: /* $OpenBSD: ber.c,v 1.13 2018/07/13 08:30:10 rob Exp $ */
1.1 reyk 2:
3: /*
1.6 rob 4: * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
1.1 reyk 5: * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
6: * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
7: *
8: * Permission to use, copy, modify, and distribute this software for any
9: * purpose with or without fee is hereby granted, provided that the above
10: * copyright notice and this permission notice appear in all copies.
11: *
12: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19: */
20:
21: #include <sys/types.h>
22:
23: #include <errno.h>
24: #include <limits.h>
25: #include <stdlib.h>
26: #include <err.h> /* XXX for debug output */
27: #include <stdio.h> /* XXX for debug output */
28: #include <string.h>
29: #include <unistd.h>
30: #include <stdarg.h>
31:
32: #include "ber.h"
33:
34: #define BER_TYPE_CONSTRUCTED 0x20 /* otherwise primitive */
35: #define BER_TYPE_SINGLE_MAX 30
36: #define BER_TAG_MASK 0x1f
37: #define BER_TAG_MORE 0x80 /* more subsequent octets */
38: #define BER_TAG_TYPE_MASK 0x7f
39: #define BER_CLASS_SHIFT 6
40:
41: static int ber_dump_element(struct ber *ber, struct ber_element *root);
42: static void ber_dump_header(struct ber *ber, struct ber_element *root);
43: static void ber_putc(struct ber *ber, u_char c);
44: static void ber_write(struct ber *ber, void *buf, size_t len);
45: static ssize_t get_id(struct ber *b, unsigned long *tag, int *class,
46: int *cstruct);
47: static ssize_t get_len(struct ber *b, ssize_t *len);
48: static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm);
49: static ssize_t ber_getc(struct ber *b, u_char *c);
50: static ssize_t ber_read(struct ber *ber, void *buf, size_t len);
51:
52: #ifdef DEBUG
53: #define DPRINTF(...) printf(__VA_ARGS__)
54: #else
55: #define DPRINTF(...) do { } while (0)
56: #endif
57:
58: struct ber_element *
59: ber_get_element(unsigned long encoding)
60: {
61: struct ber_element *elm;
62:
63: if ((elm = calloc(1, sizeof(*elm))) == NULL)
64: return NULL;
65:
66: elm->be_encoding = encoding;
67: ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
68:
69: return elm;
70: }
71:
72: void
73: ber_set_header(struct ber_element *elm, int class, unsigned long type)
74: {
75: elm->be_class = class & BER_CLASS_MASK;
76: if (type == BER_TYPE_DEFAULT)
77: type = elm->be_encoding;
78: elm->be_type = type;
79: }
80:
81: void
82: ber_link_elements(struct ber_element *prev, struct ber_element *elm)
83: {
84: if (prev != NULL) {
85: if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
86: prev->be_encoding == BER_TYPE_SET) &&
87: prev->be_sub == NULL)
88: prev->be_sub = elm;
89: else
90: prev->be_next = elm;
91: }
92: }
93:
94: struct ber_element *
95: ber_unlink_elements(struct ber_element *prev)
96: {
97: struct ber_element *elm;
98:
99: if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
100: prev->be_encoding == BER_TYPE_SET) &&
101: prev->be_sub != NULL) {
102: elm = prev->be_sub;
103: prev->be_sub = NULL;
104: } else {
105: elm = prev->be_next;
106: prev->be_next = NULL;
107: }
108:
109: return (elm);
110: }
111:
112: void
113: ber_replace_elements(struct ber_element *prev, struct ber_element *new)
114: {
115: struct ber_element *ber, *next;
116:
117: ber = ber_unlink_elements(prev);
118: next = ber_unlink_elements(ber);
119: ber_link_elements(new, next);
120: ber_link_elements(prev, new);
121:
122: /* cleanup old element */
123: ber_free_elements(ber);
124: }
125:
126: struct ber_element *
127: ber_add_sequence(struct ber_element *prev)
128: {
129: struct ber_element *elm;
130:
131: if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL)
132: return NULL;
133:
134: ber_link_elements(prev, elm);
135:
136: return elm;
137: }
138:
139: struct ber_element *
140: ber_add_set(struct ber_element *prev)
141: {
142: struct ber_element *elm;
143:
144: if ((elm = ber_get_element(BER_TYPE_SET)) == NULL)
145: return NULL;
146:
147: ber_link_elements(prev, elm);
148:
149: return elm;
150: }
151:
152: struct ber_element *
153: ber_add_enumerated(struct ber_element *prev, long long val)
154: {
155: struct ber_element *elm;
156: u_int i, len = 0;
157: u_char cur, last = 0;
158:
159: if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL)
160: return NULL;
161:
162: elm->be_numeric = val;
163:
164: for (i = 0; i < sizeof(long long); i++) {
165: cur = val & 0xff;
166: if (cur != 0 && cur != 0xff)
167: len = i;
168: if ((cur == 0 && last & 0x80) ||
169: (cur == 0xff && (last & 0x80) == 0))
170: len = i;
171: val >>= 8;
172: last = cur;
173: }
174: elm->be_len = len + 1;
175:
176: ber_link_elements(prev, elm);
177:
178: return elm;
179: }
180:
181: struct ber_element *
182: ber_add_integer(struct ber_element *prev, long long val)
183: {
184: struct ber_element *elm;
185: u_int i, len = 0;
186: u_char cur, last = 0;
187:
188: if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL)
189: return NULL;
190:
191: elm->be_numeric = val;
192:
193: for (i = 0; i < sizeof(long long); i++) {
194: cur = val & 0xff;
195: if (cur != 0 && cur != 0xff)
196: len = i;
197: if ((cur == 0 && last & 0x80) ||
198: (cur == 0xff && (last & 0x80) == 0))
199: len = i;
200: val >>= 8;
201: last = cur;
202: }
203: elm->be_len = len + 1;
204:
205: ber_link_elements(prev, elm);
206:
207: return elm;
208: }
209:
210: int
211: ber_get_integer(struct ber_element *elm, long long *n)
212: {
213: if (elm->be_encoding != BER_TYPE_INTEGER)
214: return -1;
215:
216: *n = elm->be_numeric;
217: return 0;
218: }
219:
220: int
221: ber_get_enumerated(struct ber_element *elm, long long *n)
222: {
223: if (elm->be_encoding != BER_TYPE_ENUMERATED)
224: return -1;
225:
226: *n = elm->be_numeric;
227: return 0;
228: }
229:
230: struct ber_element *
231: ber_add_boolean(struct ber_element *prev, int bool)
232: {
233: struct ber_element *elm;
234:
235: if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL)
236: return NULL;
237:
238: elm->be_numeric = bool ? 0xff : 0;
239: elm->be_len = 1;
240:
241: ber_link_elements(prev, elm);
242:
243: return elm;
244: }
245:
246: int
247: ber_get_boolean(struct ber_element *elm, int *b)
248: {
249: if (elm->be_encoding != BER_TYPE_BOOLEAN)
250: return -1;
251:
252: *b = !(elm->be_numeric == 0);
253: return 0;
254: }
255:
256: struct ber_element *
257: ber_add_string(struct ber_element *prev, const char *string)
258: {
259: return ber_add_nstring(prev, string, strlen(string));
260: }
261:
262: struct ber_element *
263: ber_add_nstring(struct ber_element *prev, const char *string0, size_t len)
264: {
265: struct ber_element *elm;
266: char *string;
267:
1.3 rob 268: if ((string = calloc(1, len + 1)) == NULL)
1.1 reyk 269: return NULL;
270: if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
271: free(string);
272: return NULL;
273: }
274:
275: bcopy(string0, string, len);
276: elm->be_val = string;
277: elm->be_len = len;
278: elm->be_free = 1; /* free string on cleanup */
279:
280: ber_link_elements(prev, elm);
281:
282: return elm;
283: }
284:
285: int
286: ber_get_string(struct ber_element *elm, char **s)
287: {
288: if (elm->be_encoding != BER_TYPE_OCTETSTRING)
289: return -1;
290:
291: *s = elm->be_val;
292: return 0;
293: }
294:
295: int
296: ber_get_nstring(struct ber_element *elm, void **p, size_t *len)
297: {
298: if (elm->be_encoding != BER_TYPE_OCTETSTRING)
299: return -1;
300:
301: *p = elm->be_val;
302: *len = elm->be_len;
303: return 0;
304: }
305:
306: struct ber_element *
307: ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
308: {
309: struct ber_element *elm;
310: void *v;
311:
312: if ((v = calloc(1, len)) == NULL)
313: return NULL;
314: if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) {
315: free(v);
316: return NULL;
317: }
318:
319: bcopy(v0, v, len);
320: elm->be_val = v;
321: elm->be_len = len;
322: elm->be_free = 1; /* free string on cleanup */
323:
324: ber_link_elements(prev, elm);
325:
326: return elm;
327: }
328:
329: int
330: ber_get_bitstring(struct ber_element *elm, void **v, size_t *len)
331: {
332: if (elm->be_encoding != BER_TYPE_BITSTRING)
333: return -1;
334:
335: *v = elm->be_val;
336: *len = elm->be_len;
337: return 0;
338: }
339:
340: struct ber_element *
341: ber_add_null(struct ber_element *prev)
342: {
343: struct ber_element *elm;
344:
345: if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL)
346: return NULL;
347:
348: ber_link_elements(prev, elm);
349:
350: return elm;
351: }
352:
353: int
354: ber_get_null(struct ber_element *elm)
355: {
356: if (elm->be_encoding != BER_TYPE_NULL)
357: return -1;
358:
359: return 0;
360: }
361:
362: struct ber_element *
363: ber_add_eoc(struct ber_element *prev)
364: {
365: struct ber_element *elm;
366:
367: if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL)
368: return NULL;
369:
370: ber_link_elements(prev, elm);
371:
372: return elm;
373: }
374:
375: int
376: ber_get_eoc(struct ber_element *elm)
377: {
378: if (elm->be_encoding != BER_TYPE_EOC)
379: return -1;
380:
381: return 0;
382: }
383:
384: size_t
385: ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
386: {
387: u_int32_t v;
388: u_int i, j = 0, k;
389:
390: if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
391: o->bo_id[0] > 2 || o->bo_id[1] > 40)
392: return (0);
393:
394: v = (o->bo_id[0] * 40) + o->bo_id[1];
395: for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
396: for (k = 28; k >= 7; k -= 7) {
397: if (v >= (u_int)(1 << k)) {
398: if (len)
399: buf[j] = v >> k | BER_TAG_MORE;
400: j++;
401: }
402: }
403: if (len)
404: buf[j] = v & BER_TAG_TYPE_MASK;
405: j++;
406: }
407:
408: return (j);
409: }
410:
411: int
412: ber_string2oid(const char *oidstr, struct ber_oid *o)
413: {
414: char *sp, *p, str[BUFSIZ];
415: const char *errstr;
416:
417: if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
418: return (-1);
419: memset(o, 0, sizeof(*o));
420:
421: /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
422: for (p = sp = str; p != NULL; sp = p) {
423: if ((p = strpbrk(p, "._-")) != NULL)
424: *p++ = '\0';
425: o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
426: if (errstr || o->bo_n > BER_MAX_OID_LEN)
427: return (-1);
428: }
429:
430: return (0);
431: }
432:
433: struct ber_element *
434: ber_add_oid(struct ber_element *prev, struct ber_oid *o)
435: {
436: struct ber_element *elm;
437: u_int8_t *buf;
438: size_t len;
439:
440: if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
441: return (NULL);
442:
443: if ((len = ber_oid2ber(o, NULL, 0)) == 0)
444: goto fail;
445:
446: if ((buf = calloc(1, len)) == NULL)
447: goto fail;
448:
449: elm->be_val = buf;
450: elm->be_len = len;
451: elm->be_free = 1;
452:
453: if (ber_oid2ber(o, buf, len) != len)
454: goto fail;
455:
456: ber_link_elements(prev, elm);
457:
458: return (elm);
459:
460: fail:
461: ber_free_elements(elm);
462: return (NULL);
463: }
464:
465: struct ber_element *
466: ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
467: {
468: struct ber_oid no;
469:
470: if (n > BER_MAX_OID_LEN)
471: return (NULL);
472: no.bo_n = n;
473: bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
474:
475: return (ber_add_oid(prev, &no));
476: }
477:
478: struct ber_element *
479: ber_add_oidstring(struct ber_element *prev, const char *oidstr)
480: {
481: struct ber_oid o;
482:
483: if (ber_string2oid(oidstr, &o) == -1)
484: return (NULL);
485:
486: return (ber_add_oid(prev, &o));
487: }
488:
489: int
490: ber_get_oid(struct ber_element *elm, struct ber_oid *o)
491: {
492: u_int8_t *buf;
493: size_t len, i = 0, j = 0;
494:
495: if (elm->be_encoding != BER_TYPE_OBJECT)
496: return (-1);
497:
498: buf = elm->be_val;
499: len = elm->be_len;
500:
501: if (!buf[i])
502: return (-1);
503:
504: memset(o, 0, sizeof(*o));
505: o->bo_id[j++] = buf[i] / 40;
506: o->bo_id[j++] = buf[i++] % 40;
507: for (; i < len && j < BER_MAX_OID_LEN; i++) {
508: o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
509: if (buf[i] & 0x80)
510: continue;
511: j++;
512: }
513: o->bo_n = j;
514:
515: return (0);
516: }
517:
518: struct ber_element *
519: ber_printf_elements(struct ber_element *ber, char *fmt, ...)
520: {
521: va_list ap;
522: int d, class;
523: size_t len;
524: unsigned long type;
525: long long i;
526: char *s;
527: void *p;
528: struct ber_oid *o;
529: struct ber_element *sub = ber, *e;
530:
531: va_start(ap, fmt);
532: while (*fmt) {
533: switch (*fmt++) {
534: case 'B':
535: p = va_arg(ap, void *);
536: len = va_arg(ap, size_t);
537: if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
538: goto fail;
539: break;
540: case 'b':
541: d = va_arg(ap, int);
542: if ((ber = ber_add_boolean(ber, d)) == NULL)
543: goto fail;
544: break;
545: case 'd':
546: d = va_arg(ap, int);
547: if ((ber = ber_add_integer(ber, d)) == NULL)
548: goto fail;
549: break;
550: case 'e':
551: e = va_arg(ap, struct ber_element *);
552: ber_link_elements(ber, e);
553: break;
554: case 'E':
555: i = va_arg(ap, long long);
556: if ((ber = ber_add_enumerated(ber, i)) == NULL)
557: goto fail;
558: break;
559: case 'i':
560: i = va_arg(ap, long long);
561: if ((ber = ber_add_integer(ber, i)) == NULL)
562: goto fail;
563: break;
564: case 'O':
565: o = va_arg(ap, struct ber_oid *);
566: if ((ber = ber_add_oid(ber, o)) == NULL)
567: goto fail;
568: break;
569: case 'o':
570: s = va_arg(ap, char *);
571: if ((ber = ber_add_oidstring(ber, s)) == NULL)
572: goto fail;
573: break;
574: case 's':
575: s = va_arg(ap, char *);
576: if ((ber = ber_add_string(ber, s)) == NULL)
577: goto fail;
578: break;
579: case 't':
580: class = va_arg(ap, int);
581: type = va_arg(ap, unsigned long);
582: ber_set_header(ber, class, type);
583: break;
584: case 'x':
585: s = va_arg(ap, char *);
586: len = va_arg(ap, size_t);
587: if ((ber = ber_add_nstring(ber, s, len)) == NULL)
588: goto fail;
589: break;
590: case '0':
591: if ((ber = ber_add_null(ber)) == NULL)
592: goto fail;
593: break;
594: case '{':
595: if ((ber = sub = ber_add_sequence(ber)) == NULL)
596: goto fail;
597: break;
598: case '(':
599: if ((ber = sub = ber_add_set(ber)) == NULL)
600: goto fail;
601: break;
602: case '}':
603: case ')':
604: ber = sub;
605: break;
606: case '.':
607: if ((e = ber_add_eoc(ber)) == NULL)
608: goto fail;
609: ber = e;
610: break;
611: default:
612: break;
613: }
614: }
615: va_end(ap);
616:
617: return (ber);
618: fail:
619: ber_free_elements(ber);
620: return (NULL);
621: }
622:
623: int
624: ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
625: {
626: #define _MAX_SEQ 128
627: va_list ap;
628: int *d, level = -1;
629: unsigned long *t;
1.8 rob 630: long long *i, l;
1.1 reyk 631: void **ptr;
632: size_t *len, ret = 0, n = strlen(fmt);
633: char **s;
1.8 rob 634: off_t *pos;
1.1 reyk 635: struct ber_oid *o;
636: struct ber_element *parent[_MAX_SEQ], **e;
637:
638: memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
639:
640: va_start(ap, fmt);
641: while (*fmt) {
642: switch (*fmt++) {
643: case 'B':
644: ptr = va_arg(ap, void **);
645: len = va_arg(ap, size_t *);
646: if (ber_get_bitstring(ber, ptr, len) == -1)
647: goto fail;
648: ret++;
649: break;
650: case 'b':
651: d = va_arg(ap, int *);
652: if (ber_get_boolean(ber, d) == -1)
653: goto fail;
654: ret++;
655: break;
1.8 rob 656: case 'd':
657: d = va_arg(ap, int *);
658: if (ber_get_integer(ber, &l) == -1)
659: goto fail;
660: *d = l;
661: ret++;
662: break;
1.1 reyk 663: case 'e':
664: e = va_arg(ap, struct ber_element **);
665: *e = ber;
666: ret++;
667: continue;
668: case 'E':
669: i = va_arg(ap, long long *);
670: if (ber_get_enumerated(ber, i) == -1)
671: goto fail;
672: ret++;
673: break;
674: case 'i':
675: i = va_arg(ap, long long *);
676: if (ber_get_integer(ber, i) == -1)
677: goto fail;
678: ret++;
679: break;
680: case 'o':
681: o = va_arg(ap, struct ber_oid *);
682: if (ber_get_oid(ber, o) == -1)
683: goto fail;
684: ret++;
685: break;
686: case 'S':
687: ret++;
688: break;
689: case 's':
690: s = va_arg(ap, char **);
691: if (ber_get_string(ber, s) == -1)
692: goto fail;
693: ret++;
694: break;
695: case 't':
696: d = va_arg(ap, int *);
697: t = va_arg(ap, unsigned long *);
698: *d = ber->be_class;
699: *t = ber->be_type;
700: ret++;
701: continue;
702: case 'x':
703: ptr = va_arg(ap, void **);
704: len = va_arg(ap, size_t *);
705: if (ber_get_nstring(ber, ptr, len) == -1)
706: goto fail;
707: ret++;
708: break;
709: case '0':
710: if (ber->be_encoding != BER_TYPE_NULL)
711: goto fail;
712: ret++;
713: break;
714: case '.':
715: if (ber->be_encoding != BER_TYPE_EOC)
716: goto fail;
717: ret++;
718: break;
1.8 rob 719: case 'p':
720: pos = va_arg(ap, off_t *);
721: *pos = ber_getpos(ber);
722: ret++;
723: continue;
1.1 reyk 724: case '{':
725: case '(':
726: if (ber->be_encoding != BER_TYPE_SEQUENCE &&
727: ber->be_encoding != BER_TYPE_SET)
728: goto fail;
729: if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
730: goto fail;
731: parent[++level] = ber;
732: ber = ber->be_sub;
733: ret++;
734: continue;
735: case '}':
736: case ')':
737: if (parent[level] == NULL)
738: goto fail;
739: ber = parent[level--];
740: ret++;
1.5 rob 741: break;
1.1 reyk 742: default:
743: goto fail;
744: }
745:
746: if (ber->be_next == NULL)
747: continue;
748: ber = ber->be_next;
749: }
750: va_end(ap);
751: return (ret == n ? 0 : -1);
752:
753: fail:
754: va_end(ap);
755: return (-1);
756:
757: }
758:
759: /*
1.14 ! rob 760: * write ber elements to the write buffer
1.1 reyk 761: *
762: * params:
1.14 ! rob 763: * ber holds the destination write buffer byte stream
1.1 reyk 764: * root fully populated element tree
765: *
766: * returns:
1.10 rob 767: * >=0 number of bytes written
1.1 reyk 768: * -1 on failure and sets errno
769: */
770: int
771: ber_write_elements(struct ber *ber, struct ber_element *root)
772: {
773: size_t len;
774:
775: /* calculate length because only the definite form is required */
776: len = ber_calc_len(root);
777: DPRINTF("write ber element of %zd bytes length\n", len);
778:
779: if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
780: free(ber->br_wbuf);
781: ber->br_wbuf = NULL;
782: }
783: if (ber->br_wbuf == NULL) {
784: if ((ber->br_wbuf = malloc(len)) == NULL)
785: return -1;
786: ber->br_wend = ber->br_wbuf + len;
787: }
788:
789: /* reset write pointer */
790: ber->br_wptr = ber->br_wbuf;
791:
792: if (ber_dump_element(ber, root) == -1)
793: return -1;
794:
795: return (len);
796: }
797:
798: /*
1.14 ! rob 799: * read ber elements from the read buffer
1.1 reyk 800: *
801: * params:
1.14 ! rob 802: * ber holds a fully populated read buffer byte stream
1.1 reyk 803: * root if NULL, build up an element tree from what we receive on
804: * the wire. If not null, use the specified encoding for the
805: * elements received.
806: *
807: * returns:
808: * !=NULL, elements read and store in the ber_element tree
809: * NULL, type mismatch or read error
810: */
811: struct ber_element *
812: ber_read_elements(struct ber *ber, struct ber_element *elm)
813: {
814: struct ber_element *root = elm;
815:
816: if (root == NULL) {
817: if ((root = ber_get_element(0)) == NULL)
818: return NULL;
819: }
820:
821: DPRINTF("read ber elements, root %p\n", root);
822:
823: if (ber_read_element(ber, root) == -1) {
824: /* Cleanup if root was allocated by us */
825: if (elm == NULL)
826: ber_free_elements(root);
827: return NULL;
828: }
829:
830: return root;
831: }
832:
1.8 rob 833: off_t
834: ber_getpos(struct ber_element *elm)
835: {
836: return elm->be_offs;
837: }
838:
1.1 reyk 839: void
1.5 rob 840: ber_free_element(struct ber_element *root)
841: {
842: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
843: root->be_encoding == BER_TYPE_SET))
844: ber_free_elements(root->be_sub);
845: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
846: root->be_encoding == BER_TYPE_BITSTRING ||
847: root->be_encoding == BER_TYPE_OBJECT))
848: free(root->be_val);
849: free(root);
850: }
851:
852: void
1.1 reyk 853: ber_free_elements(struct ber_element *root)
854: {
855: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
856: root->be_encoding == BER_TYPE_SET))
857: ber_free_elements(root->be_sub);
858: if (root->be_next)
859: ber_free_elements(root->be_next);
860: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
861: root->be_encoding == BER_TYPE_BITSTRING ||
862: root->be_encoding == BER_TYPE_OBJECT))
863: free(root->be_val);
864: free(root);
865: }
866:
867: size_t
868: ber_calc_len(struct ber_element *root)
869: {
870: unsigned long t;
871: size_t s;
872: size_t size = 2; /* minimum 1 byte head and 1 byte size */
873:
874: /* calculate the real length of a sequence or set */
875: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
876: root->be_encoding == BER_TYPE_SET))
877: root->be_len = ber_calc_len(root->be_sub);
878:
879: /* fix header length for extended types */
880: if (root->be_type > BER_TYPE_SINGLE_MAX)
881: for (t = root->be_type; t > 0; t >>= 7)
882: size++;
883: if (root->be_len >= BER_TAG_MORE)
884: for (s = root->be_len; s > 0; s >>= 8)
885: size++;
886:
887: /* calculate the length of the following elements */
888: if (root->be_next)
889: size += ber_calc_len(root->be_next);
890:
891: /* This is an empty element, do not use a minimal size */
1.2 rob 892: if (root->be_class == BER_CLASS_UNIVERSAL &&
893: root->be_type == BER_TYPE_EOC && root->be_len == 0)
1.1 reyk 894: return (0);
895:
896: return (root->be_len + size);
897: }
898:
899: /*
900: * internal functions
901: */
902:
903: static int
904: ber_dump_element(struct ber *ber, struct ber_element *root)
905: {
906: unsigned long long l;
907: int i;
908: uint8_t u;
909:
910: ber_dump_header(ber, root);
1.8 rob 911: if (root->be_cb)
912: root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1.1 reyk 913:
914: switch (root->be_encoding) {
915: case BER_TYPE_BOOLEAN:
916: case BER_TYPE_INTEGER:
917: case BER_TYPE_ENUMERATED:
918: l = (unsigned long long)root->be_numeric;
919: for (i = root->be_len; i > 0; i--) {
920: u = (l >> ((i - 1) * 8)) & 0xff;
921: ber_putc(ber, u);
922: }
923: break;
924: case BER_TYPE_BITSTRING:
925: return -1;
926: case BER_TYPE_OCTETSTRING:
927: case BER_TYPE_OBJECT:
928: ber_write(ber, root->be_val, root->be_len);
929: break;
930: case BER_TYPE_NULL: /* no payload */
931: case BER_TYPE_EOC:
932: break;
933: case BER_TYPE_SEQUENCE:
934: case BER_TYPE_SET:
935: if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
936: return -1;
937: break;
938: }
939:
940: if (root->be_next == NULL)
941: return 0;
942: return ber_dump_element(ber, root->be_next);
943: }
944:
945: static void
946: ber_dump_header(struct ber *ber, struct ber_element *root)
947: {
948: u_char id = 0, t, buf[8];
949: unsigned long type;
950: size_t size;
951:
952: /* class universal, type encoding depending on type value */
953: /* length encoding */
954: if (root->be_type <= BER_TYPE_SINGLE_MAX) {
955: id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
956: if (root->be_encoding == BER_TYPE_SEQUENCE ||
957: root->be_encoding == BER_TYPE_SET)
958: id |= BER_TYPE_CONSTRUCTED;
959:
960: ber_putc(ber, id);
961: } else {
962: id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
963: if (root->be_encoding == BER_TYPE_SEQUENCE ||
964: root->be_encoding == BER_TYPE_SET)
965: id |= BER_TYPE_CONSTRUCTED;
966:
967: ber_putc(ber, id);
968:
969: for (t = 0, type = root->be_type; type > 0; type >>= 7)
970: buf[t++] = type & ~BER_TAG_MORE;
971:
972: while (t-- > 0) {
973: if (t > 0)
974: buf[t] |= BER_TAG_MORE;
975: ber_putc(ber, buf[t]);
976: }
977: }
978:
979: if (root->be_len < BER_TAG_MORE) {
980: /* short form */
981: ber_putc(ber, root->be_len);
982: } else {
983: for (t = 0, size = root->be_len; size > 0; size >>= 8)
984: buf[t++] = size & 0xff;
985:
986: ber_putc(ber, t | BER_TAG_MORE);
987:
988: while (t > 0)
989: ber_putc(ber, buf[--t]);
990: }
991: }
992:
993: static void
994: ber_putc(struct ber *ber, u_char c)
995: {
996: if (ber->br_wptr + 1 <= ber->br_wend)
997: *ber->br_wptr = c;
998: ber->br_wptr++;
999: }
1000:
1001: static void
1002: ber_write(struct ber *ber, void *buf, size_t len)
1003: {
1004: if (ber->br_wptr + len <= ber->br_wend)
1005: bcopy(buf, ber->br_wptr, len);
1006: ber->br_wptr += len;
1007: }
1008:
1009: /*
1010: * extract a BER encoded tag. There are two types, a short and long form.
1011: */
1012: static ssize_t
1013: get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
1014: {
1015: u_char u;
1016: size_t i = 0;
1017: unsigned long t = 0;
1018:
1019: if (ber_getc(b, &u) == -1)
1020: return -1;
1021:
1022: *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1023: *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1024:
1025: if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1026: *tag = u & BER_TAG_MASK;
1027: return 1;
1028: }
1029:
1030: do {
1031: if (ber_getc(b, &u) == -1)
1032: return -1;
1033: t = (t << 7) | (u & ~BER_TAG_MORE);
1034: i++;
1.13 rob 1035: if (i > sizeof(unsigned long)) {
1036: errno = ERANGE;
1037: return -1;
1038: }
1.1 reyk 1039: } while (u & BER_TAG_MORE);
1040:
1041: *tag = t;
1042: return i + 1;
1043: }
1044:
1045: /*
1046: * extract length of a ber object -- if length is unknown an error is returned.
1047: */
1048: static ssize_t
1049: get_len(struct ber *b, ssize_t *len)
1050: {
1051: u_char u, n;
1052: ssize_t s, r;
1053:
1054: if (ber_getc(b, &u) == -1)
1055: return -1;
1056: if ((u & BER_TAG_MORE) == 0) {
1057: /* short form */
1058: *len = u;
1059: return 1;
1060: }
1061:
1.5 rob 1062: if (u == 0x80) {
1063: /* Indefinite length not supported. */
1064: errno = EINVAL;
1065: return -1;
1066: }
1067:
1.1 reyk 1068: n = u & ~BER_TAG_MORE;
1069: if (sizeof(ssize_t) < n) {
1070: errno = ERANGE;
1071: return -1;
1072: }
1073: r = n + 1;
1074:
1075: for (s = 0; n > 0; n--) {
1076: if (ber_getc(b, &u) == -1)
1077: return -1;
1078: s = (s << 8) | u;
1079: }
1080:
1081: if (s < 0) {
1082: /* overflow */
1083: errno = ERANGE;
1084: return -1;
1085: }
1086:
1087: *len = s;
1088: return r;
1089: }
1090:
1091: static ssize_t
1092: ber_read_element(struct ber *ber, struct ber_element *elm)
1093: {
1094: long long val = 0;
1095: struct ber_element *next;
1096: unsigned long type;
1097: int i, class, cstruct;
1098: ssize_t len, r, totlen = 0;
1099: u_char c;
1100:
1101: if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1102: return -1;
1103: DPRINTF("ber read got class %d type %lu, %s\n",
1.7 rob 1104: class, type, cstruct ? "constructed" : "primitive");
1.1 reyk 1105: totlen += r;
1106: if ((r = get_len(ber, &len)) == -1)
1107: return -1;
1108: DPRINTF("ber read element size %zd\n", len);
1109: totlen += r + len;
1110:
1.4 rob 1111: /* If the total size of the element is larger than the buffer
1112: * don't bother to continue. */
1.1 reyk 1113: if (len > ber->br_rend - ber->br_rptr) {
1114: errno = ECANCELED;
1115: return -1;
1116: }
1117:
1118: elm->be_type = type;
1119: elm->be_len = len;
1.8 rob 1120: elm->be_offs = ber->br_offs; /* element position within stream */
1.1 reyk 1121: elm->be_class = class;
1122:
1123: if (elm->be_encoding == 0) {
1124: /* try to figure out the encoding via class, type and cstruct */
1125: if (cstruct)
1126: elm->be_encoding = BER_TYPE_SEQUENCE;
1127: else if (class == BER_CLASS_UNIVERSAL)
1128: elm->be_encoding = type;
1129: else if (ber->br_application != NULL) {
1130: /*
1131: * Ask the application to map the encoding to a
1132: * universal type. For example, a SMI IpAddress
1133: * type is defined as 4 byte OCTET STRING.
1134: */
1135: elm->be_encoding = (*ber->br_application)(elm);
1136: } else
1137: /* last resort option */
1138: elm->be_encoding = BER_TYPE_NULL;
1139: }
1140:
1141: switch (elm->be_encoding) {
1142: case BER_TYPE_EOC: /* End-Of-Content */
1143: break;
1144: case BER_TYPE_BOOLEAN:
1145: case BER_TYPE_INTEGER:
1146: case BER_TYPE_ENUMERATED:
1147: if (len > (ssize_t)sizeof(long long))
1148: return -1;
1149: for (i = 0; i < len; i++) {
1150: if (ber_getc(ber, &c) != 1)
1151: return -1;
1152: val <<= 8;
1153: val |= c;
1154: }
1155:
1156: /* sign extend if MSB is set */
1157: if (val >> ((i - 1) * 8) & 0x80)
1158: val |= ULLONG_MAX << (i * 8);
1159: elm->be_numeric = val;
1160: break;
1161: case BER_TYPE_BITSTRING:
1162: elm->be_val = malloc(len);
1163: if (elm->be_val == NULL)
1164: return -1;
1165: elm->be_free = 1;
1166: elm->be_len = len;
1167: ber_read(ber, elm->be_val, len);
1168: break;
1169: case BER_TYPE_OCTETSTRING:
1170: case BER_TYPE_OBJECT:
1171: elm->be_val = malloc(len + 1);
1172: if (elm->be_val == NULL)
1173: return -1;
1174: elm->be_free = 1;
1175: elm->be_len = len;
1176: ber_read(ber, elm->be_val, len);
1177: ((u_char *)elm->be_val)[len] = '\0';
1178: break;
1179: case BER_TYPE_NULL: /* no payload */
1180: if (len != 0)
1181: return -1;
1182: break;
1183: case BER_TYPE_SEQUENCE:
1184: case BER_TYPE_SET:
1185: if (elm->be_sub == NULL) {
1186: if ((elm->be_sub = ber_get_element(0)) == NULL)
1187: return -1;
1188: }
1189: next = elm->be_sub;
1190: while (len > 0) {
1191: r = ber_read_element(ber, next);
1192: if (r == -1)
1193: return -1;
1194: len -= r;
1195: if (len > 0 && next->be_next == NULL) {
1196: if ((next->be_next = ber_get_element(0)) ==
1197: NULL)
1198: return -1;
1199: }
1200: next = next->be_next;
1201: }
1202: break;
1203: }
1204: return totlen;
1205: }
1206:
1207: void
1208: ber_set_readbuf(struct ber *b, void *buf, size_t len)
1209: {
1210: b->br_rbuf = b->br_rptr = buf;
1211: b->br_rend = (u_int8_t *)buf + len;
1212: }
1213:
1214: ssize_t
1215: ber_get_writebuf(struct ber *b, void **buf)
1216: {
1217: if (b->br_wbuf == NULL)
1218: return -1;
1219: *buf = b->br_wbuf;
1220: return (b->br_wend - b->br_wbuf);
1221: }
1222:
1223: void
1224: ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
1225: {
1226: b->br_application = cb;
1227: }
1228:
1229: void
1.8 rob 1230: ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
1231: void *arg)
1232: {
1233: elm->be_cb = cb;
1234: elm->be_cbarg = arg;
1235: }
1236:
1237: void
1.1 reyk 1238: ber_free(struct ber *b)
1239: {
1240: free(b->br_wbuf);
1241: }
1242:
1243: static ssize_t
1244: ber_getc(struct ber *b, u_char *c)
1245: {
1.12 jca 1246: return ber_read(b, c, 1);
1.1 reyk 1247: }
1248:
1249: static ssize_t
1250: ber_read(struct ber *ber, void *buf, size_t len)
1251: {
1.12 jca 1252: size_t sz;
1253:
1254: if (ber->br_rbuf == NULL)
1255: return -1;
1.1 reyk 1256:
1.12 jca 1257: sz = ber->br_rend - ber->br_rptr;
1258: if (len > sz) {
1259: errno = ECANCELED;
1260: return -1; /* parser wants more data than available */
1.1 reyk 1261: }
1.12 jca 1262:
1263: bcopy(ber->br_rptr, buf, len);
1264: ber->br_rptr += len;
1265: ber->br_offs += len;
1266:
1267: return len;
1.8 rob 1268: }
1269:
1270: int
1271: ber_oid_cmp(struct ber_oid *a, struct ber_oid *b)
1272: {
1273: size_t i;
1274: for (i = 0; i < BER_MAX_OID_LEN; i++) {
1275: if (a->bo_id[i] != 0) {
1276: if (a->bo_id[i] == b->bo_id[i])
1277: continue;
1278: else if (a->bo_id[i] < b->bo_id[i]) {
1279: /* b is a successor of a */
1280: return (1);
1281: } else {
1282: /* b is a predecessor of a */
1283: return (-1);
1.11 rob 1284: }
1.8 rob 1285: } else if (b->bo_id[i] != 0) {
1286: /* b is larger, but a child of a */
1287: return (2);
1288: } else
1289: break;
1290: }
1291:
1292: /* b and a are identical */
1293: return (0);
1.1 reyk 1294: }