Annotation of src/usr.bin/ldap/ber.c, Revision 1.20
1.20 ! martijn 1: /* $OpenBSD: ber.c,v 1.19 2018/08/12 22:04:09 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);
1.15 claudio 45: static ssize_t get_id(struct ber *b, unsigned int *tag, int *class,
1.1 reyk 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 *
1.15 claudio 59: ber_get_element(unsigned int encoding)
1.1 reyk 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
1.15 claudio 73: ber_set_header(struct ber_element *elm, int class, unsigned int type)
1.1 reyk 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:
1.17 rob 433: int
434: ber_oid_cmp(struct ber_oid *a, struct ber_oid *b)
435: {
436: size_t i;
437: for (i = 0; i < BER_MAX_OID_LEN; i++) {
438: if (a->bo_id[i] != 0) {
439: if (a->bo_id[i] == b->bo_id[i])
440: continue;
441: else if (a->bo_id[i] < b->bo_id[i]) {
442: /* b is a successor of a */
443: return (1);
444: } else {
445: /* b is a predecessor of a */
446: return (-1);
447: }
448: } else if (b->bo_id[i] != 0) {
449: /* b is larger, but a child of a */
450: return (2);
451: } else
452: break;
453: }
454:
455: /* b and a are identical */
456: return (0);
457: }
458:
1.1 reyk 459: struct ber_element *
460: ber_add_oid(struct ber_element *prev, struct ber_oid *o)
461: {
462: struct ber_element *elm;
463: u_int8_t *buf;
464: size_t len;
465:
466: if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
467: return (NULL);
468:
469: if ((len = ber_oid2ber(o, NULL, 0)) == 0)
470: goto fail;
471:
472: if ((buf = calloc(1, len)) == NULL)
473: goto fail;
474:
475: elm->be_val = buf;
476: elm->be_len = len;
477: elm->be_free = 1;
478:
479: if (ber_oid2ber(o, buf, len) != len)
480: goto fail;
481:
482: ber_link_elements(prev, elm);
483:
484: return (elm);
485:
486: fail:
487: ber_free_elements(elm);
488: return (NULL);
489: }
490:
491: struct ber_element *
492: ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
493: {
494: struct ber_oid no;
495:
496: if (n > BER_MAX_OID_LEN)
497: return (NULL);
498: no.bo_n = n;
499: bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
500:
501: return (ber_add_oid(prev, &no));
502: }
503:
504: struct ber_element *
505: ber_add_oidstring(struct ber_element *prev, const char *oidstr)
506: {
507: struct ber_oid o;
508:
509: if (ber_string2oid(oidstr, &o) == -1)
510: return (NULL);
511:
512: return (ber_add_oid(prev, &o));
513: }
514:
515: int
516: ber_get_oid(struct ber_element *elm, struct ber_oid *o)
517: {
518: u_int8_t *buf;
519: size_t len, i = 0, j = 0;
520:
521: if (elm->be_encoding != BER_TYPE_OBJECT)
522: return (-1);
523:
524: buf = elm->be_val;
525: len = elm->be_len;
526:
527: if (!buf[i])
528: return (-1);
529:
530: memset(o, 0, sizeof(*o));
531: o->bo_id[j++] = buf[i] / 40;
532: o->bo_id[j++] = buf[i++] % 40;
533: for (; i < len && j < BER_MAX_OID_LEN; i++) {
534: o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
535: if (buf[i] & 0x80)
536: continue;
537: j++;
538: }
539: o->bo_n = j;
540:
541: return (0);
542: }
543:
544: struct ber_element *
545: ber_printf_elements(struct ber_element *ber, char *fmt, ...)
546: {
547: va_list ap;
548: int d, class;
549: size_t len;
1.15 claudio 550: unsigned int type;
1.1 reyk 551: long long i;
552: char *s;
553: void *p;
554: struct ber_oid *o;
555: struct ber_element *sub = ber, *e;
556:
557: va_start(ap, fmt);
558: while (*fmt) {
559: switch (*fmt++) {
560: case 'B':
561: p = va_arg(ap, void *);
562: len = va_arg(ap, size_t);
563: if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
564: goto fail;
565: break;
566: case 'b':
567: d = va_arg(ap, int);
568: if ((ber = ber_add_boolean(ber, d)) == NULL)
569: goto fail;
570: break;
571: case 'd':
572: d = va_arg(ap, int);
573: if ((ber = ber_add_integer(ber, d)) == NULL)
574: goto fail;
575: break;
576: case 'e':
577: e = va_arg(ap, struct ber_element *);
578: ber_link_elements(ber, e);
579: break;
580: case 'E':
581: i = va_arg(ap, long long);
582: if ((ber = ber_add_enumerated(ber, i)) == NULL)
583: goto fail;
584: break;
585: case 'i':
586: i = va_arg(ap, long long);
587: if ((ber = ber_add_integer(ber, i)) == NULL)
588: goto fail;
589: break;
590: case 'O':
591: o = va_arg(ap, struct ber_oid *);
592: if ((ber = ber_add_oid(ber, o)) == NULL)
593: goto fail;
594: break;
595: case 'o':
596: s = va_arg(ap, char *);
597: if ((ber = ber_add_oidstring(ber, s)) == NULL)
598: goto fail;
599: break;
600: case 's':
601: s = va_arg(ap, char *);
602: if ((ber = ber_add_string(ber, s)) == NULL)
603: goto fail;
604: break;
605: case 't':
606: class = va_arg(ap, int);
1.15 claudio 607: type = va_arg(ap, unsigned int);
1.1 reyk 608: ber_set_header(ber, class, type);
609: break;
610: case 'x':
611: s = va_arg(ap, char *);
612: len = va_arg(ap, size_t);
613: if ((ber = ber_add_nstring(ber, s, len)) == NULL)
614: goto fail;
615: break;
616: case '0':
617: if ((ber = ber_add_null(ber)) == NULL)
618: goto fail;
619: break;
620: case '{':
621: if ((ber = sub = ber_add_sequence(ber)) == NULL)
622: goto fail;
623: break;
624: case '(':
625: if ((ber = sub = ber_add_set(ber)) == NULL)
626: goto fail;
627: break;
628: case '}':
629: case ')':
630: ber = sub;
631: break;
632: case '.':
633: if ((e = ber_add_eoc(ber)) == NULL)
634: goto fail;
635: ber = e;
636: break;
637: default:
638: break;
639: }
640: }
641: va_end(ap);
642:
643: return (ber);
644: fail:
645: ber_free_elements(ber);
646: return (NULL);
647: }
648:
649: int
650: ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
651: {
652: #define _MAX_SEQ 128
653: va_list ap;
654: int *d, level = -1;
1.15 claudio 655: unsigned int *t;
1.8 rob 656: long long *i, l;
1.1 reyk 657: void **ptr;
658: size_t *len, ret = 0, n = strlen(fmt);
659: char **s;
1.8 rob 660: off_t *pos;
1.1 reyk 661: struct ber_oid *o;
662: struct ber_element *parent[_MAX_SEQ], **e;
663:
664: memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
665:
666: va_start(ap, fmt);
667: while (*fmt) {
668: switch (*fmt++) {
669: case 'B':
670: ptr = va_arg(ap, void **);
671: len = va_arg(ap, size_t *);
672: if (ber_get_bitstring(ber, ptr, len) == -1)
673: goto fail;
674: ret++;
675: break;
676: case 'b':
677: d = va_arg(ap, int *);
678: if (ber_get_boolean(ber, d) == -1)
679: goto fail;
680: ret++;
681: break;
1.8 rob 682: case 'd':
683: d = va_arg(ap, int *);
684: if (ber_get_integer(ber, &l) == -1)
685: goto fail;
686: *d = l;
687: ret++;
688: break;
1.1 reyk 689: case 'e':
690: e = va_arg(ap, struct ber_element **);
691: *e = ber;
692: ret++;
693: continue;
694: case 'E':
695: i = va_arg(ap, long long *);
696: if (ber_get_enumerated(ber, i) == -1)
697: goto fail;
698: ret++;
699: break;
700: case 'i':
701: i = va_arg(ap, long long *);
702: if (ber_get_integer(ber, i) == -1)
703: goto fail;
704: ret++;
705: break;
706: case 'o':
707: o = va_arg(ap, struct ber_oid *);
708: if (ber_get_oid(ber, o) == -1)
709: goto fail;
710: ret++;
711: break;
712: case 'S':
713: ret++;
714: break;
715: case 's':
716: s = va_arg(ap, char **);
717: if (ber_get_string(ber, s) == -1)
718: goto fail;
719: ret++;
720: break;
721: case 't':
722: d = va_arg(ap, int *);
1.15 claudio 723: t = va_arg(ap, unsigned int *);
1.1 reyk 724: *d = ber->be_class;
725: *t = ber->be_type;
726: ret++;
727: continue;
728: case 'x':
729: ptr = va_arg(ap, void **);
730: len = va_arg(ap, size_t *);
731: if (ber_get_nstring(ber, ptr, len) == -1)
732: goto fail;
733: ret++;
734: break;
735: case '0':
736: if (ber->be_encoding != BER_TYPE_NULL)
737: goto fail;
738: ret++;
739: break;
740: case '.':
741: if (ber->be_encoding != BER_TYPE_EOC)
742: goto fail;
743: ret++;
744: break;
1.8 rob 745: case 'p':
746: pos = va_arg(ap, off_t *);
747: *pos = ber_getpos(ber);
748: ret++;
749: continue;
1.1 reyk 750: case '{':
751: case '(':
752: if (ber->be_encoding != BER_TYPE_SEQUENCE &&
753: ber->be_encoding != BER_TYPE_SET)
754: goto fail;
755: if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
756: goto fail;
757: parent[++level] = ber;
758: ber = ber->be_sub;
759: ret++;
760: continue;
761: case '}':
762: case ')':
763: if (parent[level] == NULL)
764: goto fail;
765: ber = parent[level--];
766: ret++;
1.5 rob 767: break;
1.1 reyk 768: default:
769: goto fail;
770: }
771:
772: if (ber->be_next == NULL)
773: continue;
774: ber = ber->be_next;
775: }
776: va_end(ap);
777: return (ret == n ? 0 : -1);
778:
779: fail:
780: va_end(ap);
781: return (-1);
782:
783: }
784:
1.17 rob 785: ssize_t
786: ber_get_writebuf(struct ber *b, void **buf)
787: {
788: if (b->br_wbuf == NULL)
789: return -1;
790: *buf = b->br_wbuf;
791: return (b->br_wend - b->br_wbuf);
792: }
793:
1.1 reyk 794: /*
1.14 rob 795: * write ber elements to the write buffer
1.1 reyk 796: *
797: * params:
1.14 rob 798: * ber holds the destination write buffer byte stream
1.1 reyk 799: * root fully populated element tree
800: *
801: * returns:
1.10 rob 802: * >=0 number of bytes written
1.1 reyk 803: * -1 on failure and sets errno
804: */
1.19 rob 805: ssize_t
1.1 reyk 806: ber_write_elements(struct ber *ber, struct ber_element *root)
807: {
808: size_t len;
809:
810: /* calculate length because only the definite form is required */
811: len = ber_calc_len(root);
812: DPRINTF("write ber element of %zd bytes length\n", len);
813:
814: if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
815: free(ber->br_wbuf);
816: ber->br_wbuf = NULL;
817: }
818: if (ber->br_wbuf == NULL) {
819: if ((ber->br_wbuf = malloc(len)) == NULL)
820: return -1;
821: ber->br_wend = ber->br_wbuf + len;
822: }
823:
824: /* reset write pointer */
825: ber->br_wptr = ber->br_wbuf;
826:
827: if (ber_dump_element(ber, root) == -1)
828: return -1;
829:
830: return (len);
831: }
832:
1.17 rob 833: void
834: ber_set_readbuf(struct ber *b, void *buf, size_t len)
835: {
836: b->br_rbuf = b->br_rptr = buf;
837: b->br_rend = (u_int8_t *)buf + len;
838: }
839:
1.1 reyk 840: /*
1.14 rob 841: * read ber elements from the read buffer
1.1 reyk 842: *
843: * params:
1.14 rob 844: * ber holds a fully populated read buffer byte stream
1.1 reyk 845: * root if NULL, build up an element tree from what we receive on
846: * the wire. If not null, use the specified encoding for the
847: * elements received.
848: *
849: * returns:
850: * !=NULL, elements read and store in the ber_element tree
851: * NULL, type mismatch or read error
852: */
853: struct ber_element *
854: ber_read_elements(struct ber *ber, struct ber_element *elm)
855: {
856: struct ber_element *root = elm;
857:
858: if (root == NULL) {
859: if ((root = ber_get_element(0)) == NULL)
860: return NULL;
861: }
862:
863: DPRINTF("read ber elements, root %p\n", root);
864:
865: if (ber_read_element(ber, root) == -1) {
866: /* Cleanup if root was allocated by us */
867: if (elm == NULL)
868: ber_free_elements(root);
869: return NULL;
870: }
871:
872: return root;
873: }
874:
1.8 rob 875: off_t
876: ber_getpos(struct ber_element *elm)
877: {
878: return elm->be_offs;
879: }
880:
1.1 reyk 881: void
1.5 rob 882: ber_free_element(struct ber_element *root)
883: {
884: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
885: root->be_encoding == BER_TYPE_SET))
886: ber_free_elements(root->be_sub);
887: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
888: root->be_encoding == BER_TYPE_BITSTRING ||
889: root->be_encoding == BER_TYPE_OBJECT))
890: free(root->be_val);
891: free(root);
892: }
893:
894: void
1.1 reyk 895: ber_free_elements(struct ber_element *root)
896: {
1.20 ! martijn 897: if (root == NULL)
! 898: return;
1.1 reyk 899: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
900: root->be_encoding == BER_TYPE_SET))
901: ber_free_elements(root->be_sub);
902: if (root->be_next)
903: ber_free_elements(root->be_next);
904: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
905: root->be_encoding == BER_TYPE_BITSTRING ||
906: root->be_encoding == BER_TYPE_OBJECT))
907: free(root->be_val);
908: free(root);
909: }
910:
911: size_t
912: ber_calc_len(struct ber_element *root)
913: {
1.15 claudio 914: unsigned int t;
1.1 reyk 915: size_t s;
916: size_t size = 2; /* minimum 1 byte head and 1 byte size */
917:
918: /* calculate the real length of a sequence or set */
919: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
920: root->be_encoding == BER_TYPE_SET))
921: root->be_len = ber_calc_len(root->be_sub);
922:
923: /* fix header length for extended types */
924: if (root->be_type > BER_TYPE_SINGLE_MAX)
925: for (t = root->be_type; t > 0; t >>= 7)
926: size++;
927: if (root->be_len >= BER_TAG_MORE)
928: for (s = root->be_len; s > 0; s >>= 8)
929: size++;
930:
931: /* calculate the length of the following elements */
932: if (root->be_next)
933: size += ber_calc_len(root->be_next);
934:
935: /* This is an empty element, do not use a minimal size */
1.2 rob 936: if (root->be_class == BER_CLASS_UNIVERSAL &&
937: root->be_type == BER_TYPE_EOC && root->be_len == 0)
1.1 reyk 938: return (0);
939:
940: return (root->be_len + size);
941: }
942:
1.17 rob 943: void
944: ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
945: {
946: b->br_application = cb;
947: }
948:
949: void
950: ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
951: void *arg)
952: {
953: elm->be_cb = cb;
954: elm->be_cbarg = arg;
955: }
956:
957: void
958: ber_free(struct ber *b)
959: {
960: free(b->br_wbuf);
961: }
962:
1.1 reyk 963: /*
964: * internal functions
965: */
966:
967: static int
968: ber_dump_element(struct ber *ber, struct ber_element *root)
969: {
970: unsigned long long l;
971: int i;
972: uint8_t u;
973:
974: ber_dump_header(ber, root);
1.8 rob 975: if (root->be_cb)
976: root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1.1 reyk 977:
978: switch (root->be_encoding) {
979: case BER_TYPE_BOOLEAN:
980: case BER_TYPE_INTEGER:
981: case BER_TYPE_ENUMERATED:
982: l = (unsigned long long)root->be_numeric;
983: for (i = root->be_len; i > 0; i--) {
984: u = (l >> ((i - 1) * 8)) & 0xff;
985: ber_putc(ber, u);
986: }
987: break;
988: case BER_TYPE_BITSTRING:
989: return -1;
990: case BER_TYPE_OCTETSTRING:
991: case BER_TYPE_OBJECT:
992: ber_write(ber, root->be_val, root->be_len);
993: break;
994: case BER_TYPE_NULL: /* no payload */
995: case BER_TYPE_EOC:
996: break;
997: case BER_TYPE_SEQUENCE:
998: case BER_TYPE_SET:
999: if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
1000: return -1;
1001: break;
1002: }
1003:
1004: if (root->be_next == NULL)
1005: return 0;
1006: return ber_dump_element(ber, root->be_next);
1007: }
1008:
1009: static void
1010: ber_dump_header(struct ber *ber, struct ber_element *root)
1011: {
1.15 claudio 1012: u_char id = 0, t, buf[5];
1013: unsigned int type;
1.1 reyk 1014: size_t size;
1015:
1016: /* class universal, type encoding depending on type value */
1017: /* length encoding */
1018: if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1019: id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1020: if (root->be_encoding == BER_TYPE_SEQUENCE ||
1021: root->be_encoding == BER_TYPE_SET)
1022: id |= BER_TYPE_CONSTRUCTED;
1023:
1024: ber_putc(ber, id);
1025: } else {
1026: id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1027: if (root->be_encoding == BER_TYPE_SEQUENCE ||
1028: root->be_encoding == BER_TYPE_SET)
1029: id |= BER_TYPE_CONSTRUCTED;
1030:
1031: ber_putc(ber, id);
1032:
1033: for (t = 0, type = root->be_type; type > 0; type >>= 7)
1034: buf[t++] = type & ~BER_TAG_MORE;
1035:
1036: while (t-- > 0) {
1037: if (t > 0)
1038: buf[t] |= BER_TAG_MORE;
1039: ber_putc(ber, buf[t]);
1040: }
1041: }
1042:
1043: if (root->be_len < BER_TAG_MORE) {
1044: /* short form */
1045: ber_putc(ber, root->be_len);
1046: } else {
1047: for (t = 0, size = root->be_len; size > 0; size >>= 8)
1048: buf[t++] = size & 0xff;
1049:
1050: ber_putc(ber, t | BER_TAG_MORE);
1051:
1052: while (t > 0)
1053: ber_putc(ber, buf[--t]);
1054: }
1055: }
1056:
1057: static void
1058: ber_putc(struct ber *ber, u_char c)
1059: {
1060: if (ber->br_wptr + 1 <= ber->br_wend)
1061: *ber->br_wptr = c;
1062: ber->br_wptr++;
1063: }
1064:
1065: static void
1066: ber_write(struct ber *ber, void *buf, size_t len)
1067: {
1068: if (ber->br_wptr + len <= ber->br_wend)
1069: bcopy(buf, ber->br_wptr, len);
1070: ber->br_wptr += len;
1071: }
1072:
1073: /*
1074: * extract a BER encoded tag. There are two types, a short and long form.
1075: */
1076: static ssize_t
1.15 claudio 1077: get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1.1 reyk 1078: {
1079: u_char u;
1080: size_t i = 0;
1.15 claudio 1081: unsigned int t = 0;
1.1 reyk 1082:
1083: if (ber_getc(b, &u) == -1)
1084: return -1;
1085:
1086: *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1087: *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1088:
1089: if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1090: *tag = u & BER_TAG_MASK;
1091: return 1;
1092: }
1093:
1094: do {
1095: if (ber_getc(b, &u) == -1)
1096: return -1;
1097: t = (t << 7) | (u & ~BER_TAG_MORE);
1098: i++;
1.15 claudio 1099: if (i > sizeof(unsigned int)) {
1.13 rob 1100: errno = ERANGE;
1101: return -1;
1102: }
1.1 reyk 1103: } while (u & BER_TAG_MORE);
1104:
1105: *tag = t;
1106: return i + 1;
1107: }
1108:
1109: /*
1110: * extract length of a ber object -- if length is unknown an error is returned.
1111: */
1112: static ssize_t
1113: get_len(struct ber *b, ssize_t *len)
1114: {
1115: u_char u, n;
1116: ssize_t s, r;
1117:
1118: if (ber_getc(b, &u) == -1)
1119: return -1;
1120: if ((u & BER_TAG_MORE) == 0) {
1121: /* short form */
1122: *len = u;
1123: return 1;
1124: }
1125:
1.5 rob 1126: if (u == 0x80) {
1127: /* Indefinite length not supported. */
1128: errno = EINVAL;
1129: return -1;
1130: }
1131:
1.1 reyk 1132: n = u & ~BER_TAG_MORE;
1133: if (sizeof(ssize_t) < n) {
1134: errno = ERANGE;
1135: return -1;
1136: }
1137: r = n + 1;
1138:
1139: for (s = 0; n > 0; n--) {
1140: if (ber_getc(b, &u) == -1)
1141: return -1;
1142: s = (s << 8) | u;
1143: }
1144:
1145: if (s < 0) {
1146: /* overflow */
1147: errno = ERANGE;
1148: return -1;
1149: }
1150:
1151: *len = s;
1152: return r;
1153: }
1154:
1155: static ssize_t
1156: ber_read_element(struct ber *ber, struct ber_element *elm)
1157: {
1158: long long val = 0;
1159: struct ber_element *next;
1.15 claudio 1160: unsigned int type;
1.18 rob 1161: int i, class, cstruct, elements = 0;
1.1 reyk 1162: ssize_t len, r, totlen = 0;
1163: u_char c;
1164:
1165: if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1166: return -1;
1.16 rob 1167: DPRINTF("ber read got class %d type %u, %s\n",
1.7 rob 1168: class, type, cstruct ? "constructed" : "primitive");
1.1 reyk 1169: totlen += r;
1170: if ((r = get_len(ber, &len)) == -1)
1171: return -1;
1172: DPRINTF("ber read element size %zd\n", len);
1173: totlen += r + len;
1174:
1.4 rob 1175: /* If the total size of the element is larger than the buffer
1176: * don't bother to continue. */
1.1 reyk 1177: if (len > ber->br_rend - ber->br_rptr) {
1178: errno = ECANCELED;
1179: return -1;
1180: }
1181:
1182: elm->be_type = type;
1183: elm->be_len = len;
1.8 rob 1184: elm->be_offs = ber->br_offs; /* element position within stream */
1.1 reyk 1185: elm->be_class = class;
1186:
1187: if (elm->be_encoding == 0) {
1188: /* try to figure out the encoding via class, type and cstruct */
1189: if (cstruct)
1190: elm->be_encoding = BER_TYPE_SEQUENCE;
1191: else if (class == BER_CLASS_UNIVERSAL)
1192: elm->be_encoding = type;
1193: else if (ber->br_application != NULL) {
1194: /*
1195: * Ask the application to map the encoding to a
1196: * universal type. For example, a SMI IpAddress
1197: * type is defined as 4 byte OCTET STRING.
1198: */
1199: elm->be_encoding = (*ber->br_application)(elm);
1200: } else
1201: /* last resort option */
1202: elm->be_encoding = BER_TYPE_NULL;
1203: }
1204:
1205: switch (elm->be_encoding) {
1206: case BER_TYPE_EOC: /* End-Of-Content */
1207: break;
1208: case BER_TYPE_BOOLEAN:
1209: case BER_TYPE_INTEGER:
1210: case BER_TYPE_ENUMERATED:
1211: if (len > (ssize_t)sizeof(long long))
1212: return -1;
1213: for (i = 0; i < len; i++) {
1214: if (ber_getc(ber, &c) != 1)
1215: return -1;
1216: val <<= 8;
1217: val |= c;
1218: }
1219:
1220: /* sign extend if MSB is set */
1221: if (val >> ((i - 1) * 8) & 0x80)
1222: val |= ULLONG_MAX << (i * 8);
1223: elm->be_numeric = val;
1224: break;
1225: case BER_TYPE_BITSTRING:
1226: elm->be_val = malloc(len);
1227: if (elm->be_val == NULL)
1228: return -1;
1229: elm->be_free = 1;
1230: elm->be_len = len;
1231: ber_read(ber, elm->be_val, len);
1232: break;
1233: case BER_TYPE_OCTETSTRING:
1234: case BER_TYPE_OBJECT:
1235: elm->be_val = malloc(len + 1);
1236: if (elm->be_val == NULL)
1237: return -1;
1238: elm->be_free = 1;
1239: elm->be_len = len;
1240: ber_read(ber, elm->be_val, len);
1241: ((u_char *)elm->be_val)[len] = '\0';
1242: break;
1243: case BER_TYPE_NULL: /* no payload */
1244: if (len != 0)
1245: return -1;
1246: break;
1247: case BER_TYPE_SEQUENCE:
1248: case BER_TYPE_SET:
1249: if (elm->be_sub == NULL) {
1250: if ((elm->be_sub = ber_get_element(0)) == NULL)
1251: return -1;
1252: }
1253: next = elm->be_sub;
1254: while (len > 0) {
1.18 rob 1255: /*
1256: * Prevent stack overflow from excessive recursion
1257: * depth in ber_free_elements().
1258: */
1259: if (elements >= BER_MAX_SEQ_ELEMENTS) {
1260: errno = ERANGE;
1261: return -1;
1262: }
1.1 reyk 1263: r = ber_read_element(ber, next);
1264: if (r == -1)
1265: return -1;
1.18 rob 1266: elements++;
1.1 reyk 1267: len -= r;
1268: if (len > 0 && next->be_next == NULL) {
1269: if ((next->be_next = ber_get_element(0)) ==
1270: NULL)
1271: return -1;
1272: }
1273: next = next->be_next;
1274: }
1275: break;
1276: }
1277: return totlen;
1278: }
1279:
1280: static ssize_t
1281: ber_getc(struct ber *b, u_char *c)
1282: {
1.12 jca 1283: return ber_read(b, c, 1);
1.1 reyk 1284: }
1285:
1286: static ssize_t
1287: ber_read(struct ber *ber, void *buf, size_t len)
1288: {
1.12 jca 1289: size_t sz;
1290:
1291: if (ber->br_rbuf == NULL)
1292: return -1;
1.1 reyk 1293:
1.12 jca 1294: sz = ber->br_rend - ber->br_rptr;
1295: if (len > sz) {
1296: errno = ECANCELED;
1297: return -1; /* parser wants more data than available */
1.1 reyk 1298: }
1.12 jca 1299:
1300: bcopy(ber->br_rptr, buf, len);
1301: ber->br_rptr += len;
1302: ber->br_offs += len;
1303:
1304: return len;
1.1 reyk 1305: }