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