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