1 /* $OpenBSD: ber.c,v 1.9 2015/02/12 00:30:38 pelikan Exp $ */
2
3 /*
4 * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
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 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, u_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, u_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 u_int i, len = 0;
160 u_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 u_int i, len = 0;
189 u_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 bool)235 ber_add_boolean(struct ber_element *prev, int bool)
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 = bool ? 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 bcopy(string0, string, 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 bcopy(v0, v, 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,u_int8_t * buf,size_t len)389 ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
390 {
391 u_int32_t v;
392 u_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 >= (u_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 bzero(o, 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 u_int8_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 bcopy(&o->bo_id, &no.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 u_int8_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 bzero(o, 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 va_end(ap);
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 bzero(parent, 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 (level < 0 || 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 u_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,u_char c)967 ber_putc(struct ber *ber, u_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 bcopy(buf, ber->br_wptr, len);
979 ber->br_wptr += len;
980 }
981
982 /*
983 * extract a BER encoded tag. There are two types, a short and long form.
984 */
985 static ssize_t
get_id(struct ber * b,unsigned long * tag,int * class,int * cstruct)986 get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
987 {
988 u_char u;
989 size_t i = 0;
990 unsigned long t = 0;
991
992 if (ber_getc(b, &u) == -1)
993 return -1;
994
995 *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
996 *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
997
998 if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
999 *tag = u & BER_TAG_MASK;
1000 return 1;
1001 }
1002
1003 do {
1004 if (ber_getc(b, &u) == -1)
1005 return -1;
1006 t = (t << 7) | (u & ~BER_TAG_MORE);
1007 i++;
1008 } while (u & BER_TAG_MORE);
1009
1010 if (i > sizeof(unsigned long)) {
1011 errno = ERANGE;
1012 return -1;
1013 }
1014
1015 *tag = t;
1016 return i + 1;
1017 }
1018
1019 /*
1020 * extract length of a ber object -- if length is unknown an error is returned.
1021 */
1022 static ssize_t
get_len(struct ber * b,ssize_t * len)1023 get_len(struct ber *b, ssize_t *len)
1024 {
1025 u_char u, n;
1026 ssize_t s, r;
1027
1028 if (ber_getc(b, &u) == -1)
1029 return -1;
1030 if ((u & BER_TAG_MORE) == 0) {
1031 /* short form */
1032 *len = u;
1033 return 1;
1034 }
1035
1036 n = u & ~BER_TAG_MORE;
1037 if (sizeof(ssize_t) < n) {
1038 errno = ERANGE;
1039 return -1;
1040 }
1041 r = n + 1;
1042
1043 for (s = 0; n > 0; n--) {
1044 if (ber_getc(b, &u) == -1)
1045 return -1;
1046 s = (s << 8) | u;
1047 }
1048
1049 if (s < 0) {
1050 /* overflow */
1051 errno = ERANGE;
1052 return -1;
1053 }
1054
1055 if (s == 0) {
1056 /* invalid encoding */
1057 errno = EINVAL;
1058 return -1;
1059 }
1060
1061 *len = s;
1062 return r;
1063 }
1064
1065 static ssize_t
ber_read_element(struct ber * ber,struct ber_element * elm)1066 ber_read_element(struct ber *ber, struct ber_element *elm)
1067 {
1068 long long val = 0;
1069 struct ber_element *next;
1070 unsigned long type;
1071 int i, class, cstruct;
1072 ssize_t len, r, totlen = 0;
1073 u_char c;
1074
1075 if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1076 return -1;
1077 DPRINTF("ber read got class %d type %lu, %s\n",
1078 class, type, cstruct ? "constructive" : "primitive");
1079 totlen += r;
1080 if ((r = get_len(ber, &len)) == -1)
1081 return -1;
1082 DPRINTF("ber read element size %zd\n", len);
1083 totlen += r + len;
1084
1085 /*
1086 * If using an external buffer and the total size of the element
1087 * is larger, then the external buffer don't bother to continue.
1088 */
1089 if (ber->fd == -1 && len > ber->br_rend - ber->br_rptr) {
1090 errno = ECANCELED;
1091 return -1;
1092 }
1093
1094 elm->be_type = type;
1095 elm->be_len = len;
1096 elm->be_class = class;
1097
1098 if (elm->be_encoding == 0) {
1099 /* try to figure out the encoding via class, type and cstruct */
1100 if (cstruct)
1101 elm->be_encoding = BER_TYPE_SEQUENCE;
1102 else if (class == BER_CLASS_UNIVERSAL)
1103 elm->be_encoding = type;
1104 else if (ber->br_application != NULL) {
1105 /*
1106 * Ask the application to map the encoding to a
1107 * universal type. For example, a SMI IpAddress
1108 * type is defined as 4 byte OCTET STRING.
1109 */
1110 elm->be_encoding = (*ber->br_application)(elm);
1111 } else
1112 /* last resort option */
1113 elm->be_encoding = BER_TYPE_NULL;
1114 }
1115
1116 switch (elm->be_encoding) {
1117 case BER_TYPE_EOC: /* End-Of-Content */
1118 break;
1119 case BER_TYPE_BOOLEAN:
1120 case BER_TYPE_INTEGER:
1121 case BER_TYPE_ENUMERATED:
1122 if (len > (ssize_t)sizeof(long long))
1123 return -1;
1124 for (i = 0; i < len; i++) {
1125 if (ber_getc(ber, &c) != 1)
1126 return -1;
1127 val <<= 8;
1128 val |= c;
1129 }
1130
1131 /* sign extend if MSB is set */
1132 if (val >> ((i - 1) * 8) & 0x80)
1133 val |= ULLONG_MAX << (i * 8);
1134 elm->be_numeric = val;
1135 break;
1136 case BER_TYPE_BITSTRING:
1137 elm->be_val = malloc(len);
1138 if (elm->be_val == NULL)
1139 return -1;
1140 elm->be_free = 1;
1141 elm->be_len = len;
1142 ber_read(ber, elm->be_val, len);
1143 break;
1144 case BER_TYPE_OCTETSTRING:
1145 case BER_TYPE_OBJECT:
1146 elm->be_val = malloc(len + 1);
1147 if (elm->be_val == NULL)
1148 return -1;
1149 elm->be_free = 1;
1150 elm->be_len = len;
1151 ber_read(ber, elm->be_val, len);
1152 ((u_char *)elm->be_val)[len] = '\0';
1153 break;
1154 case BER_TYPE_NULL: /* no payload */
1155 if (len != 0)
1156 return -1;
1157 break;
1158 case BER_TYPE_SEQUENCE:
1159 case BER_TYPE_SET:
1160 if (elm->be_sub == NULL) {
1161 if ((elm->be_sub = ber_get_element(0)) == NULL)
1162 return -1;
1163 }
1164 next = elm->be_sub;
1165 while (len > 0) {
1166 r = ber_read_element(ber, next);
1167 if (r == -1)
1168 return -1;
1169 len -= r;
1170 if (len > 0 && next->be_next == NULL) {
1171 if ((next->be_next = ber_get_element(0)) ==
1172 NULL)
1173 return -1;
1174 }
1175 next = next->be_next;
1176 }
1177 break;
1178 }
1179 return totlen;
1180 }
1181
1182 static ssize_t
ber_readbuf(struct ber * b,void * buf,size_t nbytes)1183 ber_readbuf(struct ber *b, void *buf, size_t nbytes)
1184 {
1185 size_t sz;
1186 size_t len;
1187
1188 if (b->br_rbuf == NULL)
1189 return -1;
1190
1191 sz = b->br_rend - b->br_rptr;
1192 len = MINIMUM(nbytes, sz);
1193 if (len == 0) {
1194 errno = ECANCELED;
1195 return (-1); /* end of buffer and parser wants more data */
1196 }
1197
1198 bcopy(b->br_rptr, buf, len);
1199 b->br_rptr += len;
1200
1201 return (len);
1202 }
1203
1204 void
ber_set_readbuf(struct ber * b,void * buf,size_t len)1205 ber_set_readbuf(struct ber *b, void *buf, size_t len)
1206 {
1207 b->br_rbuf = b->br_rptr = buf;
1208 b->br_rend = (u_int8_t *)buf + len;
1209 }
1210
1211 ssize_t
ber_get_writebuf(struct ber * b,void ** buf)1212 ber_get_writebuf(struct ber *b, void **buf)
1213 {
1214 if (b->br_wbuf == NULL)
1215 return -1;
1216 *buf = b->br_wbuf;
1217 return (b->br_wend - b->br_wbuf);
1218 }
1219
1220 void
ber_set_application(struct ber * b,unsigned long (* cb)(struct ber_element *))1221 ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
1222 {
1223 b->br_application = cb;
1224 }
1225
1226 void
ber_free(struct ber * b)1227 ber_free(struct ber *b)
1228 {
1229 free(b->br_wbuf);
1230 }
1231
1232 static ssize_t
ber_getc(struct ber * b,u_char * c)1233 ber_getc(struct ber *b, u_char *c)
1234 {
1235 ssize_t r;
1236 /*
1237 * XXX calling read here is wrong in many ways. The most obvious one
1238 * being that we will block till data arrives.
1239 * But for now it is _good enough_ *gulp*
1240 */
1241 if (b->fd == -1)
1242 r = ber_readbuf(b, c, 1);
1243 else
1244 r = read(b->fd, c, 1);
1245 return r;
1246 }
1247
1248 static ssize_t
ber_read(struct ber * ber,void * buf,size_t len)1249 ber_read(struct ber *ber, void *buf, size_t len)
1250 {
1251 u_char *b = buf;
1252 ssize_t r, remain = len;
1253
1254 /*
1255 * XXX calling read here is wrong in many ways. The most obvious one
1256 * being that we will block till data arrives.
1257 * But for now it is _good enough_ *gulp*
1258 */
1259
1260 while (remain > 0) {
1261 if (ber->fd == -1)
1262 r = ber_readbuf(ber, b, remain);
1263 else
1264 r = read(ber->fd, b, remain);
1265 if (r == -1) {
1266 if (errno == EINTR || errno == EAGAIN)
1267 continue;
1268 return -1;
1269 }
1270 if (r == 0)
1271 return (b - (u_char *)buf);
1272 b += r;
1273 remain -= r;
1274 }
1275 return (b - (u_char *)buf);
1276 }
1277