1 /* $OpenBSD: ber.c,v 1.26 2023/11/10 12:12:02 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 *
ober_get_element(unsigned int encoding)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
ober_set_header(struct ber_element * elm,int class,unsigned int type)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
ober_link_elements(struct ber_element * prev,struct ber_element * elm)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 *
ober_unlink_elements(struct ber_element * prev)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
ober_replace_elements(struct ber_element * prev,struct ber_element * new)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 *
ober_add_sequence(struct ber_element * prev)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 *
ober_add_set(struct ber_element * prev)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 *
ober_add_enumerated(struct ber_element * prev,long long val)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 *
ober_add_integer(struct ber_element * prev,long long val)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
ober_get_integer(struct ber_element * elm,long long * n)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
ober_get_enumerated(struct ber_element * elm,long long * n)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 *
ober_add_boolean(struct ber_element * prev,int bool)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
ober_get_boolean(struct ber_element * elm,int * b)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 *
ober_add_string(struct ber_element * prev,const char * string)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 *
ober_add_nstring(struct ber_element * prev,const char * string0,size_t len)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 *
ober_add_ostring(struct ber_element * prev,struct ber_octetstring * s)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
ober_get_string(struct ber_element * elm,char ** s)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
ober_get_nstring(struct ber_element * elm,void ** p,size_t * len)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
ober_get_ostring(struct ber_element * elm,struct ber_octetstring * s)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 *
ober_add_bitstring(struct ber_element * prev,const void * v0,size_t len)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
ober_get_bitstring(struct ber_element * elm,void ** v,size_t * len)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 *
ober_add_null(struct ber_element * prev)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
ober_get_null(struct ber_element * elm)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 *
ober_add_eoc(struct ber_element * prev)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
ober_get_eoc(struct ber_element * elm)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
ober_oid2ber(struct ber_oid * o,u_int8_t * buf,size_t len)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
ober_string2oid(const char * oidstr,struct ber_oid * o)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
ober_oid_cmp(struct ber_oid * a,struct ber_oid * b)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 *
ober_add_oid(struct ber_element * prev,struct ber_oid * o)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 *
ober_add_noid(struct ber_element * prev,struct ber_oid * o,int n)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 *
ober_add_oidstring(struct ber_element * prev,const char * oidstr)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
ober_get_oid(struct ber_element * elm,struct ber_oid * o)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 #define _MAX_SEQ 128
580 struct ber_element *
ober_printf_elements(struct ber_element * ber,char * fmt,...)581 ober_printf_elements(struct ber_element *ber, char *fmt, ...)
582 {
583 va_list ap;
584 int d, class, level = 0;
585 size_t len;
586 unsigned int type;
587 long long i;
588 char *s;
589 void *p;
590 struct ber_oid *o;
591 struct ber_element *parent[_MAX_SEQ], *e;
592 struct ber_element *origber = ber, *firstber = NULL;
593
594 memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
595
596 va_start(ap, fmt);
597
598 while (*fmt) {
599 switch (*fmt++) {
600 case 'B':
601 p = va_arg(ap, void *);
602 len = va_arg(ap, size_t);
603 if ((ber = ober_add_bitstring(ber, p, len)) == NULL)
604 goto fail;
605 break;
606 case 'b':
607 d = va_arg(ap, int);
608 if ((ber = ober_add_boolean(ber, d)) == NULL)
609 goto fail;
610 break;
611 case 'd':
612 d = va_arg(ap, int);
613 if ((ber = ober_add_integer(ber, d)) == NULL)
614 goto fail;
615 break;
616 case 'e':
617 e = va_arg(ap, struct ber_element *);
618 ober_link_elements(ber, e);
619 break;
620 case 'E':
621 i = va_arg(ap, long long);
622 if ((ber = ober_add_enumerated(ber, i)) == NULL)
623 goto fail;
624 break;
625 case 'i':
626 i = va_arg(ap, long long);
627 if ((ber = ober_add_integer(ber, i)) == NULL)
628 goto fail;
629 break;
630 case 'O':
631 o = va_arg(ap, struct ber_oid *);
632 if ((ber = ober_add_oid(ber, o)) == NULL)
633 goto fail;
634 break;
635 case 'o':
636 s = va_arg(ap, char *);
637 if ((ber = ober_add_oidstring(ber, s)) == NULL)
638 goto fail;
639 break;
640 case 's':
641 s = va_arg(ap, char *);
642 if ((ber = ober_add_string(ber, s)) == NULL)
643 goto fail;
644 break;
645 case 't':
646 class = va_arg(ap, int);
647 type = va_arg(ap, unsigned int);
648 ober_set_header(ber, class, type);
649 break;
650 case 'x':
651 s = va_arg(ap, char *);
652 len = va_arg(ap, size_t);
653 if ((ber = ober_add_nstring(ber, s, len)) == NULL)
654 goto fail;
655 break;
656 case '0':
657 if ((ber = ober_add_null(ber)) == NULL)
658 goto fail;
659 break;
660 case '{':
661 if (level >= _MAX_SEQ-1)
662 goto fail;
663 if ((ber= ober_add_sequence(ber)) == NULL)
664 goto fail;
665 parent[level++] = ber;
666 break;
667 case '(':
668 if (level >= _MAX_SEQ-1)
669 goto fail;
670 if ((ber = ober_add_set(ber)) == NULL)
671 goto fail;
672 parent[level++] = ber;
673 break;
674 case '}':
675 case ')':
676 if (level <= 0 || parent[level - 1] == NULL)
677 goto fail;
678 ber = parent[--level];
679 break;
680 case '.':
681 if ((e = ober_add_eoc(ber)) == NULL)
682 goto fail;
683 ber = e;
684 break;
685 default:
686 break;
687 }
688 if (firstber == NULL)
689 firstber = ber;
690 }
691 va_end(ap);
692
693 return (ber);
694 fail:
695 if (origber != NULL)
696 ober_unlink_elements(origber);
697 ober_free_elements(firstber);
698 return (NULL);
699 }
700
701 int
ober_scanf_elements(struct ber_element * ber,char * fmt,...)702 ober_scanf_elements(struct ber_element *ber, char *fmt, ...)
703 {
704 va_list ap;
705 int *d, level = -1;
706 unsigned int *t;
707 long long *i, l;
708 void **ptr;
709 size_t *len, ret = 0, n = strlen(fmt);
710 char **s;
711 off_t *pos;
712 struct ber_oid *o;
713 struct ber_element *parent[_MAX_SEQ], **e;
714
715 memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
716
717 va_start(ap, fmt);
718 while (*fmt) {
719 if (ber == NULL && *fmt != '$' && *fmt != '}' && *fmt != ')')
720 goto fail;
721 switch (*fmt++) {
722 case '$':
723 if (ber != NULL)
724 goto fail;
725 ret++;
726 continue;
727 case 'B':
728 ptr = va_arg(ap, void **);
729 len = va_arg(ap, size_t *);
730 if (ober_get_bitstring(ber, ptr, len) == -1)
731 goto fail;
732 ret++;
733 break;
734 case 'b':
735 d = va_arg(ap, int *);
736 if (ober_get_boolean(ber, d) == -1)
737 goto fail;
738 ret++;
739 break;
740 case 'd':
741 d = va_arg(ap, int *);
742 if (ober_get_integer(ber, &l) == -1)
743 goto fail;
744 if (d != NULL)
745 *d = l;
746 ret++;
747 break;
748 case 'e':
749 e = va_arg(ap, struct ber_element **);
750 *e = ber;
751 ret++;
752 continue;
753 case 'E':
754 i = va_arg(ap, long long *);
755 if (ober_get_enumerated(ber, i) == -1)
756 goto fail;
757 ret++;
758 break;
759 case 'i':
760 i = va_arg(ap, long long *);
761 if (ober_get_integer(ber, i) == -1)
762 goto fail;
763 ret++;
764 break;
765 case 'o':
766 o = va_arg(ap, struct ber_oid *);
767 if (ober_get_oid(ber, o) == -1)
768 goto fail;
769 ret++;
770 break;
771 case 'S':
772 ret++;
773 break;
774 case 's':
775 s = va_arg(ap, char **);
776 if (ober_get_string(ber, s) == -1)
777 goto fail;
778 ret++;
779 break;
780 case 't':
781 d = va_arg(ap, int *);
782 t = va_arg(ap, unsigned int *);
783 if (d != NULL)
784 *d = ber->be_class;
785 if (t != NULL)
786 *t = ber->be_type;
787 ret++;
788 continue;
789 case 'x':
790 ptr = va_arg(ap, void **);
791 len = va_arg(ap, size_t *);
792 if (ober_get_nstring(ber, ptr, len) == -1)
793 goto fail;
794 ret++;
795 break;
796 case '0':
797 if (ber->be_encoding != BER_TYPE_NULL)
798 goto fail;
799 ret++;
800 break;
801 case '.':
802 if (ber->be_encoding != BER_TYPE_EOC)
803 goto fail;
804 ret++;
805 break;
806 case 'p':
807 pos = va_arg(ap, off_t *);
808 *pos = ober_getpos(ber);
809 ret++;
810 continue;
811 case '{':
812 case '(':
813 if (ber->be_encoding != BER_TYPE_SEQUENCE &&
814 ber->be_encoding != BER_TYPE_SET)
815 goto fail;
816 if (level >= _MAX_SEQ-1)
817 goto fail;
818 parent[++level] = ber;
819 ber = ber->be_sub;
820 ret++;
821 continue;
822 case '}':
823 case ')':
824 if (level < 0 || parent[level] == NULL)
825 goto fail;
826 ber = parent[level--];
827 ret++;
828 break;
829 default:
830 goto fail;
831 }
832
833 ber = ber->be_next;
834 }
835 va_end(ap);
836 return (ret == n ? 0 : -1);
837
838 fail:
839 va_end(ap);
840 return (-1);
841
842 }
843
844 ssize_t
ober_get_writebuf(struct ber * b,void ** buf)845 ober_get_writebuf(struct ber *b, void **buf)
846 {
847 if (b->br_wbuf == NULL)
848 return -1;
849 *buf = b->br_wbuf;
850 return (b->br_wend - b->br_wbuf);
851 }
852
853 /*
854 * write ber elements to the write buffer
855 *
856 * params:
857 * ber holds the destination write buffer byte stream
858 * root fully populated element tree
859 *
860 * returns:
861 * >=0 number of bytes written
862 * -1 on failure and sets errno
863 */
864 ssize_t
ober_write_elements(struct ber * ber,struct ber_element * root)865 ober_write_elements(struct ber *ber, struct ber_element *root)
866 {
867 size_t len;
868
869 /* calculate length because only the definite form is required */
870 len = ober_calc_len(root);
871 DPRINTF("write ber element of %zd bytes length\n", len);
872
873 if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
874 free(ber->br_wbuf);
875 ber->br_wbuf = NULL;
876 }
877 if (ber->br_wbuf == NULL) {
878 if ((ber->br_wbuf = malloc(len)) == NULL)
879 return -1;
880 ber->br_wend = ber->br_wbuf + len;
881 }
882
883 /* reset write pointer */
884 ber->br_wptr = ber->br_wbuf;
885
886 if (ober_dump_element(ber, root) == -1)
887 return -1;
888
889 return (len);
890 }
891
892 void
ober_set_readbuf(struct ber * b,void * buf,size_t len)893 ober_set_readbuf(struct ber *b, void *buf, size_t len)
894 {
895 b->br_rbuf = b->br_rptr = buf;
896 b->br_rend = (u_int8_t *)buf + len;
897 }
898
899 /*
900 * read ber elements from the read buffer
901 *
902 * params:
903 * ber holds a fully populated read buffer byte stream
904 * root if NULL, build up an element tree from what we receive on
905 * the wire. If not null, use the specified encoding for the
906 * elements received.
907 *
908 * returns:
909 * !=NULL, elements read and store in the ber_element tree
910 * NULL, type mismatch or read error
911 */
912 struct ber_element *
ober_read_elements(struct ber * ber,struct ber_element * elm)913 ober_read_elements(struct ber *ber, struct ber_element *elm)
914 {
915 struct ber_element *root = elm;
916
917 if (root == NULL) {
918 if ((root = ober_get_element(0)) == NULL)
919 return NULL;
920 }
921
922 DPRINTF("read ber elements, root %p\n", root);
923
924 if (ober_read_element(ber, root) == -1) {
925 /* Cleanup if root was allocated by us */
926 if (elm == NULL)
927 ober_free_elements(root);
928 return NULL;
929 }
930
931 return root;
932 }
933
934 off_t
ober_getpos(struct ber_element * elm)935 ober_getpos(struct ber_element *elm)
936 {
937 return elm->be_offs;
938 }
939
940 struct ber_element *
ober_dup(struct ber_element * orig)941 ober_dup(struct ber_element *orig)
942 {
943 struct ber_element *new;
944
945 if ((new = malloc(sizeof(*new))) == NULL)
946 return NULL;
947 memcpy(new, orig, sizeof(*new));
948 new->be_next = NULL;
949 new->be_sub = NULL;
950
951 if (orig->be_next != NULL) {
952 if ((new->be_next = ober_dup(orig->be_next)) == NULL)
953 goto fail;
954 }
955 if (orig->be_encoding == BER_TYPE_SEQUENCE ||
956 orig->be_encoding == BER_TYPE_SET) {
957 if (orig->be_sub != NULL) {
958 if ((new->be_sub = ober_dup(orig->be_sub)) == NULL)
959 goto fail;
960 }
961 } else if (orig->be_encoding == BER_TYPE_OCTETSTRING ||
962 orig->be_encoding == BER_TYPE_BITSTRING ||
963 orig->be_encoding == BER_TYPE_OBJECT) {
964 if (orig->be_val != NULL) {
965 if ((new->be_val = malloc(orig->be_len)) == NULL)
966 goto fail;
967 memcpy(new->be_val, orig->be_val, orig->be_len);
968 }
969 } else
970 new->be_numeric = orig->be_numeric;
971 return new;
972 fail:
973 ober_free_elements(new);
974 return NULL;
975 }
976
977 void
ober_free_element(struct ber_element * root)978 ober_free_element(struct ber_element *root)
979 {
980 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
981 root->be_encoding == BER_TYPE_SET))
982 ober_free_elements(root->be_sub);
983 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
984 root->be_encoding == BER_TYPE_BITSTRING ||
985 root->be_encoding == BER_TYPE_OBJECT))
986 free(root->be_val);
987 free(root);
988 }
989
990 void
ober_free_elements(struct ber_element * root)991 ober_free_elements(struct ber_element *root)
992 {
993 if (root == NULL)
994 return;
995 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
996 root->be_encoding == BER_TYPE_SET))
997 ober_free_elements(root->be_sub);
998 if (root->be_next)
999 ober_free_elements(root->be_next);
1000 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
1001 root->be_encoding == BER_TYPE_BITSTRING ||
1002 root->be_encoding == BER_TYPE_OBJECT))
1003 free(root->be_val);
1004 free(root);
1005 }
1006
1007 size_t
ober_calc_len(struct ber_element * root)1008 ober_calc_len(struct ber_element *root)
1009 {
1010 unsigned int t;
1011 size_t s;
1012 size_t size = 2; /* minimum 1 byte head and 1 byte size */
1013
1014 /* calculate the real length of a sequence or set */
1015 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
1016 root->be_encoding == BER_TYPE_SET))
1017 root->be_len = ober_calc_len(root->be_sub);
1018
1019 /* fix header length for extended types */
1020 if (root->be_type > BER_TYPE_SINGLE_MAX)
1021 for (t = root->be_type; t > 0; t >>= 7)
1022 size++;
1023 if (root->be_len >= BER_TAG_MORE)
1024 for (s = root->be_len; s > 0; s >>= 8)
1025 size++;
1026
1027 /* calculate the length of the following elements */
1028 if (root->be_next)
1029 size += ober_calc_len(root->be_next);
1030
1031 /* This is an empty element, do not use a minimal size */
1032 if (root->be_class == BER_CLASS_UNIVERSAL &&
1033 root->be_type == BER_TYPE_EOC && root->be_len == 0)
1034 return (0);
1035
1036 return (root->be_len + size);
1037 }
1038
1039 void
ober_set_application(struct ber * b,unsigned int (* cb)(struct ber_element *))1040 ober_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
1041 {
1042 b->br_application = cb;
1043 }
1044
1045 void
ober_set_writecallback(struct ber_element * elm,void (* cb)(void *,size_t),void * arg)1046 ober_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
1047 void *arg)
1048 {
1049 elm->be_cb = cb;
1050 elm->be_cbarg = arg;
1051 }
1052
1053 void
ober_free(struct ber * b)1054 ober_free(struct ber *b)
1055 {
1056 free(b->br_wbuf);
1057 }
1058
1059 /*
1060 * internal functions
1061 */
1062
1063 static int
ober_dump_element(struct ber * ber,struct ber_element * root)1064 ober_dump_element(struct ber *ber, struct ber_element *root)
1065 {
1066 unsigned long long l;
1067 int i;
1068 uint8_t u;
1069
1070 ober_dump_header(ber, root);
1071 if (root->be_cb)
1072 root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1073
1074 switch (root->be_encoding) {
1075 case BER_TYPE_BOOLEAN:
1076 case BER_TYPE_INTEGER:
1077 case BER_TYPE_ENUMERATED:
1078 l = (unsigned long long)root->be_numeric;
1079 for (i = root->be_len; i > 0; i--) {
1080 u = (l >> ((i - 1) * 8)) & 0xff;
1081 ober_putc(ber, u);
1082 }
1083 break;
1084 case BER_TYPE_BITSTRING:
1085 case BER_TYPE_OCTETSTRING:
1086 case BER_TYPE_OBJECT:
1087 ober_write(ber, root->be_val, root->be_len);
1088 break;
1089 case BER_TYPE_NULL: /* no payload */
1090 case BER_TYPE_EOC:
1091 break;
1092 case BER_TYPE_SEQUENCE:
1093 case BER_TYPE_SET:
1094 if (root->be_sub && ober_dump_element(ber, root->be_sub) == -1)
1095 return -1;
1096 break;
1097 }
1098
1099 if (root->be_next == NULL)
1100 return 0;
1101 return ober_dump_element(ber, root->be_next);
1102 }
1103
1104 static void
ober_dump_header(struct ber * ber,struct ber_element * root)1105 ober_dump_header(struct ber *ber, struct ber_element *root)
1106 {
1107 u_char id = 0, t, buf[5];
1108 unsigned int type;
1109 size_t size;
1110
1111 /* class universal, type encoding depending on type value */
1112 /* length encoding */
1113 if (root->be_type <= BER_TYPE_SINGLE_MAX) {
1114 id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
1115 if (root->be_encoding == BER_TYPE_SEQUENCE ||
1116 root->be_encoding == BER_TYPE_SET)
1117 id |= BER_TYPE_CONSTRUCTED;
1118
1119 ober_putc(ber, id);
1120 } else {
1121 id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
1122 if (root->be_encoding == BER_TYPE_SEQUENCE ||
1123 root->be_encoding == BER_TYPE_SET)
1124 id |= BER_TYPE_CONSTRUCTED;
1125
1126 ober_putc(ber, id);
1127
1128 for (t = 0, type = root->be_type; type > 0; type >>= 7)
1129 buf[t++] = type & ~BER_TAG_MORE;
1130
1131 while (t-- > 0) {
1132 if (t > 0)
1133 buf[t] |= BER_TAG_MORE;
1134 ober_putc(ber, buf[t]);
1135 }
1136 }
1137
1138 if (root->be_len < BER_TAG_MORE) {
1139 /* short form */
1140 ober_putc(ber, root->be_len);
1141 } else {
1142 for (t = 0, size = root->be_len; size > 0; size >>= 8)
1143 buf[t++] = size & 0xff;
1144
1145 ober_putc(ber, t | BER_TAG_MORE);
1146
1147 while (t > 0)
1148 ober_putc(ber, buf[--t]);
1149 }
1150 }
1151
1152 static void
ober_putc(struct ber * ber,u_char c)1153 ober_putc(struct ber *ber, u_char c)
1154 {
1155 if (ber->br_wptr + 1 <= ber->br_wend)
1156 *ber->br_wptr = c;
1157 ber->br_wptr++;
1158 }
1159
1160 static void
ober_write(struct ber * ber,void * buf,size_t len)1161 ober_write(struct ber *ber, void *buf, size_t len)
1162 {
1163 if (ber->br_wptr + len <= ber->br_wend)
1164 bcopy(buf, ber->br_wptr, len);
1165 ber->br_wptr += len;
1166 }
1167
1168 /*
1169 * extract a BER encoded tag. There are two types, a short and long form.
1170 */
1171 static ssize_t
get_id(struct ber * b,unsigned int * tag,int * class,int * cstruct)1172 get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1173 {
1174 u_char u;
1175 size_t i = 0;
1176 unsigned int t = 0;
1177
1178 if (ober_getc(b, &u) == -1)
1179 return -1;
1180
1181 *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1182 *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1183
1184 if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1185 *tag = u & BER_TAG_MASK;
1186 return 1;
1187 }
1188
1189 do {
1190 if (ober_getc(b, &u) == -1)
1191 return -1;
1192
1193 /* enforce minimal number of octets for tag > 30 */
1194 if (i == 0 && (u & ~BER_TAG_MORE) == 0) {
1195 errno = EINVAL;
1196 return -1;
1197 }
1198
1199 t = (t << 7) | (u & ~BER_TAG_MORE);
1200 i++;
1201 if (i > sizeof(unsigned int)) {
1202 errno = ERANGE;
1203 return -1;
1204 }
1205 } while (u & BER_TAG_MORE);
1206
1207 *tag = t;
1208 return i + 1;
1209 }
1210
1211 /*
1212 * extract length of a ber object -- if length is unknown an error is returned.
1213 */
1214 static ssize_t
get_len(struct ber * b,ssize_t * len)1215 get_len(struct ber *b, ssize_t *len)
1216 {
1217 u_char u, n;
1218 ssize_t s, r;
1219
1220 if (ober_getc(b, &u) == -1)
1221 return -1;
1222 if ((u & BER_TAG_MORE) == 0) {
1223 /* short form */
1224 *len = u;
1225 return 1;
1226 }
1227
1228 if (u == 0x80) {
1229 /* Indefinite length not supported. */
1230 errno = EINVAL;
1231 return -1;
1232 }
1233
1234 if (u == 0xff) {
1235 /* Reserved for future use. */
1236 errno = EINVAL;
1237 return -1;
1238 }
1239
1240 n = u & ~BER_TAG_MORE;
1241 /*
1242 * Limit to a decent size that works on all of our architectures.
1243 */
1244 if (sizeof(int32_t) < n) {
1245 errno = ERANGE;
1246 return -1;
1247 }
1248 r = n + 1;
1249
1250 for (s = 0; n > 0; n--) {
1251 if (ober_getc(b, &u) == -1)
1252 return -1;
1253 s = (s << 8) | u;
1254 }
1255
1256 if (s < 0) {
1257 /* overflow */
1258 errno = ERANGE;
1259 return -1;
1260 }
1261
1262 *len = s;
1263 return r;
1264 }
1265
1266 static ssize_t
ober_read_element(struct ber * ber,struct ber_element * elm)1267 ober_read_element(struct ber *ber, struct ber_element *elm)
1268 {
1269 long long val = 0;
1270 struct ber_element *next;
1271 unsigned int type;
1272 int i, class, cstruct, elements = 0;
1273 ssize_t len, r, totlen = 0;
1274 u_char c, last = 0;
1275
1276 if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1277 return -1;
1278 DPRINTF("ber read got class %d type %u, %s\n",
1279 class, type, cstruct ? "constructed" : "primitive");
1280 totlen += r;
1281 if ((r = get_len(ber, &len)) == -1)
1282 return -1;
1283 DPRINTF("ber read element size %zd\n", len);
1284 totlen += r + len;
1285
1286 /* The encoding of boolean, integer, enumerated, and null values
1287 * must be primitive. */
1288 if (class == BER_CLASS_UNIVERSAL)
1289 if (type == BER_TYPE_BOOLEAN ||
1290 type == BER_TYPE_INTEGER ||
1291 type == BER_TYPE_ENUMERATED ||
1292 type == BER_TYPE_NULL)
1293 if (cstruct) {
1294 errno = EINVAL;
1295 return -1;
1296 }
1297
1298 /* If the total size of the element is larger than the buffer
1299 * don't bother to continue. */
1300 if (len > ber->br_rend - ber->br_rptr) {
1301 errno = ECANCELED;
1302 return -1;
1303 }
1304
1305 elm->be_type = type;
1306 elm->be_len = len;
1307 elm->be_offs = ber->br_offs; /* element position within stream */
1308 elm->be_class = class;
1309
1310 if (elm->be_encoding == 0) {
1311 /* try to figure out the encoding via class, type and cstruct */
1312 if (cstruct)
1313 elm->be_encoding = BER_TYPE_SEQUENCE;
1314 else if (class == BER_CLASS_UNIVERSAL)
1315 elm->be_encoding = type;
1316 else if (ber->br_application != NULL) {
1317 /*
1318 * Ask the application to map the encoding to a
1319 * universal type. For example, a SMI IpAddress
1320 * type is defined as 4 byte OCTET STRING.
1321 */
1322 elm->be_encoding = (*ber->br_application)(elm);
1323 } else
1324 /* last resort option */
1325 elm->be_encoding = BER_TYPE_NULL;
1326 }
1327
1328 switch (elm->be_encoding) {
1329 case BER_TYPE_EOC: /* End-Of-Content */
1330 break;
1331 case BER_TYPE_BOOLEAN:
1332 if (len != 1) {
1333 errno = EINVAL;
1334 return -1;
1335 }
1336 case BER_TYPE_INTEGER:
1337 case BER_TYPE_ENUMERATED:
1338 if (len < 1) {
1339 errno = EINVAL;
1340 return -1;
1341 }
1342 if (len > (ssize_t)sizeof(long long)) {
1343 errno = ERANGE;
1344 return -1;
1345 }
1346 for (i = 0; i < len; i++) {
1347 if (ober_getc(ber, &c) != 1)
1348 return -1;
1349
1350 /* smallest number of contents octets only */
1351 if ((i == 1 && last == 0 && (c & 0x80) == 0) ||
1352 (i == 1 && last == 0xff && (c & 0x80) != 0)) {
1353 errno = EINVAL;
1354 return -1;
1355 }
1356
1357 val <<= 8;
1358 val |= c;
1359 last = c;
1360 }
1361
1362 /* sign extend if MSB is set */
1363 if (len < (ssize_t)sizeof(long long) &&
1364 (val >> ((len - 1) * 8) & 0x80))
1365 val |= ULLONG_MAX << (len * 8);
1366 elm->be_numeric = val;
1367 break;
1368 case BER_TYPE_BITSTRING:
1369 elm->be_val = malloc(len);
1370 if (elm->be_val == NULL)
1371 return -1;
1372 elm->be_free = 1;
1373 elm->be_len = len;
1374 ober_read(ber, elm->be_val, len);
1375 break;
1376 case BER_TYPE_OCTETSTRING:
1377 case BER_TYPE_OBJECT:
1378 elm->be_val = malloc(len + 1);
1379 if (elm->be_val == NULL)
1380 return -1;
1381 elm->be_free = 1;
1382 elm->be_len = len;
1383 ober_read(ber, elm->be_val, len);
1384 ((u_char *)elm->be_val)[len] = '\0';
1385 break;
1386 case BER_TYPE_NULL: /* no payload */
1387 if (len != 0) {
1388 errno = EINVAL;
1389 return -1;
1390 }
1391 break;
1392 case BER_TYPE_SEQUENCE:
1393 case BER_TYPE_SET:
1394 if (len > 0 && elm->be_sub == NULL) {
1395 if ((elm->be_sub = ober_get_element(0)) == NULL)
1396 return -1;
1397 }
1398 next = elm->be_sub;
1399 while (len > 0) {
1400 /*
1401 * Prevent stack overflow from excessive recursion
1402 * depth in ober_free_elements().
1403 */
1404 if (elements >= BER_MAX_SEQ_ELEMENTS) {
1405 errno = ERANGE;
1406 return -1;
1407 }
1408 r = ober_read_element(ber, next);
1409 if (r == -1) {
1410 /* sub-element overflows sequence/set */
1411 if (errno == ECANCELED)
1412 errno = EINVAL;
1413 return -1;
1414 }
1415 if (r > len) {
1416 errno = EINVAL;
1417 return -1;
1418 }
1419 elements++;
1420 len -= r;
1421 if (len > 0 && next->be_next == NULL) {
1422 next->be_next = ober_get_element(0);
1423 if (next->be_next == NULL)
1424 return -1;
1425 }
1426 next = next->be_next;
1427 }
1428 break;
1429 }
1430 return totlen;
1431 }
1432
1433 static ssize_t
ober_getc(struct ber * b,u_char * c)1434 ober_getc(struct ber *b, u_char *c)
1435 {
1436 return ober_read(b, c, 1);
1437 }
1438
1439 static ssize_t
ober_read(struct ber * ber,void * buf,size_t len)1440 ober_read(struct ber *ber, void *buf, size_t len)
1441 {
1442 size_t sz;
1443
1444 if (ber->br_rbuf == NULL) {
1445 errno = ENOBUFS;
1446 return -1;
1447 }
1448
1449 sz = ber->br_rend - ber->br_rptr;
1450 if (len > sz) {
1451 errno = ECANCELED;
1452 return -1; /* parser wants more data than available */
1453 }
1454
1455 bcopy(ber->br_rptr, buf, len);
1456 ber->br_rptr += len;
1457 ber->br_offs += len;
1458
1459 return len;
1460 }
1461