Annotation of src/usr.bin/ldap/ber.c, Revision 1.1.1.1
1.1 reyk 1: /* $OpenBSD: ber.c,v 1.13 2018/02/08 18:02:06 jca Exp $ */
2:
3: /*
4: * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
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:
272: if ((string = calloc(1, len)) == NULL)
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;
634: long long *i;
635: void **ptr;
636: size_t *len, ret = 0, n = strlen(fmt);
637: char **s;
638: struct ber_oid *o;
639: struct ber_element *parent[_MAX_SEQ], **e;
640:
641: memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
642:
643: va_start(ap, fmt);
644: while (*fmt) {
645: switch (*fmt++) {
646: case 'B':
647: ptr = va_arg(ap, void **);
648: len = va_arg(ap, size_t *);
649: if (ber_get_bitstring(ber, ptr, len) == -1)
650: goto fail;
651: ret++;
652: break;
653: case 'b':
654: d = va_arg(ap, int *);
655: if (ber_get_boolean(ber, d) == -1)
656: goto fail;
657: ret++;
658: break;
659: case 'e':
660: e = va_arg(ap, struct ber_element **);
661: *e = ber;
662: ret++;
663: continue;
664: case 'E':
665: i = va_arg(ap, long long *);
666: if (ber_get_enumerated(ber, i) == -1)
667: goto fail;
668: ret++;
669: break;
670: case 'i':
671: i = va_arg(ap, long long *);
672: if (ber_get_integer(ber, i) == -1)
673: goto fail;
674: ret++;
675: break;
676: case 'o':
677: o = va_arg(ap, struct ber_oid *);
678: if (ber_get_oid(ber, o) == -1)
679: goto fail;
680: ret++;
681: break;
682: case 'S':
683: ret++;
684: break;
685: case 's':
686: s = va_arg(ap, char **);
687: if (ber_get_string(ber, s) == -1)
688: goto fail;
689: ret++;
690: break;
691: case 't':
692: d = va_arg(ap, int *);
693: t = va_arg(ap, unsigned long *);
694: *d = ber->be_class;
695: *t = ber->be_type;
696: ret++;
697: continue;
698: case 'x':
699: ptr = va_arg(ap, void **);
700: len = va_arg(ap, size_t *);
701: if (ber_get_nstring(ber, ptr, len) == -1)
702: goto fail;
703: ret++;
704: break;
705: case '0':
706: if (ber->be_encoding != BER_TYPE_NULL)
707: goto fail;
708: ret++;
709: break;
710: case '.':
711: if (ber->be_encoding != BER_TYPE_EOC)
712: goto fail;
713: ret++;
714: break;
715: case '{':
716: case '(':
717: if (ber->be_encoding != BER_TYPE_SEQUENCE &&
718: ber->be_encoding != BER_TYPE_SET)
719: goto fail;
720: if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
721: goto fail;
722: parent[++level] = ber;
723: ber = ber->be_sub;
724: ret++;
725: continue;
726: case '}':
727: case ')':
728: if (parent[level] == NULL)
729: goto fail;
730: ber = parent[level--];
731: ret++;
732: continue;
733: default:
734: goto fail;
735: }
736:
737: if (ber->be_next == NULL)
738: continue;
739: ber = ber->be_next;
740: }
741: va_end(ap);
742: return (ret == n ? 0 : -1);
743:
744: fail:
745: va_end(ap);
746: return (-1);
747:
748: }
749:
750: /*
751: * write ber elements to the socket
752: *
753: * params:
754: * ber holds the socket
755: * root fully populated element tree
756: *
757: * returns:
758: * >=0 number of bytes written
759: * -1 on failure and sets errno
760: */
761: int
762: ber_write_elements(struct ber *ber, struct ber_element *root)
763: {
764: size_t len;
765:
766: /* calculate length because only the definite form is required */
767: len = ber_calc_len(root);
768: DPRINTF("write ber element of %zd bytes length\n", len);
769:
770: if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
771: free(ber->br_wbuf);
772: ber->br_wbuf = NULL;
773: }
774: if (ber->br_wbuf == NULL) {
775: if ((ber->br_wbuf = malloc(len)) == NULL)
776: return -1;
777: ber->br_wend = ber->br_wbuf + len;
778: }
779:
780: /* reset write pointer */
781: ber->br_wptr = ber->br_wbuf;
782:
783: if (ber_dump_element(ber, root) == -1)
784: return -1;
785:
786: return (len);
787: }
788:
789: /*
790: * read ber elements from the socket
791: *
792: * params:
793: * ber holds the socket and lot more
794: * root if NULL, build up an element tree from what we receive on
795: * the wire. If not null, use the specified encoding for the
796: * elements received.
797: *
798: * returns:
799: * !=NULL, elements read and store in the ber_element tree
800: * NULL, type mismatch or read error
801: */
802: struct ber_element *
803: ber_read_elements(struct ber *ber, struct ber_element *elm)
804: {
805: struct ber_element *root = elm;
806:
807: if (root == NULL) {
808: if ((root = ber_get_element(0)) == NULL)
809: return NULL;
810: }
811:
812: DPRINTF("read ber elements, root %p\n", root);
813:
814: if (ber_read_element(ber, root) == -1) {
815: /* Cleanup if root was allocated by us */
816: if (elm == NULL)
817: ber_free_elements(root);
818: return NULL;
819: }
820:
821: return root;
822: }
823:
824: void
825: ber_free_elements(struct ber_element *root)
826: {
827: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
828: root->be_encoding == BER_TYPE_SET))
829: ber_free_elements(root->be_sub);
830: if (root->be_next)
831: ber_free_elements(root->be_next);
832: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
833: root->be_encoding == BER_TYPE_BITSTRING ||
834: root->be_encoding == BER_TYPE_OBJECT))
835: free(root->be_val);
836: free(root);
837: }
838:
839: size_t
840: ber_calc_len(struct ber_element *root)
841: {
842: unsigned long t;
843: size_t s;
844: size_t size = 2; /* minimum 1 byte head and 1 byte size */
845:
846: /* calculate the real length of a sequence or set */
847: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
848: root->be_encoding == BER_TYPE_SET))
849: root->be_len = ber_calc_len(root->be_sub);
850:
851: /* fix header length for extended types */
852: if (root->be_type > BER_TYPE_SINGLE_MAX)
853: for (t = root->be_type; t > 0; t >>= 7)
854: size++;
855: if (root->be_len >= BER_TAG_MORE)
856: for (s = root->be_len; s > 0; s >>= 8)
857: size++;
858:
859: /* calculate the length of the following elements */
860: if (root->be_next)
861: size += ber_calc_len(root->be_next);
862:
863: /* This is an empty element, do not use a minimal size */
864: if (root->be_type == BER_TYPE_EOC && root->be_len == 0)
865: return (0);
866:
867: return (root->be_len + size);
868: }
869:
870: /*
871: * internal functions
872: */
873:
874: static int
875: ber_dump_element(struct ber *ber, struct ber_element *root)
876: {
877: unsigned long long l;
878: int i;
879: uint8_t u;
880:
881: ber_dump_header(ber, root);
882:
883: switch (root->be_encoding) {
884: case BER_TYPE_BOOLEAN:
885: case BER_TYPE_INTEGER:
886: case BER_TYPE_ENUMERATED:
887: l = (unsigned long long)root->be_numeric;
888: for (i = root->be_len; i > 0; i--) {
889: u = (l >> ((i - 1) * 8)) & 0xff;
890: ber_putc(ber, u);
891: }
892: break;
893: case BER_TYPE_BITSTRING:
894: return -1;
895: case BER_TYPE_OCTETSTRING:
896: case BER_TYPE_OBJECT:
897: ber_write(ber, root->be_val, root->be_len);
898: break;
899: case BER_TYPE_NULL: /* no payload */
900: case BER_TYPE_EOC:
901: break;
902: case BER_TYPE_SEQUENCE:
903: case BER_TYPE_SET:
904: if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
905: return -1;
906: break;
907: }
908:
909: if (root->be_next == NULL)
910: return 0;
911: return ber_dump_element(ber, root->be_next);
912: }
913:
914: static void
915: ber_dump_header(struct ber *ber, struct ber_element *root)
916: {
917: u_char id = 0, t, buf[8];
918: unsigned long type;
919: size_t size;
920:
921: /* class universal, type encoding depending on type value */
922: /* length encoding */
923: if (root->be_type <= BER_TYPE_SINGLE_MAX) {
924: id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
925: if (root->be_encoding == BER_TYPE_SEQUENCE ||
926: root->be_encoding == BER_TYPE_SET)
927: id |= BER_TYPE_CONSTRUCTED;
928:
929: ber_putc(ber, id);
930: } else {
931: id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
932: if (root->be_encoding == BER_TYPE_SEQUENCE ||
933: root->be_encoding == BER_TYPE_SET)
934: id |= BER_TYPE_CONSTRUCTED;
935:
936: ber_putc(ber, id);
937:
938: for (t = 0, type = root->be_type; type > 0; type >>= 7)
939: buf[t++] = type & ~BER_TAG_MORE;
940:
941: while (t-- > 0) {
942: if (t > 0)
943: buf[t] |= BER_TAG_MORE;
944: ber_putc(ber, buf[t]);
945: }
946: }
947:
948: if (root->be_len < BER_TAG_MORE) {
949: /* short form */
950: ber_putc(ber, root->be_len);
951: } else {
952: for (t = 0, size = root->be_len; size > 0; size >>= 8)
953: buf[t++] = size & 0xff;
954:
955: ber_putc(ber, t | BER_TAG_MORE);
956:
957: while (t > 0)
958: ber_putc(ber, buf[--t]);
959: }
960: }
961:
962: static void
963: ber_putc(struct ber *ber, u_char c)
964: {
965: if (ber->br_wptr + 1 <= ber->br_wend)
966: *ber->br_wptr = c;
967: ber->br_wptr++;
968: }
969:
970: static void
971: ber_write(struct ber *ber, void *buf, size_t len)
972: {
973: if (ber->br_wptr + len <= ber->br_wend)
974: bcopy(buf, ber->br_wptr, len);
975: ber->br_wptr += len;
976: }
977:
978: /*
979: * extract a BER encoded tag. There are two types, a short and long form.
980: */
981: static ssize_t
982: get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
983: {
984: u_char u;
985: size_t i = 0;
986: unsigned long t = 0;
987:
988: if (ber_getc(b, &u) == -1)
989: return -1;
990:
991: *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
992: *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
993:
994: if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
995: *tag = u & BER_TAG_MASK;
996: return 1;
997: }
998:
999: do {
1000: if (ber_getc(b, &u) == -1)
1001: return -1;
1002: t = (t << 7) | (u & ~BER_TAG_MORE);
1003: i++;
1004: } while (u & BER_TAG_MORE);
1005:
1006: if (i > sizeof(unsigned long)) {
1007: errno = ERANGE;
1008: return -1;
1009: }
1010:
1011: *tag = t;
1012: return i + 1;
1013: }
1014:
1015: /*
1016: * extract length of a ber object -- if length is unknown an error is returned.
1017: */
1018: static ssize_t
1019: get_len(struct ber *b, ssize_t *len)
1020: {
1021: u_char u, n;
1022: ssize_t s, r;
1023:
1024: if (ber_getc(b, &u) == -1)
1025: return -1;
1026: if ((u & BER_TAG_MORE) == 0) {
1027: /* short form */
1028: *len = u;
1029: return 1;
1030: }
1031:
1032: n = u & ~BER_TAG_MORE;
1033: if (sizeof(ssize_t) < n) {
1034: errno = ERANGE;
1035: return -1;
1036: }
1037: r = n + 1;
1038:
1039: for (s = 0; n > 0; n--) {
1040: if (ber_getc(b, &u) == -1)
1041: return -1;
1042: s = (s << 8) | u;
1043: }
1044:
1045: if (s < 0) {
1046: /* overflow */
1047: errno = ERANGE;
1048: return -1;
1049: }
1050:
1051: if (s == 0) {
1052: /* invalid encoding */
1053: errno = EINVAL;
1054: return -1;
1055: }
1056:
1057: *len = s;
1058: return r;
1059: }
1060:
1061: static ssize_t
1062: ber_read_element(struct ber *ber, struct ber_element *elm)
1063: {
1064: long long val = 0;
1065: struct ber_element *next;
1066: unsigned long type;
1067: int i, class, cstruct;
1068: ssize_t len, r, totlen = 0;
1069: u_char c;
1070:
1071: if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1072: return -1;
1073: DPRINTF("ber read got class %d type %lu, %s\n",
1074: class, type, cstruct ? "constructive" : "primitive");
1075: totlen += r;
1076: if ((r = get_len(ber, &len)) == -1)
1077: return -1;
1078: DPRINTF("ber read element size %zd\n", len);
1079: totlen += r + len;
1080:
1081: /* If the total size of the element is larger than external
1082: * buffer don't bother to continue. */
1083: if (len > ber->br_rend - ber->br_rptr) {
1084: errno = ECANCELED;
1085: return -1;
1086: }
1087:
1088: elm->be_type = type;
1089: elm->be_len = len;
1090: elm->be_class = class;
1091:
1092: if (elm->be_encoding == 0) {
1093: /* try to figure out the encoding via class, type and cstruct */
1094: if (cstruct)
1095: elm->be_encoding = BER_TYPE_SEQUENCE;
1096: else if (class == BER_CLASS_UNIVERSAL)
1097: elm->be_encoding = type;
1098: else if (ber->br_application != NULL) {
1099: /*
1100: * Ask the application to map the encoding to a
1101: * universal type. For example, a SMI IpAddress
1102: * type is defined as 4 byte OCTET STRING.
1103: */
1104: elm->be_encoding = (*ber->br_application)(elm);
1105: } else
1106: /* last resort option */
1107: elm->be_encoding = BER_TYPE_NULL;
1108: }
1109:
1110: switch (elm->be_encoding) {
1111: case BER_TYPE_EOC: /* End-Of-Content */
1112: break;
1113: case BER_TYPE_BOOLEAN:
1114: case BER_TYPE_INTEGER:
1115: case BER_TYPE_ENUMERATED:
1116: if (len > (ssize_t)sizeof(long long))
1117: return -1;
1118: for (i = 0; i < len; i++) {
1119: if (ber_getc(ber, &c) != 1)
1120: return -1;
1121: val <<= 8;
1122: val |= c;
1123: }
1124:
1125: /* sign extend if MSB is set */
1126: if (val >> ((i - 1) * 8) & 0x80)
1127: val |= ULLONG_MAX << (i * 8);
1128: elm->be_numeric = val;
1129: break;
1130: case BER_TYPE_BITSTRING:
1131: elm->be_val = malloc(len);
1132: if (elm->be_val == NULL)
1133: return -1;
1134: elm->be_free = 1;
1135: elm->be_len = len;
1136: ber_read(ber, elm->be_val, len);
1137: break;
1138: case BER_TYPE_OCTETSTRING:
1139: case BER_TYPE_OBJECT:
1140: elm->be_val = malloc(len + 1);
1141: if (elm->be_val == NULL)
1142: return -1;
1143: elm->be_free = 1;
1144: elm->be_len = len;
1145: ber_read(ber, elm->be_val, len);
1146: ((u_char *)elm->be_val)[len] = '\0';
1147: break;
1148: case BER_TYPE_NULL: /* no payload */
1149: if (len != 0)
1150: return -1;
1151: break;
1152: case BER_TYPE_SEQUENCE:
1153: case BER_TYPE_SET:
1154: if (elm->be_sub == NULL) {
1155: if ((elm->be_sub = ber_get_element(0)) == NULL)
1156: return -1;
1157: }
1158: next = elm->be_sub;
1159: while (len > 0) {
1160: r = ber_read_element(ber, next);
1161: if (r == -1)
1162: return -1;
1163: len -= r;
1164: if (len > 0 && next->be_next == NULL) {
1165: if ((next->be_next = ber_get_element(0)) ==
1166: NULL)
1167: return -1;
1168: }
1169: next = next->be_next;
1170: }
1171: break;
1172: }
1173: return totlen;
1174: }
1175:
1176: static ssize_t
1177: ber_readbuf(struct ber *b, void *buf, size_t nbytes)
1178: {
1179: size_t sz;
1180: size_t len;
1181:
1182: if (b->br_rbuf == NULL)
1183: return -1;
1184:
1185: sz = b->br_rend - b->br_rptr;
1186: len = MINIMUM(nbytes, sz);
1187: if (len == 0) {
1188: errno = ECANCELED;
1189: return (-1); /* end of buffer and parser wants more data */
1190: }
1191:
1192: bcopy(b->br_rptr, buf, len);
1193: b->br_rptr += len;
1194:
1195: return (len);
1196: }
1197:
1198: void
1199: ber_set_readbuf(struct ber *b, void *buf, size_t len)
1200: {
1201: b->br_rbuf = b->br_rptr = buf;
1202: b->br_rend = (u_int8_t *)buf + len;
1203: }
1204:
1205: ssize_t
1206: ber_get_writebuf(struct ber *b, void **buf)
1207: {
1208: if (b->br_wbuf == NULL)
1209: return -1;
1210: *buf = b->br_wbuf;
1211: return (b->br_wend - b->br_wbuf);
1212: }
1213:
1214: void
1215: ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
1216: {
1217: b->br_application = cb;
1218: }
1219:
1220: void
1221: ber_free(struct ber *b)
1222: {
1223: free(b->br_wbuf);
1224: }
1225:
1226: static ssize_t
1227: ber_getc(struct ber *b, u_char *c)
1228: {
1229: return ber_readbuf(b, c, 1);
1230: }
1231:
1232: static ssize_t
1233: ber_read(struct ber *ber, void *buf, size_t len)
1234: {
1235: u_char *b = buf;
1236: ssize_t r, remain = len;
1237:
1238: while (remain > 0) {
1239: r = ber_readbuf(ber, b, remain);
1240: if (r == -1)
1241: return -1;
1242: if (r == 0)
1243: return (b - (u_char *)buf);
1244: b += r;
1245: remain -= r;
1246: }
1247: return (b - (u_char *)buf);
1248: }