xref: /openbsd/lib/libutil/ber.c (revision 55cc5ba3)
1 /*	$OpenBSD: ber.c,v 1.20 2021/01/28 19:56:33 martijn Exp $ */
2 
3 /*
4  * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
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	ober_dump_element(struct ber *ber, struct ber_element *root);
42 static void	ober_dump_header(struct ber *ber, struct ber_element *root);
43 static void	ober_putc(struct ber *ber, u_char c);
44 static void	ober_write(struct ber *ber, void *buf, size_t len);
45 static ssize_t	get_id(struct ber *b, unsigned int *tag, int *class,
46     int *cstruct);
47 static ssize_t	get_len(struct ber *b, ssize_t *len);
48 static ssize_t	ober_read_element(struct ber *ber, struct ber_element *elm);
49 static ssize_t	ober_getc(struct ber *b, u_char *c);
50 static ssize_t	ober_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 *
59 ober_get_element(unsigned int encoding)
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 	ober_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
68 
69 	return elm;
70 }
71 
72 void
73 ober_set_header(struct ber_element *elm, int class, unsigned int type)
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 ober_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 ober_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 ober_replace_elements(struct ber_element *prev, struct ber_element *new)
114 {
115 	struct ber_element *ber, *next;
116 
117 	ber = ober_unlink_elements(prev);
118 	next = ober_unlink_elements(ber);
119 	ober_link_elements(new, next);
120 	ober_link_elements(prev, new);
121 
122 	/* cleanup old element */
123 	ober_free_elements(ber);
124 }
125 
126 struct ber_element *
127 ober_add_sequence(struct ber_element *prev)
128 {
129 	struct ber_element *elm;
130 
131 	if ((elm = ober_get_element(BER_TYPE_SEQUENCE)) == NULL)
132 		return NULL;
133 
134 	ober_link_elements(prev, elm);
135 
136 	return elm;
137 }
138 
139 struct ber_element *
140 ober_add_set(struct ber_element *prev)
141 {
142 	struct ber_element *elm;
143 
144 	if ((elm = ober_get_element(BER_TYPE_SET)) == NULL)
145 		return NULL;
146 
147 	ober_link_elements(prev, elm);
148 
149 	return elm;
150 }
151 
152 struct ber_element *
153 ober_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 = ober_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 	ober_link_elements(prev, elm);
177 
178 	return elm;
179 }
180 
181 struct ber_element *
182 ober_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 = ober_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 	ober_link_elements(prev, elm);
206 
207 	return elm;
208 }
209 
210 int
211 ober_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 ober_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 ober_add_boolean(struct ber_element *prev, int bool)
232 {
233 	struct ber_element *elm;
234 
235 	if ((elm = ober_get_element(BER_TYPE_BOOLEAN)) == NULL)
236 		return NULL;
237 
238 	elm->be_numeric = bool ? 0xff : 0;
239 	elm->be_len = 1;
240 
241 	ober_link_elements(prev, elm);
242 
243 	return elm;
244 }
245 
246 int
247 ober_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 ober_add_string(struct ber_element *prev, const char *string)
258 {
259 	return ober_add_nstring(prev, string, strlen(string));
260 }
261 
262 struct ber_element *
263 ober_add_nstring(struct ber_element *prev, const char *string0, size_t len)
264 {
265 	struct ber_element *elm;
266 	char *string;
267 
268 	if ((string = calloc(1, len + 1)) == NULL)
269 		return NULL;
270 	if ((elm = ober_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 	ober_link_elements(prev, elm);
281 
282 	return elm;
283 }
284 
285 struct ber_element *
286 ober_add_ostring(struct ber_element *prev, struct ber_octetstring *s)
287 {
288 	return ober_add_nstring(prev, s->ostr_val, s->ostr_len);
289 }
290 
291 int
292 ober_get_string(struct ber_element *elm, char **s)
293 {
294 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
295 		return -1;
296 	/* XXX some components use getstring on binary data containing \0 */
297 #if 0
298 	if (memchr(elm->be_val, '\0', elm->be_len) != NULL)
299 		return -1;
300 #endif
301 
302 	*s = elm->be_val;
303 	return 0;
304 }
305 
306 int
307 ober_get_nstring(struct ber_element *elm, void **p, size_t *len)
308 {
309 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
310 		return -1;
311 
312 	*p = elm->be_val;
313 	*len = elm->be_len;
314 	return 0;
315 }
316 
317 int
318 ober_get_ostring(struct ber_element *elm, struct ber_octetstring *s)
319 {
320 	if (elm->be_encoding != BER_TYPE_OCTETSTRING)
321 		return -1;
322 
323 	s->ostr_val = elm->be_val;
324 	s->ostr_len = elm->be_len;
325 	return 0;
326 }
327 
328 struct ber_element *
329 ober_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
330 {
331 	struct ber_element *elm;
332 	void *v;
333 
334 	if ((v = calloc(1, len)) == NULL)
335 		return NULL;
336 	if ((elm = ober_get_element(BER_TYPE_BITSTRING)) == NULL) {
337 		free(v);
338 		return NULL;
339 	}
340 
341 	bcopy(v0, v, len);
342 	elm->be_val = v;
343 	elm->be_len = len;
344 	elm->be_free = 1;		/* free string on cleanup */
345 
346 	ober_link_elements(prev, elm);
347 
348 	return elm;
349 }
350 
351 int
352 ober_get_bitstring(struct ber_element *elm, void **v, size_t *len)
353 {
354 	if (elm->be_encoding != BER_TYPE_BITSTRING)
355 		return -1;
356 
357 	*v = elm->be_val;
358 	*len = elm->be_len;
359 	return 0;
360 }
361 
362 struct ber_element *
363 ober_add_null(struct ber_element *prev)
364 {
365 	struct ber_element *elm;
366 
367 	if ((elm = ober_get_element(BER_TYPE_NULL)) == NULL)
368 		return NULL;
369 
370 	ober_link_elements(prev, elm);
371 
372 	return elm;
373 }
374 
375 int
376 ober_get_null(struct ber_element *elm)
377 {
378 	if (elm->be_encoding != BER_TYPE_NULL)
379 		return -1;
380 
381 	return 0;
382 }
383 
384 struct ber_element *
385 ober_add_eoc(struct ber_element *prev)
386 {
387 	struct ber_element *elm;
388 
389 	if ((elm = ober_get_element(BER_TYPE_EOC)) == NULL)
390 		return NULL;
391 
392 	ober_link_elements(prev, elm);
393 
394 	return elm;
395 }
396 
397 int
398 ober_get_eoc(struct ber_element *elm)
399 {
400 	if (elm->be_encoding != BER_TYPE_EOC)
401 		return -1;
402 
403 	return 0;
404 }
405 
406 size_t
407 ober_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
408 {
409 	u_int32_t	 v;
410 	u_int		 i, j = 0, k;
411 
412 	if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
413 	    o->bo_id[0] > 2 || o->bo_id[1] > 40)
414 		return (0);
415 
416 	v = (o->bo_id[0] * 40) + o->bo_id[1];
417 	for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
418 		for (k = 28; k >= 7; k -= 7) {
419 			if (v >= (u_int)(1 << k)) {
420 				if (len)
421 					buf[j] = v >> k | BER_TAG_MORE;
422 				j++;
423 			}
424 		}
425 		if (len)
426 			buf[j] = v & BER_TAG_TYPE_MASK;
427 		j++;
428 	}
429 
430 	return (j);
431 }
432 
433 int
434 ober_string2oid(const char *oidstr, struct ber_oid *o)
435 {
436 	char			*sp, *p, str[BUFSIZ];
437 	const char		*errstr;
438 
439 	if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
440 		return (-1);
441 	memset(o, 0, sizeof(*o));
442 
443 	/* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
444 	for (p = sp = str; p != NULL; sp = p) {
445 		if ((p = strpbrk(p, "._-")) != NULL)
446 			*p++ = '\0';
447 		o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
448 		if (errstr || o->bo_n > BER_MAX_OID_LEN)
449 			return (-1);
450 	}
451 
452 	return (0);
453 }
454 
455 int
456 ober_oid_cmp(struct ber_oid *a, struct ber_oid *b)
457 {
458 	size_t	 i;
459 	for (i = 0; i < a->bo_n && i < b->bo_n; i++) {
460 		if (a->bo_id[i] == b->bo_id[i])
461 			continue;
462 		else if (a->bo_id[i] < b->bo_id[i]) {
463 			/* b is a successor of a */
464 			return (1);
465 		} else {
466 			/* b is a predecessor of a */
467 			return (-1);
468 		}
469 	}
470 	/* b is larger, but a child of a */
471 	if (a->bo_n < b->bo_n)
472 		return (2);
473 	/* b is a predecessor of a */
474 	if (a->bo_n > b->bo_n)
475 		return -1;
476 
477 	/* b and a are identical */
478 	return (0);
479 }
480 
481 struct ber_element *
482 ober_add_oid(struct ber_element *prev, struct ber_oid *o)
483 {
484 	struct ber_element	*elm;
485 	u_int8_t		*buf;
486 	size_t			 len;
487 
488 	if ((elm = ober_get_element(BER_TYPE_OBJECT)) == NULL)
489 		return (NULL);
490 
491 	if ((len = ober_oid2ber(o, NULL, 0)) == 0)
492 		goto fail;
493 
494 	if ((buf = calloc(1, len)) == NULL)
495 		goto fail;
496 
497 	elm->be_val = buf;
498 	elm->be_len = len;
499 	elm->be_free = 1;
500 
501 	if (ober_oid2ber(o, buf, len) != len)
502 		goto fail;
503 
504 	ober_link_elements(prev, elm);
505 
506 	return (elm);
507 
508  fail:
509 	ober_free_elements(elm);
510 	return (NULL);
511 }
512 
513 struct ber_element *
514 ober_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
515 {
516 	struct ber_oid		 no;
517 
518 	if (n > BER_MAX_OID_LEN)
519 		return (NULL);
520 	no.bo_n = n;
521 	bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
522 
523 	return (ober_add_oid(prev, &no));
524 }
525 
526 struct ber_element *
527 ober_add_oidstring(struct ber_element *prev, const char *oidstr)
528 {
529 	struct ber_oid		 o;
530 
531 	if (ober_string2oid(oidstr, &o) == -1)
532 		return (NULL);
533 
534 	return (ober_add_oid(prev, &o));
535 }
536 
537 int
538 ober_get_oid(struct ber_element *elm, struct ber_oid *o)
539 {
540 	u_int8_t	*buf;
541 	size_t		 len, i = 0, j = 0;
542 
543 	if (elm->be_encoding != BER_TYPE_OBJECT)
544 		return (-1);
545 
546 	buf = elm->be_val;
547 	len = elm->be_len;
548 
549 	memset(o, 0, sizeof(*o));
550 	o->bo_id[j++] = buf[i] / 40;
551 	o->bo_id[j++] = buf[i++] % 40;
552 	for (; i < len && j < BER_MAX_OID_LEN; i++) {
553 		o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
554 		if (buf[i] & 0x80)
555 			continue;
556 		j++;
557 	}
558 	o->bo_n = j;
559 
560 	return (0);
561 }
562 
563 struct ber_element *
564 ober_printf_elements(struct ber_element *ber, char *fmt, ...)
565 {
566 	va_list			 ap;
567 	int			 d, class;
568 	size_t			 len;
569 	unsigned int		 type;
570 	long long		 i;
571 	char			*s;
572 	void			*p;
573 	struct ber_oid		*o;
574 	struct ber_element	*sub = ber, *e;
575 
576 	va_start(ap, fmt);
577 	while (*fmt) {
578 		switch (*fmt++) {
579 		case 'B':
580 			p = va_arg(ap, void *);
581 			len = va_arg(ap, size_t);
582 			if ((ber = ober_add_bitstring(ber, p, len)) == NULL)
583 				goto fail;
584 			break;
585 		case 'b':
586 			d = va_arg(ap, int);
587 			if ((ber = ober_add_boolean(ber, d)) == NULL)
588 				goto fail;
589 			break;
590 		case 'd':
591 			d = va_arg(ap, int);
592 			if ((ber = ober_add_integer(ber, d)) == NULL)
593 				goto fail;
594 			break;
595 		case 'e':
596 			e = va_arg(ap, struct ber_element *);
597 			ober_link_elements(ber, e);
598 			break;
599 		case 'E':
600 			i = va_arg(ap, long long);
601 			if ((ber = ober_add_enumerated(ber, i)) == NULL)
602 				goto fail;
603 			break;
604 		case 'i':
605 			i = va_arg(ap, long long);
606 			if ((ber = ober_add_integer(ber, i)) == NULL)
607 				goto fail;
608 			break;
609 		case 'O':
610 			o = va_arg(ap, struct ber_oid *);
611 			if ((ber = ober_add_oid(ber, o)) == NULL)
612 				goto fail;
613 			break;
614 		case 'o':
615 			s = va_arg(ap, char *);
616 			if ((ber = ober_add_oidstring(ber, s)) == NULL)
617 				goto fail;
618 			break;
619 		case 's':
620 			s = va_arg(ap, char *);
621 			if ((ber = ober_add_string(ber, s)) == NULL)
622 				goto fail;
623 			break;
624 		case 't':
625 			class = va_arg(ap, int);
626 			type = va_arg(ap, unsigned int);
627 			ober_set_header(ber, class, type);
628 			break;
629 		case 'x':
630 			s = va_arg(ap, char *);
631 			len = va_arg(ap, size_t);
632 			if ((ber = ober_add_nstring(ber, s, len)) == NULL)
633 				goto fail;
634 			break;
635 		case '0':
636 			if ((ber = ober_add_null(ber)) == NULL)
637 				goto fail;
638 			break;
639 		case '{':
640 			if ((ber = sub = ober_add_sequence(ber)) == NULL)
641 				goto fail;
642 			break;
643 		case '(':
644 			if ((ber = sub = ober_add_set(ber)) == NULL)
645 				goto fail;
646 			break;
647 		case '}':
648 		case ')':
649 			ber = sub;
650 			break;
651 		case '.':
652 			if ((e = ober_add_eoc(ber)) == NULL)
653 				goto fail;
654 			ber = e;
655 			break;
656 		default:
657 			break;
658 		}
659 	}
660 	va_end(ap);
661 
662 	return (ber);
663  fail:
664 	ober_free_elements(ber);
665 	return (NULL);
666 }
667 
668 int
669 ober_scanf_elements(struct ber_element *ber, char *fmt, ...)
670 {
671 #define _MAX_SEQ		 128
672 	va_list			 ap;
673 	int			*d, level = -1;
674 	unsigned int		*t;
675 	long long		*i, l;
676 	void			**ptr;
677 	size_t			*len, ret = 0, n = strlen(fmt);
678 	char			**s;
679 	off_t			*pos;
680 	struct ber_oid		*o;
681 	struct ber_element	*parent[_MAX_SEQ], **e;
682 
683 	memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
684 
685 	va_start(ap, fmt);
686 	while (*fmt) {
687 		if (ber == NULL && *fmt != '$' && *fmt != '}' && *fmt != ')')
688 			goto fail;
689 		switch (*fmt++) {
690 		case '$':
691 			if (ber != NULL)
692 				goto fail;
693 			ret++;
694 			continue;
695 		case 'B':
696 			ptr = va_arg(ap, void **);
697 			len = va_arg(ap, size_t *);
698 			if (ober_get_bitstring(ber, ptr, len) == -1)
699 				goto fail;
700 			ret++;
701 			break;
702 		case 'b':
703 			d = va_arg(ap, int *);
704 			if (ober_get_boolean(ber, d) == -1)
705 				goto fail;
706 			ret++;
707 			break;
708 		case 'd':
709 			d = va_arg(ap, int *);
710 			if (ober_get_integer(ber, &l) == -1)
711 				goto fail;
712 			*d = l;
713 			ret++;
714 			break;
715 		case 'e':
716 			e = va_arg(ap, struct ber_element **);
717 			*e = ber;
718 			ret++;
719 			continue;
720 		case 'E':
721 			i = va_arg(ap, long long *);
722 			if (ober_get_enumerated(ber, i) == -1)
723 				goto fail;
724 			ret++;
725 			break;
726 		case 'i':
727 			i = va_arg(ap, long long *);
728 			if (ober_get_integer(ber, i) == -1)
729 				goto fail;
730 			ret++;
731 			break;
732 		case 'o':
733 			o = va_arg(ap, struct ber_oid *);
734 			if (ober_get_oid(ber, o) == -1)
735 				goto fail;
736 			ret++;
737 			break;
738 		case 'S':
739 			ret++;
740 			break;
741 		case 's':
742 			s = va_arg(ap, char **);
743 			if (ober_get_string(ber, s) == -1)
744 				goto fail;
745 			ret++;
746 			break;
747 		case 't':
748 			d = va_arg(ap, int *);
749 			t = va_arg(ap, unsigned int *);
750 			*d = ber->be_class;
751 			*t = ber->be_type;
752 			ret++;
753 			continue;
754 		case 'x':
755 			ptr = va_arg(ap, void **);
756 			len = va_arg(ap, size_t *);
757 			if (ober_get_nstring(ber, ptr, len) == -1)
758 				goto fail;
759 			ret++;
760 			break;
761 		case '0':
762 			if (ber->be_encoding != BER_TYPE_NULL)
763 				goto fail;
764 			ret++;
765 			break;
766 		case '.':
767 			if (ber->be_encoding != BER_TYPE_EOC)
768 				goto fail;
769 			ret++;
770 			break;
771 		case 'p':
772 			pos = va_arg(ap, off_t *);
773 			*pos = ober_getpos(ber);
774 			ret++;
775 			continue;
776 		case '{':
777 		case '(':
778 			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
779 			    ber->be_encoding != BER_TYPE_SET)
780 				goto fail;
781 			if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
782 				goto fail;
783 			parent[++level] = ber;
784 			ber = ber->be_sub;
785 			ret++;
786 			continue;
787 		case '}':
788 		case ')':
789 			if (level < 0 || parent[level] == NULL)
790 				goto fail;
791 			ber = parent[level--];
792 			ret++;
793 			break;
794 		default:
795 			goto fail;
796 		}
797 
798 		ber = ber->be_next;
799 	}
800 	va_end(ap);
801 	return (ret == n ? 0 : -1);
802 
803  fail:
804 	va_end(ap);
805 	return (-1);
806 
807 }
808 
809 ssize_t
810 ober_get_writebuf(struct ber *b, void **buf)
811 {
812 	if (b->br_wbuf == NULL)
813 		return -1;
814 	*buf = b->br_wbuf;
815 	return (b->br_wend - b->br_wbuf);
816 }
817 
818 /*
819  * write ber elements to the write buffer
820  *
821  * params:
822  *	ber	holds the destination write buffer byte stream
823  *	root	fully populated element tree
824  *
825  * returns:
826  *	>=0	number of bytes written
827  *	-1	on failure and sets errno
828  */
829 ssize_t
830 ober_write_elements(struct ber *ber, struct ber_element *root)
831 {
832 	size_t len;
833 
834 	/* calculate length because only the definite form is required */
835 	len = ober_calc_len(root);
836 	DPRINTF("write ber element of %zd bytes length\n", len);
837 
838 	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
839 		free(ber->br_wbuf);
840 		ber->br_wbuf = NULL;
841 	}
842 	if (ber->br_wbuf == NULL) {
843 		if ((ber->br_wbuf = malloc(len)) == NULL)
844 			return -1;
845 		ber->br_wend = ber->br_wbuf + len;
846 	}
847 
848 	/* reset write pointer */
849 	ber->br_wptr = ber->br_wbuf;
850 
851 	if (ober_dump_element(ber, root) == -1)
852 		return -1;
853 
854 	return (len);
855 }
856 
857 void
858 ober_set_readbuf(struct ber *b, void *buf, size_t len)
859 {
860 	b->br_rbuf = b->br_rptr = buf;
861 	b->br_rend = (u_int8_t *)buf + len;
862 }
863 
864 /*
865  * read ber elements from the read buffer
866  *
867  * params:
868  *	ber	holds a fully populated read buffer byte stream
869  *	root	if NULL, build up an element tree from what we receive on
870  *		the wire. If not null, use the specified encoding for the
871  *		elements received.
872  *
873  * returns:
874  *	!=NULL, elements read and store in the ber_element tree
875  *	NULL, type mismatch or read error
876  */
877 struct ber_element *
878 ober_read_elements(struct ber *ber, struct ber_element *elm)
879 {
880 	struct ber_element *root = elm;
881 
882 	if (root == NULL) {
883 		if ((root = ober_get_element(0)) == NULL)
884 			return NULL;
885 	}
886 
887 	DPRINTF("read ber elements, root %p\n", root);
888 
889 	if (ober_read_element(ber, root) == -1) {
890 		/* Cleanup if root was allocated by us */
891 		if (elm == NULL)
892 			ober_free_elements(root);
893 		return NULL;
894 	}
895 
896 	return root;
897 }
898 
899 off_t
900 ober_getpos(struct ber_element *elm)
901 {
902 	return elm->be_offs;
903 }
904 
905 void
906 ober_free_element(struct ber_element *root)
907 {
908 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
909 	    root->be_encoding == BER_TYPE_SET))
910 		ober_free_elements(root->be_sub);
911 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
912 	    root->be_encoding == BER_TYPE_BITSTRING ||
913 	    root->be_encoding == BER_TYPE_OBJECT))
914 		free(root->be_val);
915 	free(root);
916 }
917 
918 void
919 ober_free_elements(struct ber_element *root)
920 {
921 	if (root == NULL)
922 		return;
923 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
924 	    root->be_encoding == BER_TYPE_SET))
925 		ober_free_elements(root->be_sub);
926 	if (root->be_next)
927 		ober_free_elements(root->be_next);
928 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
929 	    root->be_encoding == BER_TYPE_BITSTRING ||
930 	    root->be_encoding == BER_TYPE_OBJECT))
931 		free(root->be_val);
932 	free(root);
933 }
934 
935 size_t
936 ober_calc_len(struct ber_element *root)
937 {
938 	unsigned int t;
939 	size_t s;
940 	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
941 
942 	/* calculate the real length of a sequence or set */
943 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
944 	    root->be_encoding == BER_TYPE_SET))
945 		root->be_len = ober_calc_len(root->be_sub);
946 
947 	/* fix header length for extended types */
948 	if (root->be_type > BER_TYPE_SINGLE_MAX)
949 		for (t = root->be_type; t > 0; t >>= 7)
950 			size++;
951 	if (root->be_len >= BER_TAG_MORE)
952 		for (s = root->be_len; s > 0; s >>= 8)
953 			size++;
954 
955 	/* calculate the length of the following elements */
956 	if (root->be_next)
957 		size += ober_calc_len(root->be_next);
958 
959 	/* This is an empty element, do not use a minimal size */
960 	if (root->be_class == BER_CLASS_UNIVERSAL &&
961 	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
962 		return (0);
963 
964 	return (root->be_len + size);
965 }
966 
967 void
968 ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
969 {
970 	b->br_application = cb;
971 }
972 
973 void
974 ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
975     void *arg)
976 {
977 	elm->be_cb = cb;
978 	elm->be_cbarg = arg;
979 }
980 
981 void
982 ober_free(struct ber *b)
983 {
984 	free(b->br_wbuf);
985 }
986 
987 /*
988  * internal functions
989  */
990 
991 static int
992 ober_dump_element(struct ber *ber, struct ber_element *root)
993 {
994 	unsigned long long l;
995 	int i;
996 	uint8_t u;
997 
998 	ober_dump_header(ber, root);
999 	if (root->be_cb)
1000 		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1001 
1002 	switch (root->be_encoding) {
1003 	case BER_TYPE_BOOLEAN:
1004 	case BER_TYPE_INTEGER:
1005 	case BER_TYPE_ENUMERATED:
1006 		l = (unsigned long long)root->be_numeric;
1007 		for (i = root->be_len; i > 0; i--) {
1008 			u = (l >> ((i - 1) * 8)) & 0xff;
1009 			ober_putc(ber, u);
1010 		}
1011 		break;
1012 	case BER_TYPE_BITSTRING:
1013 	case BER_TYPE_OCTETSTRING:
1014 	case BER_TYPE_OBJECT:
1015 		ober_write(ber, root->be_val, root->be_len);
1016 		break;
1017 	case BER_TYPE_NULL:	/* no payload */
1018 	case BER_TYPE_EOC:
1019 		break;
1020 	case BER_TYPE_SEQUENCE:
1021 	case BER_TYPE_SET:
1022 		if (root->be_sub && ober_dump_element(ber, root->be_sub) == -1)
1023 			return -1;
1024 		break;
1025 	}
1026 
1027 	if (root->be_next == NULL)
1028 		return 0;
1029 	return ober_dump_element(ber, root->be_next);
1030 }
1031 
1032 static void
1033 ober_dump_header(struct ber *ber, struct ber_element *root)
1034 {
1035 	u_char	id = 0, t, buf[5];
1036 	unsigned int type;
1037 	size_t size;
1038 
1039 	/* class universal, type encoding depending on type value */
1040 	/* length encoding */
1041 	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1042 		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1043 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1044 		    root->be_encoding == BER_TYPE_SET)
1045 			id |= BER_TYPE_CONSTRUCTED;
1046 
1047 		ober_putc(ber, id);
1048 	} else {
1049 		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1050 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1051 		    root->be_encoding == BER_TYPE_SET)
1052 			id |= BER_TYPE_CONSTRUCTED;
1053 
1054 		ober_putc(ber, id);
1055 
1056 		for (t = 0, type = root->be_type; type > 0; type >>= 7)
1057 			buf[t++] = type & ~BER_TAG_MORE;
1058 
1059 		while (t-- > 0) {
1060 			if (t > 0)
1061 				buf[t] |= BER_TAG_MORE;
1062 			ober_putc(ber, buf[t]);
1063 		}
1064 	}
1065 
1066 	if (root->be_len < BER_TAG_MORE) {
1067 		/* short form */
1068 		ober_putc(ber, root->be_len);
1069 	} else {
1070 		for (t = 0, size = root->be_len; size > 0; size >>= 8)
1071 			buf[t++] = size & 0xff;
1072 
1073 		ober_putc(ber, t | BER_TAG_MORE);
1074 
1075 		while (t > 0)
1076 			ober_putc(ber, buf[--t]);
1077 	}
1078 }
1079 
1080 static void
1081 ober_putc(struct ber *ber, u_char c)
1082 {
1083 	if (ber->br_wptr + 1 <= ber->br_wend)
1084 		*ber->br_wptr = c;
1085 	ber->br_wptr++;
1086 }
1087 
1088 static void
1089 ober_write(struct ber *ber, void *buf, size_t len)
1090 {
1091 	if (ber->br_wptr + len <= ber->br_wend)
1092 		bcopy(buf, ber->br_wptr, len);
1093 	ber->br_wptr += len;
1094 }
1095 
1096 /*
1097  * extract a BER encoded tag. There are two types, a short and long form.
1098  */
1099 static ssize_t
1100 get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1101 {
1102 	u_char u;
1103 	size_t i = 0;
1104 	unsigned int t = 0;
1105 
1106 	if (ober_getc(b, &u) == -1)
1107 		return -1;
1108 
1109 	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1110 	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1111 
1112 	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1113 		*tag = u & BER_TAG_MASK;
1114 		return 1;
1115 	}
1116 
1117 	do {
1118 		if (ober_getc(b, &u) == -1)
1119 			return -1;
1120 
1121 		/* enforce minimal number of octets for tag > 30 */
1122 		if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1123 			errno = EINVAL;
1124 			return -1;
1125 		}
1126 
1127 		t = (t << 7) | (u & ~BER_TAG_MORE);
1128 		i++;
1129 		if (i > sizeof(unsigned int)) {
1130 			errno = ERANGE;
1131 			return -1;
1132 		}
1133 	} while (u & BER_TAG_MORE);
1134 
1135 	*tag = t;
1136 	return i + 1;
1137 }
1138 
1139 /*
1140  * extract length of a ber object -- if length is unknown an error is returned.
1141  */
1142 static ssize_t
1143 get_len(struct ber *b, ssize_t *len)
1144 {
1145 	u_char	u, n;
1146 	ssize_t	s, r;
1147 
1148 	if (ober_getc(b, &u) == -1)
1149 		return -1;
1150 	if ((u & BER_TAG_MORE) == 0) {
1151 		/* short form */
1152 		*len = u;
1153 		return 1;
1154 	}
1155 
1156 	if (u == 0x80) {
1157 		/* Indefinite length not supported. */
1158 		errno = EINVAL;
1159 		return -1;
1160 	}
1161 
1162 	if (u == 0xff) {
1163 		/* Reserved for future use. */
1164 		errno = EINVAL;
1165 		return -1;
1166 	}
1167 
1168 	n = u & ~BER_TAG_MORE;
1169 	/*
1170 	 * Limit to a decent size that works on all of our architectures.
1171 	 */
1172 	if (sizeof(int32_t) < n) {
1173 		errno = ERANGE;
1174 		return -1;
1175 	}
1176 	r = n + 1;
1177 
1178 	for (s = 0; n > 0; n--) {
1179 		if (ober_getc(b, &u) == -1)
1180 			return -1;
1181 		s = (s << 8) | u;
1182 	}
1183 
1184 	if (s < 0) {
1185 		/* overflow */
1186 		errno = ERANGE;
1187 		return -1;
1188 	}
1189 
1190 	*len = s;
1191 	return r;
1192 }
1193 
1194 static ssize_t
1195 ober_read_element(struct ber *ber, struct ber_element *elm)
1196 {
1197 	long long val = 0;
1198 	struct ber_element *next;
1199 	unsigned int type;
1200 	int i, class, cstruct, elements = 0;
1201 	ssize_t len, r, totlen = 0;
1202 	u_char c, last = 0;
1203 
1204 	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1205 		return -1;
1206 	DPRINTF("ber read got class %d type %u, %s\n",
1207 	    class, type, cstruct ? "constructed" : "primitive");
1208 	totlen += r;
1209 	if ((r = get_len(ber, &len)) == -1)
1210 		return -1;
1211 	DPRINTF("ber read element size %zd\n", len);
1212 	totlen += r + len;
1213 
1214 	/* The encoding of boolean, integer, enumerated, and null values
1215 	 * must be primitive. */
1216 	if (class == BER_CLASS_UNIVERSAL)
1217 		if (type == BER_TYPE_BOOLEAN ||
1218 		    type == BER_TYPE_INTEGER ||
1219 		    type == BER_TYPE_ENUMERATED ||
1220 		    type == BER_TYPE_NULL)
1221 			if (cstruct) {
1222 				errno = EINVAL;
1223 				return -1;
1224 			}
1225 
1226 	/* If the total size of the element is larger than the buffer
1227 	 * don't bother to continue. */
1228 	if (len > ber->br_rend - ber->br_rptr) {
1229 		errno = ECANCELED;
1230 		return -1;
1231 	}
1232 
1233 	elm->be_type = type;
1234 	elm->be_len = len;
1235 	elm->be_offs = ber->br_offs;	/* element position within stream */
1236 	elm->be_class = class;
1237 
1238 	if (elm->be_encoding == 0) {
1239 		/* try to figure out the encoding via class, type and cstruct */
1240 		if (cstruct)
1241 			elm->be_encoding = BER_TYPE_SEQUENCE;
1242 		else if (class == BER_CLASS_UNIVERSAL)
1243 			elm->be_encoding = type;
1244 		else if (ber->br_application != NULL) {
1245 			/*
1246 			 * Ask the application to map the encoding to a
1247 			 * universal type. For example, a SMI IpAddress
1248 			 * type is defined as 4 byte OCTET STRING.
1249 			 */
1250 			elm->be_encoding = (*ber->br_application)(elm);
1251 		} else
1252 			/* last resort option */
1253 			elm->be_encoding = BER_TYPE_NULL;
1254 	}
1255 
1256 	switch (elm->be_encoding) {
1257 	case BER_TYPE_EOC:	/* End-Of-Content */
1258 		break;
1259 	case BER_TYPE_BOOLEAN:
1260 		if (len != 1) {
1261 			errno = EINVAL;
1262 			return -1;
1263 		}
1264 	case BER_TYPE_INTEGER:
1265 	case BER_TYPE_ENUMERATED:
1266 		if (len < 1) {
1267 			errno = EINVAL;
1268 			return -1;
1269 		}
1270 		if (len > (ssize_t)sizeof(long long)) {
1271 			errno = ERANGE;
1272 			return -1;
1273 		}
1274 		for (i = 0; i < len; i++) {
1275 			if (ober_getc(ber, &c) != 1)
1276 				return -1;
1277 
1278 			/* smallest number of contents octets only */
1279 			if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1280 			    (i == 1 && last == 0xff && (c & 0x80) != 0)) {
1281 				errno = EINVAL;
1282 				return -1;
1283 			}
1284 
1285 			val <<= 8;
1286 			val |= c;
1287 			last = c;
1288 		}
1289 
1290 		/* sign extend if MSB is set */
1291 		if (len < (ssize_t)sizeof(long long) &&
1292 		    (val >> ((len - 1) * 8) & 0x80))
1293 			val |= ULLONG_MAX << (len * 8);
1294 		elm->be_numeric = val;
1295 		break;
1296 	case BER_TYPE_BITSTRING:
1297 		elm->be_val = malloc(len);
1298 		if (elm->be_val == NULL)
1299 			return -1;
1300 		elm->be_free = 1;
1301 		elm->be_len = len;
1302 		ober_read(ber, elm->be_val, len);
1303 		break;
1304 	case BER_TYPE_OCTETSTRING:
1305 	case BER_TYPE_OBJECT:
1306 		elm->be_val = malloc(len + 1);
1307 		if (elm->be_val == NULL)
1308 			return -1;
1309 		elm->be_free = 1;
1310 		elm->be_len = len;
1311 		ober_read(ber, elm->be_val, len);
1312 		((u_char *)elm->be_val)[len] = '\0';
1313 		break;
1314 	case BER_TYPE_NULL:	/* no payload */
1315 		if (len != 0) {
1316 			errno = EINVAL;
1317 			return -1;
1318 		}
1319 		break;
1320 	case BER_TYPE_SEQUENCE:
1321 	case BER_TYPE_SET:
1322 		if (elm->be_sub == NULL) {
1323 			if ((elm->be_sub = ober_get_element(0)) == NULL)
1324 				return -1;
1325 		}
1326 		next = elm->be_sub;
1327 		while (len > 0) {
1328 			/*
1329 			 * Prevent stack overflow from excessive recursion
1330 			 * depth in ober_free_elements().
1331 			 */
1332 			if (elements >= BER_MAX_SEQ_ELEMENTS) {
1333 				errno = ERANGE;
1334 				return -1;
1335 			}
1336 			r = ober_read_element(ber, next);
1337 			if (r == -1)
1338 				return -1;
1339 			elements++;
1340 			len -= r;
1341 			if (len > 0 && next->be_next == NULL) {
1342 				if ((next->be_next = ober_get_element(0)) ==
1343 				    NULL)
1344 					return -1;
1345 			}
1346 			next = next->be_next;
1347 		}
1348 		break;
1349 	}
1350 	return totlen;
1351 }
1352 
1353 static ssize_t
1354 ober_getc(struct ber *b, u_char *c)
1355 {
1356 	return ober_read(b, c, 1);
1357 }
1358 
1359 static ssize_t
1360 ober_read(struct ber *ber, void *buf, size_t len)
1361 {
1362 	size_t	sz;
1363 
1364 	if (ber->br_rbuf == NULL) {
1365 		errno = ENOBUFS;
1366 		return -1;
1367 	}
1368 
1369 	sz = ber->br_rend - ber->br_rptr;
1370 	if (len > sz) {
1371 		errno = ECANCELED;
1372 		return -1;	/* parser wants more data than available */
1373 	}
1374 
1375 	bcopy(ber->br_rptr, buf, len);
1376 	ber->br_rptr += len;
1377 	ber->br_offs += len;
1378 
1379 	return len;
1380 }
1381