xref: /openbsd/lib/libutil/ber.c (revision e5dd7070)
1 /*	$OpenBSD: ber.c,v 1.15 2019/10/24 12:39:26 tb 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 != ')')
688 			goto fail;
689 		switch (*fmt++) {
690 		case 'B':
691 			ptr = va_arg(ap, void **);
692 			len = va_arg(ap, size_t *);
693 			if (ober_get_bitstring(ber, ptr, len) == -1)
694 				goto fail;
695 			ret++;
696 			break;
697 		case 'b':
698 			d = va_arg(ap, int *);
699 			if (ober_get_boolean(ber, d) == -1)
700 				goto fail;
701 			ret++;
702 			break;
703 		case 'd':
704 			d = va_arg(ap, int *);
705 			if (ober_get_integer(ber, &l) == -1)
706 				goto fail;
707 			*d = l;
708 			ret++;
709 			break;
710 		case 'e':
711 			e = va_arg(ap, struct ber_element **);
712 			*e = ber;
713 			ret++;
714 			continue;
715 		case 'E':
716 			i = va_arg(ap, long long *);
717 			if (ober_get_enumerated(ber, i) == -1)
718 				goto fail;
719 			ret++;
720 			break;
721 		case 'i':
722 			i = va_arg(ap, long long *);
723 			if (ober_get_integer(ber, i) == -1)
724 				goto fail;
725 			ret++;
726 			break;
727 		case 'o':
728 			o = va_arg(ap, struct ber_oid *);
729 			if (ober_get_oid(ber, o) == -1)
730 				goto fail;
731 			ret++;
732 			break;
733 		case 'S':
734 			ret++;
735 			break;
736 		case 's':
737 			s = va_arg(ap, char **);
738 			if (ober_get_string(ber, s) == -1)
739 				goto fail;
740 			ret++;
741 			break;
742 		case 't':
743 			d = va_arg(ap, int *);
744 			t = va_arg(ap, unsigned int *);
745 			*d = ber->be_class;
746 			*t = ber->be_type;
747 			ret++;
748 			continue;
749 		case 'x':
750 			ptr = va_arg(ap, void **);
751 			len = va_arg(ap, size_t *);
752 			if (ober_get_nstring(ber, ptr, len) == -1)
753 				goto fail;
754 			ret++;
755 			break;
756 		case '0':
757 			if (ber->be_encoding != BER_TYPE_NULL)
758 				goto fail;
759 			ret++;
760 			break;
761 		case '.':
762 			if (ber->be_encoding != BER_TYPE_EOC)
763 				goto fail;
764 			ret++;
765 			break;
766 		case 'p':
767 			pos = va_arg(ap, off_t *);
768 			*pos = ober_getpos(ber);
769 			ret++;
770 			continue;
771 		case '{':
772 		case '(':
773 			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
774 			    ber->be_encoding != BER_TYPE_SET)
775 				goto fail;
776 			if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
777 				goto fail;
778 			parent[++level] = ber;
779 			ber = ber->be_sub;
780 			ret++;
781 			continue;
782 		case '}':
783 		case ')':
784 			if (parent[level] == NULL)
785 				goto fail;
786 			ber = parent[level--];
787 			ret++;
788 			break;
789 		default:
790 			goto fail;
791 		}
792 
793 		ber = ber->be_next;
794 	}
795 	va_end(ap);
796 	return (ret == n ? 0 : -1);
797 
798  fail:
799 	va_end(ap);
800 	return (-1);
801 
802 }
803 
804 ssize_t
805 ober_get_writebuf(struct ber *b, void **buf)
806 {
807 	if (b->br_wbuf == NULL)
808 		return -1;
809 	*buf = b->br_wbuf;
810 	return (b->br_wend - b->br_wbuf);
811 }
812 
813 /*
814  * write ber elements to the write buffer
815  *
816  * params:
817  *	ber	holds the destination write buffer byte stream
818  *	root	fully populated element tree
819  *
820  * returns:
821  *	>=0	number of bytes written
822  *	-1	on failure and sets errno
823  */
824 ssize_t
825 ober_write_elements(struct ber *ber, struct ber_element *root)
826 {
827 	size_t len;
828 
829 	/* calculate length because only the definite form is required */
830 	len = ober_calc_len(root);
831 	DPRINTF("write ber element of %zd bytes length\n", len);
832 
833 	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
834 		free(ber->br_wbuf);
835 		ber->br_wbuf = NULL;
836 	}
837 	if (ber->br_wbuf == NULL) {
838 		if ((ber->br_wbuf = malloc(len)) == NULL)
839 			return -1;
840 		ber->br_wend = ber->br_wbuf + len;
841 	}
842 
843 	/* reset write pointer */
844 	ber->br_wptr = ber->br_wbuf;
845 
846 	if (ober_dump_element(ber, root) == -1)
847 		return -1;
848 
849 	return (len);
850 }
851 
852 void
853 ober_set_readbuf(struct ber *b, void *buf, size_t len)
854 {
855 	b->br_rbuf = b->br_rptr = buf;
856 	b->br_rend = (u_int8_t *)buf + len;
857 }
858 
859 /*
860  * read ber elements from the read buffer
861  *
862  * params:
863  *	ber	holds a fully populated read buffer byte stream
864  *	root	if NULL, build up an element tree from what we receive on
865  *		the wire. If not null, use the specified encoding for the
866  *		elements received.
867  *
868  * returns:
869  *	!=NULL, elements read and store in the ber_element tree
870  *	NULL, type mismatch or read error
871  */
872 struct ber_element *
873 ober_read_elements(struct ber *ber, struct ber_element *elm)
874 {
875 	struct ber_element *root = elm;
876 
877 	if (root == NULL) {
878 		if ((root = ober_get_element(0)) == NULL)
879 			return NULL;
880 	}
881 
882 	DPRINTF("read ber elements, root %p\n", root);
883 
884 	if (ober_read_element(ber, root) == -1) {
885 		/* Cleanup if root was allocated by us */
886 		if (elm == NULL)
887 			ober_free_elements(root);
888 		return NULL;
889 	}
890 
891 	return root;
892 }
893 
894 off_t
895 ober_getpos(struct ber_element *elm)
896 {
897 	return elm->be_offs;
898 }
899 
900 void
901 ober_free_element(struct ber_element *root)
902 {
903 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
904 	    root->be_encoding == BER_TYPE_SET))
905 		ober_free_elements(root->be_sub);
906 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
907 	    root->be_encoding == BER_TYPE_BITSTRING ||
908 	    root->be_encoding == BER_TYPE_OBJECT))
909 		free(root->be_val);
910 	free(root);
911 }
912 
913 void
914 ober_free_elements(struct ber_element *root)
915 {
916 	if (root == NULL)
917 		return;
918 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
919 	    root->be_encoding == BER_TYPE_SET))
920 		ober_free_elements(root->be_sub);
921 	if (root->be_next)
922 		ober_free_elements(root->be_next);
923 	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
924 	    root->be_encoding == BER_TYPE_BITSTRING ||
925 	    root->be_encoding == BER_TYPE_OBJECT))
926 		free(root->be_val);
927 	free(root);
928 }
929 
930 size_t
931 ober_calc_len(struct ber_element *root)
932 {
933 	unsigned int t;
934 	size_t s;
935 	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
936 
937 	/* calculate the real length of a sequence or set */
938 	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
939 	    root->be_encoding == BER_TYPE_SET))
940 		root->be_len = ober_calc_len(root->be_sub);
941 
942 	/* fix header length for extended types */
943 	if (root->be_type > BER_TYPE_SINGLE_MAX)
944 		for (t = root->be_type; t > 0; t >>= 7)
945 			size++;
946 	if (root->be_len >= BER_TAG_MORE)
947 		for (s = root->be_len; s > 0; s >>= 8)
948 			size++;
949 
950 	/* calculate the length of the following elements */
951 	if (root->be_next)
952 		size += ober_calc_len(root->be_next);
953 
954 	/* This is an empty element, do not use a minimal size */
955 	if (root->be_class == BER_CLASS_UNIVERSAL &&
956 	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
957 		return (0);
958 
959 	return (root->be_len + size);
960 }
961 
962 void
963 ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
964 {
965 	b->br_application = cb;
966 }
967 
968 void
969 ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
970     void *arg)
971 {
972 	elm->be_cb = cb;
973 	elm->be_cbarg = arg;
974 }
975 
976 void
977 ober_free(struct ber *b)
978 {
979 	free(b->br_wbuf);
980 }
981 
982 /*
983  * internal functions
984  */
985 
986 static int
987 ober_dump_element(struct ber *ber, struct ber_element *root)
988 {
989 	unsigned long long l;
990 	int i;
991 	uint8_t u;
992 
993 	ober_dump_header(ber, root);
994 	if (root->be_cb)
995 		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
996 
997 	switch (root->be_encoding) {
998 	case BER_TYPE_BOOLEAN:
999 	case BER_TYPE_INTEGER:
1000 	case BER_TYPE_ENUMERATED:
1001 		l = (unsigned long long)root->be_numeric;
1002 		for (i = root->be_len; i > 0; i--) {
1003 			u = (l >> ((i - 1) * 8)) & 0xff;
1004 			ober_putc(ber, u);
1005 		}
1006 		break;
1007 	case BER_TYPE_BITSTRING:
1008 	case BER_TYPE_OCTETSTRING:
1009 	case BER_TYPE_OBJECT:
1010 		ober_write(ber, root->be_val, root->be_len);
1011 		break;
1012 	case BER_TYPE_NULL:	/* no payload */
1013 	case BER_TYPE_EOC:
1014 		break;
1015 	case BER_TYPE_SEQUENCE:
1016 	case BER_TYPE_SET:
1017 		if (root->be_sub && ober_dump_element(ber, root->be_sub) == -1)
1018 			return -1;
1019 		break;
1020 	}
1021 
1022 	if (root->be_next == NULL)
1023 		return 0;
1024 	return ober_dump_element(ber, root->be_next);
1025 }
1026 
1027 static void
1028 ober_dump_header(struct ber *ber, struct ber_element *root)
1029 {
1030 	u_char	id = 0, t, buf[5];
1031 	unsigned int type;
1032 	size_t size;
1033 
1034 	/* class universal, type encoding depending on type value */
1035 	/* length encoding */
1036 	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1037 		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1038 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1039 		    root->be_encoding == BER_TYPE_SET)
1040 			id |= BER_TYPE_CONSTRUCTED;
1041 
1042 		ober_putc(ber, id);
1043 	} else {
1044 		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1045 		if (root->be_encoding == BER_TYPE_SEQUENCE ||
1046 		    root->be_encoding == BER_TYPE_SET)
1047 			id |= BER_TYPE_CONSTRUCTED;
1048 
1049 		ober_putc(ber, id);
1050 
1051 		for (t = 0, type = root->be_type; type > 0; type >>= 7)
1052 			buf[t++] = type & ~BER_TAG_MORE;
1053 
1054 		while (t-- > 0) {
1055 			if (t > 0)
1056 				buf[t] |= BER_TAG_MORE;
1057 			ober_putc(ber, buf[t]);
1058 		}
1059 	}
1060 
1061 	if (root->be_len < BER_TAG_MORE) {
1062 		/* short form */
1063 		ober_putc(ber, root->be_len);
1064 	} else {
1065 		for (t = 0, size = root->be_len; size > 0; size >>= 8)
1066 			buf[t++] = size & 0xff;
1067 
1068 		ober_putc(ber, t | BER_TAG_MORE);
1069 
1070 		while (t > 0)
1071 			ober_putc(ber, buf[--t]);
1072 	}
1073 }
1074 
1075 static void
1076 ober_putc(struct ber *ber, u_char c)
1077 {
1078 	if (ber->br_wptr + 1 <= ber->br_wend)
1079 		*ber->br_wptr = c;
1080 	ber->br_wptr++;
1081 }
1082 
1083 static void
1084 ober_write(struct ber *ber, void *buf, size_t len)
1085 {
1086 	if (ber->br_wptr + len <= ber->br_wend)
1087 		bcopy(buf, ber->br_wptr, len);
1088 	ber->br_wptr += len;
1089 }
1090 
1091 /*
1092  * extract a BER encoded tag. There are two types, a short and long form.
1093  */
1094 static ssize_t
1095 get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1096 {
1097 	u_char u;
1098 	size_t i = 0;
1099 	unsigned int t = 0;
1100 
1101 	if (ober_getc(b, &u) == -1)
1102 		return -1;
1103 
1104 	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1105 	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1106 
1107 	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1108 		*tag = u & BER_TAG_MASK;
1109 		return 1;
1110 	}
1111 
1112 	do {
1113 		if (ober_getc(b, &u) == -1)
1114 			return -1;
1115 
1116 		/* enforce minimal number of octets for tag > 30 */
1117 		if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1118 			errno = EINVAL;
1119 			return -1;
1120 		}
1121 
1122 		t = (t << 7) | (u & ~BER_TAG_MORE);
1123 		i++;
1124 		if (i > sizeof(unsigned int)) {
1125 			errno = ERANGE;
1126 			return -1;
1127 		}
1128 	} while (u & BER_TAG_MORE);
1129 
1130 	*tag = t;
1131 	return i + 1;
1132 }
1133 
1134 /*
1135  * extract length of a ber object -- if length is unknown an error is returned.
1136  */
1137 static ssize_t
1138 get_len(struct ber *b, ssize_t *len)
1139 {
1140 	u_char	u, n;
1141 	ssize_t	s, r;
1142 
1143 	if (ober_getc(b, &u) == -1)
1144 		return -1;
1145 	if ((u & BER_TAG_MORE) == 0) {
1146 		/* short form */
1147 		*len = u;
1148 		return 1;
1149 	}
1150 
1151 	if (u == 0x80) {
1152 		/* Indefinite length not supported. */
1153 		errno = EINVAL;
1154 		return -1;
1155 	}
1156 
1157 	if (u == 0xff) {
1158 		/* Reserved for future use. */
1159 		errno = EINVAL;
1160 		return -1;
1161 	}
1162 
1163 	n = u & ~BER_TAG_MORE;
1164 	/*
1165 	 * Limit to a decent size that works on all of our architectures.
1166 	 */
1167 	if (sizeof(int32_t) < n) {
1168 		errno = ERANGE;
1169 		return -1;
1170 	}
1171 	r = n + 1;
1172 
1173 	for (s = 0; n > 0; n--) {
1174 		if (ober_getc(b, &u) == -1)
1175 			return -1;
1176 		s = (s << 8) | u;
1177 	}
1178 
1179 	if (s < 0) {
1180 		/* overflow */
1181 		errno = ERANGE;
1182 		return -1;
1183 	}
1184 
1185 	*len = s;
1186 	return r;
1187 }
1188 
1189 static ssize_t
1190 ober_read_element(struct ber *ber, struct ber_element *elm)
1191 {
1192 	long long val = 0;
1193 	struct ber_element *next;
1194 	unsigned int type;
1195 	int i, class, cstruct, elements = 0;
1196 	ssize_t len, r, totlen = 0;
1197 	u_char c, last = 0;
1198 
1199 	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1200 		return -1;
1201 	DPRINTF("ber read got class %d type %u, %s\n",
1202 	    class, type, cstruct ? "constructed" : "primitive");
1203 	totlen += r;
1204 	if ((r = get_len(ber, &len)) == -1)
1205 		return -1;
1206 	DPRINTF("ber read element size %zd\n", len);
1207 	totlen += r + len;
1208 
1209 	/* The encoding of boolean, integer, enumerated, and null values
1210 	 * must be primitive. */
1211 	if (class == BER_CLASS_UNIVERSAL)
1212 		if (type == BER_TYPE_BOOLEAN ||
1213 		    type == BER_TYPE_INTEGER ||
1214 		    type == BER_TYPE_ENUMERATED ||
1215 		    type == BER_TYPE_NULL)
1216 			if (cstruct) {
1217 				errno = EINVAL;
1218 				return -1;
1219 			}
1220 
1221 	/* If the total size of the element is larger than the buffer
1222 	 * don't bother to continue. */
1223 	if (len > ber->br_rend - ber->br_rptr) {
1224 		errno = ECANCELED;
1225 		return -1;
1226 	}
1227 
1228 	elm->be_type = type;
1229 	elm->be_len = len;
1230 	elm->be_offs = ber->br_offs;	/* element position within stream */
1231 	elm->be_class = class;
1232 
1233 	if (elm->be_encoding == 0) {
1234 		/* try to figure out the encoding via class, type and cstruct */
1235 		if (cstruct)
1236 			elm->be_encoding = BER_TYPE_SEQUENCE;
1237 		else if (class == BER_CLASS_UNIVERSAL)
1238 			elm->be_encoding = type;
1239 		else if (ber->br_application != NULL) {
1240 			/*
1241 			 * Ask the application to map the encoding to a
1242 			 * universal type. For example, a SMI IpAddress
1243 			 * type is defined as 4 byte OCTET STRING.
1244 			 */
1245 			elm->be_encoding = (*ber->br_application)(elm);
1246 		} else
1247 			/* last resort option */
1248 			elm->be_encoding = BER_TYPE_NULL;
1249 	}
1250 
1251 	switch (elm->be_encoding) {
1252 	case BER_TYPE_EOC:	/* End-Of-Content */
1253 		break;
1254 	case BER_TYPE_BOOLEAN:
1255 		if (len != 1) {
1256 			errno = EINVAL;
1257 			return -1;
1258 		}
1259 	case BER_TYPE_INTEGER:
1260 	case BER_TYPE_ENUMERATED:
1261 		if (len > (ssize_t)sizeof(long long))
1262 			return -1;
1263 		for (i = 0; i < len; i++) {
1264 			if (ober_getc(ber, &c) != 1)
1265 				return -1;
1266 
1267 			/* smallest number of contents octets only */
1268 			if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1269 			    (i == 1 && last == 0xff && (c & 0x80) != 0))
1270 				return -1;
1271 
1272 			val <<= 8;
1273 			val |= c;
1274 			last = c;
1275 		}
1276 
1277 		/* sign extend if MSB is set */
1278 		if (len < (ssize_t)sizeof(long long) &&
1279 		    (val >> ((len - 1) * 8) & 0x80))
1280 			val |= ULLONG_MAX << (len * 8);
1281 		elm->be_numeric = val;
1282 		break;
1283 	case BER_TYPE_BITSTRING:
1284 		elm->be_val = malloc(len);
1285 		if (elm->be_val == NULL)
1286 			return -1;
1287 		elm->be_free = 1;
1288 		elm->be_len = len;
1289 		ober_read(ber, elm->be_val, len);
1290 		break;
1291 	case BER_TYPE_OCTETSTRING:
1292 	case BER_TYPE_OBJECT:
1293 		elm->be_val = malloc(len + 1);
1294 		if (elm->be_val == NULL)
1295 			return -1;
1296 		elm->be_free = 1;
1297 		elm->be_len = len;
1298 		ober_read(ber, elm->be_val, len);
1299 		((u_char *)elm->be_val)[len] = '\0';
1300 		break;
1301 	case BER_TYPE_NULL:	/* no payload */
1302 		if (len != 0)
1303 			return -1;
1304 		break;
1305 	case BER_TYPE_SEQUENCE:
1306 	case BER_TYPE_SET:
1307 		if (elm->be_sub == NULL) {
1308 			if ((elm->be_sub = ober_get_element(0)) == NULL)
1309 				return -1;
1310 		}
1311 		next = elm->be_sub;
1312 		while (len > 0) {
1313 			/*
1314 			 * Prevent stack overflow from excessive recursion
1315 			 * depth in ober_free_elements().
1316 			 */
1317 			if (elements >= BER_MAX_SEQ_ELEMENTS) {
1318 				errno = ERANGE;
1319 				return -1;
1320 			}
1321 			r = ober_read_element(ber, next);
1322 			if (r == -1)
1323 				return -1;
1324 			elements++;
1325 			len -= r;
1326 			if (len > 0 && next->be_next == NULL) {
1327 				if ((next->be_next = ober_get_element(0)) ==
1328 				    NULL)
1329 					return -1;
1330 			}
1331 			next = next->be_next;
1332 		}
1333 		break;
1334 	}
1335 	return totlen;
1336 }
1337 
1338 static ssize_t
1339 ober_getc(struct ber *b, u_char *c)
1340 {
1341 	return ober_read(b, c, 1);
1342 }
1343 
1344 static ssize_t
1345 ober_read(struct ber *ber, void *buf, size_t len)
1346 {
1347 	size_t	sz;
1348 
1349 	if (ber->br_rbuf == NULL)
1350 		return -1;
1351 
1352 	sz = ber->br_rend - ber->br_rptr;
1353 	if (len > sz) {
1354 		errno = ECANCELED;
1355 		return -1;	/* parser wants more data than available */
1356 	}
1357 
1358 	bcopy(ber->br_rptr, buf, len);
1359 	ber->br_rptr += len;
1360 	ber->br_offs += len;
1361 
1362 	return len;
1363 }
1364