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