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