Annotation of src/usr.bin/ldap/ber.c, Revision 1.18
1.18 ! rob 1: /* $OpenBSD: ber.c,v 1.17 2018/07/31 19:38: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: */
805: int
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: {
897: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
898: root->be_encoding == BER_TYPE_SET))
899: ber_free_elements(root->be_sub);
900: if (root->be_next)
901: ber_free_elements(root->be_next);
902: if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
903: root->be_encoding == BER_TYPE_BITSTRING ||
904: root->be_encoding == BER_TYPE_OBJECT))
905: free(root->be_val);
906: free(root);
907: }
908:
909: size_t
910: ber_calc_len(struct ber_element *root)
911: {
1.15 claudio 912: unsigned int t;
1.1 reyk 913: size_t s;
914: size_t size = 2; /* minimum 1 byte head and 1 byte size */
915:
916: /* calculate the real length of a sequence or set */
917: if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
918: root->be_encoding == BER_TYPE_SET))
919: root->be_len = ber_calc_len(root->be_sub);
920:
921: /* fix header length for extended types */
922: if (root->be_type > BER_TYPE_SINGLE_MAX)
923: for (t = root->be_type; t > 0; t >>= 7)
924: size++;
925: if (root->be_len >= BER_TAG_MORE)
926: for (s = root->be_len; s > 0; s >>= 8)
927: size++;
928:
929: /* calculate the length of the following elements */
930: if (root->be_next)
931: size += ber_calc_len(root->be_next);
932:
933: /* This is an empty element, do not use a minimal size */
1.2 rob 934: if (root->be_class == BER_CLASS_UNIVERSAL &&
935: root->be_type == BER_TYPE_EOC && root->be_len == 0)
1.1 reyk 936: return (0);
937:
938: return (root->be_len + size);
939: }
940:
1.17 rob 941: void
942: ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
943: {
944: b->br_application = cb;
945: }
946:
947: void
948: ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
949: void *arg)
950: {
951: elm->be_cb = cb;
952: elm->be_cbarg = arg;
953: }
954:
955: void
956: ber_free(struct ber *b)
957: {
958: free(b->br_wbuf);
959: }
960:
1.1 reyk 961: /*
962: * internal functions
963: */
964:
965: static int
966: ber_dump_element(struct ber *ber, struct ber_element *root)
967: {
968: unsigned long long l;
969: int i;
970: uint8_t u;
971:
972: ber_dump_header(ber, root);
1.8 rob 973: if (root->be_cb)
974: root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1.1 reyk 975:
976: switch (root->be_encoding) {
977: case BER_TYPE_BOOLEAN:
978: case BER_TYPE_INTEGER:
979: case BER_TYPE_ENUMERATED:
980: l = (unsigned long long)root->be_numeric;
981: for (i = root->be_len; i > 0; i--) {
982: u = (l >> ((i - 1) * 8)) & 0xff;
983: ber_putc(ber, u);
984: }
985: break;
986: case BER_TYPE_BITSTRING:
987: return -1;
988: case BER_TYPE_OCTETSTRING:
989: case BER_TYPE_OBJECT:
990: ber_write(ber, root->be_val, root->be_len);
991: break;
992: case BER_TYPE_NULL: /* no payload */
993: case BER_TYPE_EOC:
994: break;
995: case BER_TYPE_SEQUENCE:
996: case BER_TYPE_SET:
997: if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
998: return -1;
999: break;
1000: }
1001:
1002: if (root->be_next == NULL)
1003: return 0;
1004: return ber_dump_element(ber, root->be_next);
1005: }
1006:
1007: static void
1008: ber_dump_header(struct ber *ber, struct ber_element *root)
1009: {
1.15 claudio 1010: u_char id = 0, t, buf[5];
1011: unsigned int type;
1.1 reyk 1012: size_t size;
1013:
1014: /* class universal, type encoding depending on type value */
1015: /* length encoding */
1016: if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1017: id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1018: if (root->be_encoding == BER_TYPE_SEQUENCE ||
1019: root->be_encoding == BER_TYPE_SET)
1020: id |= BER_TYPE_CONSTRUCTED;
1021:
1022: ber_putc(ber, id);
1023: } else {
1024: id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1025: if (root->be_encoding == BER_TYPE_SEQUENCE ||
1026: root->be_encoding == BER_TYPE_SET)
1027: id |= BER_TYPE_CONSTRUCTED;
1028:
1029: ber_putc(ber, id);
1030:
1031: for (t = 0, type = root->be_type; type > 0; type >>= 7)
1032: buf[t++] = type & ~BER_TAG_MORE;
1033:
1034: while (t-- > 0) {
1035: if (t > 0)
1036: buf[t] |= BER_TAG_MORE;
1037: ber_putc(ber, buf[t]);
1038: }
1039: }
1040:
1041: if (root->be_len < BER_TAG_MORE) {
1042: /* short form */
1043: ber_putc(ber, root->be_len);
1044: } else {
1045: for (t = 0, size = root->be_len; size > 0; size >>= 8)
1046: buf[t++] = size & 0xff;
1047:
1048: ber_putc(ber, t | BER_TAG_MORE);
1049:
1050: while (t > 0)
1051: ber_putc(ber, buf[--t]);
1052: }
1053: }
1054:
1055: static void
1056: ber_putc(struct ber *ber, u_char c)
1057: {
1058: if (ber->br_wptr + 1 <= ber->br_wend)
1059: *ber->br_wptr = c;
1060: ber->br_wptr++;
1061: }
1062:
1063: static void
1064: ber_write(struct ber *ber, void *buf, size_t len)
1065: {
1066: if (ber->br_wptr + len <= ber->br_wend)
1067: bcopy(buf, ber->br_wptr, len);
1068: ber->br_wptr += len;
1069: }
1070:
1071: /*
1072: * extract a BER encoded tag. There are two types, a short and long form.
1073: */
1074: static ssize_t
1.15 claudio 1075: get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1.1 reyk 1076: {
1077: u_char u;
1078: size_t i = 0;
1.15 claudio 1079: unsigned int t = 0;
1.1 reyk 1080:
1081: if (ber_getc(b, &u) == -1)
1082: return -1;
1083:
1084: *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1085: *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1086:
1087: if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1088: *tag = u & BER_TAG_MASK;
1089: return 1;
1090: }
1091:
1092: do {
1093: if (ber_getc(b, &u) == -1)
1094: return -1;
1095: t = (t << 7) | (u & ~BER_TAG_MORE);
1096: i++;
1.15 claudio 1097: if (i > sizeof(unsigned int)) {
1.13 rob 1098: errno = ERANGE;
1099: return -1;
1100: }
1.1 reyk 1101: } while (u & BER_TAG_MORE);
1102:
1103: *tag = t;
1104: return i + 1;
1105: }
1106:
1107: /*
1108: * extract length of a ber object -- if length is unknown an error is returned.
1109: */
1110: static ssize_t
1111: get_len(struct ber *b, ssize_t *len)
1112: {
1113: u_char u, n;
1114: ssize_t s, r;
1115:
1116: if (ber_getc(b, &u) == -1)
1117: return -1;
1118: if ((u & BER_TAG_MORE) == 0) {
1119: /* short form */
1120: *len = u;
1121: return 1;
1122: }
1123:
1.5 rob 1124: if (u == 0x80) {
1125: /* Indefinite length not supported. */
1126: errno = EINVAL;
1127: return -1;
1128: }
1129:
1.1 reyk 1130: n = u & ~BER_TAG_MORE;
1131: if (sizeof(ssize_t) < n) {
1132: errno = ERANGE;
1133: return -1;
1134: }
1135: r = n + 1;
1136:
1137: for (s = 0; n > 0; n--) {
1138: if (ber_getc(b, &u) == -1)
1139: return -1;
1140: s = (s << 8) | u;
1141: }
1142:
1143: if (s < 0) {
1144: /* overflow */
1145: errno = ERANGE;
1146: return -1;
1147: }
1148:
1149: *len = s;
1150: return r;
1151: }
1152:
1153: static ssize_t
1154: ber_read_element(struct ber *ber, struct ber_element *elm)
1155: {
1156: long long val = 0;
1157: struct ber_element *next;
1.15 claudio 1158: unsigned int type;
1.18 ! rob 1159: int i, class, cstruct, elements = 0;
1.1 reyk 1160: ssize_t len, r, totlen = 0;
1161: u_char c;
1162:
1163: if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1164: return -1;
1.16 rob 1165: DPRINTF("ber read got class %d type %u, %s\n",
1.7 rob 1166: class, type, cstruct ? "constructed" : "primitive");
1.1 reyk 1167: totlen += r;
1168: if ((r = get_len(ber, &len)) == -1)
1169: return -1;
1170: DPRINTF("ber read element size %zd\n", len);
1171: totlen += r + len;
1172:
1.4 rob 1173: /* If the total size of the element is larger than the buffer
1174: * don't bother to continue. */
1.1 reyk 1175: if (len > ber->br_rend - ber->br_rptr) {
1176: errno = ECANCELED;
1177: return -1;
1178: }
1179:
1180: elm->be_type = type;
1181: elm->be_len = len;
1.8 rob 1182: elm->be_offs = ber->br_offs; /* element position within stream */
1.1 reyk 1183: elm->be_class = class;
1184:
1185: if (elm->be_encoding == 0) {
1186: /* try to figure out the encoding via class, type and cstruct */
1187: if (cstruct)
1188: elm->be_encoding = BER_TYPE_SEQUENCE;
1189: else if (class == BER_CLASS_UNIVERSAL)
1190: elm->be_encoding = type;
1191: else if (ber->br_application != NULL) {
1192: /*
1193: * Ask the application to map the encoding to a
1194: * universal type. For example, a SMI IpAddress
1195: * type is defined as 4 byte OCTET STRING.
1196: */
1197: elm->be_encoding = (*ber->br_application)(elm);
1198: } else
1199: /* last resort option */
1200: elm->be_encoding = BER_TYPE_NULL;
1201: }
1202:
1203: switch (elm->be_encoding) {
1204: case BER_TYPE_EOC: /* End-Of-Content */
1205: break;
1206: case BER_TYPE_BOOLEAN:
1207: case BER_TYPE_INTEGER:
1208: case BER_TYPE_ENUMERATED:
1209: if (len > (ssize_t)sizeof(long long))
1210: return -1;
1211: for (i = 0; i < len; i++) {
1212: if (ber_getc(ber, &c) != 1)
1213: return -1;
1214: val <<= 8;
1215: val |= c;
1216: }
1217:
1218: /* sign extend if MSB is set */
1219: if (val >> ((i - 1) * 8) & 0x80)
1220: val |= ULLONG_MAX << (i * 8);
1221: elm->be_numeric = val;
1222: break;
1223: case BER_TYPE_BITSTRING:
1224: elm->be_val = malloc(len);
1225: if (elm->be_val == NULL)
1226: return -1;
1227: elm->be_free = 1;
1228: elm->be_len = len;
1229: ber_read(ber, elm->be_val, len);
1230: break;
1231: case BER_TYPE_OCTETSTRING:
1232: case BER_TYPE_OBJECT:
1233: elm->be_val = malloc(len + 1);
1234: if (elm->be_val == NULL)
1235: return -1;
1236: elm->be_free = 1;
1237: elm->be_len = len;
1238: ber_read(ber, elm->be_val, len);
1239: ((u_char *)elm->be_val)[len] = '\0';
1240: break;
1241: case BER_TYPE_NULL: /* no payload */
1242: if (len != 0)
1243: return -1;
1244: break;
1245: case BER_TYPE_SEQUENCE:
1246: case BER_TYPE_SET:
1247: if (elm->be_sub == NULL) {
1248: if ((elm->be_sub = ber_get_element(0)) == NULL)
1249: return -1;
1250: }
1251: next = elm->be_sub;
1252: while (len > 0) {
1.18 ! rob 1253: /*
! 1254: * Prevent stack overflow from excessive recursion
! 1255: * depth in ber_free_elements().
! 1256: */
! 1257: if (elements >= BER_MAX_SEQ_ELEMENTS) {
! 1258: errno = ERANGE;
! 1259: return -1;
! 1260: }
1.1 reyk 1261: r = ber_read_element(ber, next);
1262: if (r == -1)
1263: return -1;
1.18 ! rob 1264: elements++;
1.1 reyk 1265: len -= r;
1266: if (len > 0 && next->be_next == NULL) {
1267: if ((next->be_next = ber_get_element(0)) ==
1268: NULL)
1269: return -1;
1270: }
1271: next = next->be_next;
1272: }
1273: break;
1274: }
1275: return totlen;
1276: }
1277:
1278: static ssize_t
1279: ber_getc(struct ber *b, u_char *c)
1280: {
1.12 jca 1281: return ber_read(b, c, 1);
1.1 reyk 1282: }
1283:
1284: static ssize_t
1285: ber_read(struct ber *ber, void *buf, size_t len)
1286: {
1.12 jca 1287: size_t sz;
1288:
1289: if (ber->br_rbuf == NULL)
1290: return -1;
1.1 reyk 1291:
1.12 jca 1292: sz = ber->br_rend - ber->br_rptr;
1293: if (len > sz) {
1294: errno = ECANCELED;
1295: return -1; /* parser wants more data than available */
1.1 reyk 1296: }
1.12 jca 1297:
1298: bcopy(ber->br_rptr, buf, len);
1299: ber->br_rptr += len;
1300: ber->br_offs += len;
1301:
1302: return len;
1.1 reyk 1303: }