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