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