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