1 /* $OpenBSD: ber.c,v 1.9 2019/06/01 19:40:05 rob Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 23 #include <errno.h> 24 #include <limits.h> 25 #include <stdlib.h> 26 #include <err.h> /* XXX for debug output */ 27 #include <stdio.h> /* XXX for debug output */ 28 #include <string.h> 29 #include <unistd.h> 30 #include <stdarg.h> 31 32 #include "ber.h" 33 34 #define BER_TYPE_CONSTRUCTED 0x20 /* otherwise primitive */ 35 #define BER_TYPE_SINGLE_MAX 30 36 #define BER_TAG_MASK 0x1f 37 #define BER_TAG_MORE 0x80 /* more subsequent octets */ 38 #define BER_TAG_TYPE_MASK 0x7f 39 #define BER_CLASS_SHIFT 6 40 41 static int ber_dump_element(struct ber *ber, struct ber_element *root); 42 static void ber_dump_header(struct ber *ber, struct ber_element *root); 43 static void ber_putc(struct ber *ber, u_char c); 44 static void ber_write(struct ber *ber, void *buf, size_t len); 45 static ssize_t get_id(struct ber *b, unsigned int *tag, int *class, 46 int *cstruct); 47 static ssize_t get_len(struct ber *b, ssize_t *len); 48 static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm); 49 static ssize_t ber_getc(struct ber *b, u_char *c); 50 static 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 58 struct ber_element * 59 ber_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 72 void 73 ber_set_header(struct ber_element *elm, int class, unsigned int type) 74 { 75 elm->be_class = class & BER_CLASS_MASK; 76 if (type == BER_TYPE_DEFAULT) 77 type = elm->be_encoding; 78 elm->be_type = type; 79 } 80 81 void 82 ber_link_elements(struct ber_element *prev, struct ber_element *elm) 83 { 84 if (prev != NULL) { 85 if ((prev->be_encoding == BER_TYPE_SEQUENCE || 86 prev->be_encoding == BER_TYPE_SET) && 87 prev->be_sub == NULL) 88 prev->be_sub = elm; 89 else 90 prev->be_next = elm; 91 } 92 } 93 94 struct ber_element * 95 ber_unlink_elements(struct ber_element *prev) 96 { 97 struct ber_element *elm; 98 99 if ((prev->be_encoding == BER_TYPE_SEQUENCE || 100 prev->be_encoding == BER_TYPE_SET) && 101 prev->be_sub != NULL) { 102 elm = prev->be_sub; 103 prev->be_sub = NULL; 104 } else { 105 elm = prev->be_next; 106 prev->be_next = NULL; 107 } 108 109 return (elm); 110 } 111 112 void 113 ber_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 126 struct ber_element * 127 ber_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 139 struct ber_element * 140 ber_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 152 struct ber_element * 153 ber_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 181 struct ber_element * 182 ber_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 210 int 211 ber_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 220 int 221 ber_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 230 struct ber_element * 231 ber_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 246 int 247 ber_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 256 struct ber_element * 257 ber_add_string(struct ber_element *prev, const char *string) 258 { 259 return ber_add_nstring(prev, string, strlen(string)); 260 } 261 262 struct ber_element * 263 ber_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 285 struct ber_element * 286 ber_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 291 int 292 ber_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 306 int 307 ber_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 317 int 318 ber_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 328 struct ber_element * 329 ber_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 351 int 352 ber_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 362 struct ber_element * 363 ber_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 375 int 376 ber_get_null(struct ber_element *elm) 377 { 378 if (elm->be_encoding != BER_TYPE_NULL) 379 return -1; 380 381 return 0; 382 } 383 384 struct ber_element * 385 ber_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 397 int 398 ber_get_eoc(struct ber_element *elm) 399 { 400 if (elm->be_encoding != BER_TYPE_EOC) 401 return -1; 402 403 return 0; 404 } 405 406 size_t 407 ber_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 433 int 434 ber_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 455 int 456 ber_oid_cmp(struct ber_oid *a, struct ber_oid *b) 457 { 458 size_t i; 459 for (i = 0; i < BER_MAX_OID_LEN; i++) { 460 if (a->bo_id[i] != 0) { 461 if (a->bo_id[i] == b->bo_id[i]) 462 continue; 463 else if (a->bo_id[i] < b->bo_id[i]) { 464 /* b is a successor of a */ 465 return (1); 466 } else { 467 /* b is a predecessor of a */ 468 return (-1); 469 } 470 } else if (b->bo_id[i] != 0) { 471 /* b is larger, but a child of a */ 472 return (2); 473 } else 474 break; 475 } 476 477 /* b and a are identical */ 478 return (0); 479 } 480 481 struct ber_element * 482 ber_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 513 struct ber_element * 514 ber_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 526 struct ber_element * 527 ber_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 537 int 538 ber_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 if (!buf[i]) 550 return (-1); 551 552 memset(o, 0, sizeof(*o)); 553 o->bo_id[j++] = buf[i] / 40; 554 o->bo_id[j++] = buf[i++] % 40; 555 for (; i < len && j < BER_MAX_OID_LEN; i++) { 556 o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80); 557 if (buf[i] & 0x80) 558 continue; 559 j++; 560 } 561 o->bo_n = j; 562 563 return (0); 564 } 565 566 struct ber_element * 567 ber_printf_elements(struct ber_element *ber, char *fmt, ...) 568 { 569 va_list ap; 570 int d, class; 571 size_t len; 572 unsigned int type; 573 long long i; 574 char *s; 575 void *p; 576 struct ber_oid *o; 577 struct ber_element *sub = ber, *e; 578 579 va_start(ap, fmt); 580 while (*fmt) { 581 switch (*fmt++) { 582 case 'B': 583 p = va_arg(ap, void *); 584 len = va_arg(ap, size_t); 585 if ((ber = ber_add_bitstring(ber, p, len)) == NULL) 586 goto fail; 587 break; 588 case 'b': 589 d = va_arg(ap, int); 590 if ((ber = ber_add_boolean(ber, d)) == NULL) 591 goto fail; 592 break; 593 case 'd': 594 d = va_arg(ap, int); 595 if ((ber = ber_add_integer(ber, d)) == NULL) 596 goto fail; 597 break; 598 case 'e': 599 e = va_arg(ap, struct ber_element *); 600 ber_link_elements(ber, e); 601 break; 602 case 'E': 603 i = va_arg(ap, long long); 604 if ((ber = ber_add_enumerated(ber, i)) == NULL) 605 goto fail; 606 break; 607 case 'i': 608 i = va_arg(ap, long long); 609 if ((ber = ber_add_integer(ber, i)) == NULL) 610 goto fail; 611 break; 612 case 'O': 613 o = va_arg(ap, struct ber_oid *); 614 if ((ber = ber_add_oid(ber, o)) == NULL) 615 goto fail; 616 break; 617 case 'o': 618 s = va_arg(ap, char *); 619 if ((ber = ber_add_oidstring(ber, s)) == NULL) 620 goto fail; 621 break; 622 case 's': 623 s = va_arg(ap, char *); 624 if ((ber = ber_add_string(ber, s)) == NULL) 625 goto fail; 626 break; 627 case 't': 628 class = va_arg(ap, int); 629 type = va_arg(ap, unsigned int); 630 ber_set_header(ber, class, type); 631 break; 632 case 'x': 633 s = va_arg(ap, char *); 634 len = va_arg(ap, size_t); 635 if ((ber = ber_add_nstring(ber, s, len)) == NULL) 636 goto fail; 637 break; 638 case '0': 639 if ((ber = ber_add_null(ber)) == NULL) 640 goto fail; 641 break; 642 case '{': 643 if ((ber = sub = ber_add_sequence(ber)) == NULL) 644 goto fail; 645 break; 646 case '(': 647 if ((ber = sub = ber_add_set(ber)) == NULL) 648 goto fail; 649 break; 650 case '}': 651 case ')': 652 ber = sub; 653 break; 654 case '.': 655 if ((e = ber_add_eoc(ber)) == NULL) 656 goto fail; 657 ber = e; 658 break; 659 default: 660 break; 661 } 662 } 663 va_end(ap); 664 665 return (ber); 666 fail: 667 ber_free_elements(ber); 668 return (NULL); 669 } 670 671 int 672 ber_scanf_elements(struct ber_element *ber, char *fmt, ...) 673 { 674 #define _MAX_SEQ 128 675 va_list ap; 676 int *d, level = -1; 677 unsigned int *t; 678 long long *i, l; 679 void **ptr; 680 size_t *len, ret = 0, n = strlen(fmt); 681 char **s; 682 off_t *pos; 683 struct ber_oid *o; 684 struct ber_element *parent[_MAX_SEQ], **e; 685 686 memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ); 687 688 va_start(ap, fmt); 689 while (*fmt) { 690 switch (*fmt++) { 691 case 'B': 692 ptr = va_arg(ap, void **); 693 len = va_arg(ap, size_t *); 694 if (ber_get_bitstring(ber, ptr, len) == -1) 695 goto fail; 696 ret++; 697 break; 698 case 'b': 699 d = va_arg(ap, int *); 700 if (ber_get_boolean(ber, d) == -1) 701 goto fail; 702 ret++; 703 break; 704 case 'd': 705 d = va_arg(ap, int *); 706 if (ber_get_integer(ber, &l) == -1) 707 goto fail; 708 *d = l; 709 ret++; 710 break; 711 case 'e': 712 e = va_arg(ap, struct ber_element **); 713 *e = ber; 714 ret++; 715 continue; 716 case 'E': 717 i = va_arg(ap, long long *); 718 if (ber_get_enumerated(ber, i) == -1) 719 goto fail; 720 ret++; 721 break; 722 case 'i': 723 i = va_arg(ap, long long *); 724 if (ber_get_integer(ber, i) == -1) 725 goto fail; 726 ret++; 727 break; 728 case 'o': 729 o = va_arg(ap, struct ber_oid *); 730 if (ber_get_oid(ber, o) == -1) 731 goto fail; 732 ret++; 733 break; 734 case 'S': 735 ret++; 736 break; 737 case 's': 738 s = va_arg(ap, char **); 739 if (ber_get_string(ber, s) == -1) 740 goto fail; 741 ret++; 742 break; 743 case 't': 744 d = va_arg(ap, int *); 745 t = va_arg(ap, unsigned int *); 746 *d = ber->be_class; 747 *t = ber->be_type; 748 ret++; 749 continue; 750 case 'x': 751 ptr = va_arg(ap, void **); 752 len = va_arg(ap, size_t *); 753 if (ber_get_nstring(ber, ptr, len) == -1) 754 goto fail; 755 ret++; 756 break; 757 case '0': 758 if (ber->be_encoding != BER_TYPE_NULL) 759 goto fail; 760 ret++; 761 break; 762 case '.': 763 if (ber->be_encoding != BER_TYPE_EOC) 764 goto fail; 765 ret++; 766 break; 767 case 'p': 768 pos = va_arg(ap, off_t *); 769 *pos = ber_getpos(ber); 770 ret++; 771 continue; 772 case '{': 773 case '(': 774 if (ber->be_encoding != BER_TYPE_SEQUENCE && 775 ber->be_encoding != BER_TYPE_SET) 776 goto fail; 777 if (ber->be_sub == NULL || level >= _MAX_SEQ-1) 778 goto fail; 779 parent[++level] = ber; 780 ber = ber->be_sub; 781 ret++; 782 continue; 783 case '}': 784 case ')': 785 if (parent[level] == NULL) 786 goto fail; 787 ber = parent[level--]; 788 ret++; 789 break; 790 default: 791 goto fail; 792 } 793 794 if (ber->be_next == NULL) 795 continue; 796 ber = ber->be_next; 797 } 798 va_end(ap); 799 return (ret == n ? 0 : -1); 800 801 fail: 802 va_end(ap); 803 return (-1); 804 805 } 806 807 ssize_t 808 ber_get_writebuf(struct ber *b, void **buf) 809 { 810 if (b->br_wbuf == NULL) 811 return -1; 812 *buf = b->br_wbuf; 813 return (b->br_wend - b->br_wbuf); 814 } 815 816 /* 817 * write ber elements to the write buffer 818 * 819 * params: 820 * ber holds the destination write buffer byte stream 821 * root fully populated element tree 822 * 823 * returns: 824 * >=0 number of bytes written 825 * -1 on failure and sets errno 826 */ 827 ssize_t 828 ber_write_elements(struct ber *ber, struct ber_element *root) 829 { 830 size_t len; 831 832 /* calculate length because only the definite form is required */ 833 len = ber_calc_len(root); 834 DPRINTF("write ber element of %zd bytes length\n", len); 835 836 if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) { 837 free(ber->br_wbuf); 838 ber->br_wbuf = NULL; 839 } 840 if (ber->br_wbuf == NULL) { 841 if ((ber->br_wbuf = malloc(len)) == NULL) 842 return -1; 843 ber->br_wend = ber->br_wbuf + len; 844 } 845 846 /* reset write pointer */ 847 ber->br_wptr = ber->br_wbuf; 848 849 if (ber_dump_element(ber, root) == -1) 850 return -1; 851 852 return (len); 853 } 854 855 void 856 ber_set_readbuf(struct ber *b, void *buf, size_t len) 857 { 858 b->br_rbuf = b->br_rptr = buf; 859 b->br_rend = (u_int8_t *)buf + len; 860 } 861 862 /* 863 * read ber elements from the read buffer 864 * 865 * params: 866 * ber holds a fully populated read buffer byte stream 867 * root if NULL, build up an element tree from what we receive on 868 * the wire. If not null, use the specified encoding for the 869 * elements received. 870 * 871 * returns: 872 * !=NULL, elements read and store in the ber_element tree 873 * NULL, type mismatch or read error 874 */ 875 struct ber_element * 876 ber_read_elements(struct ber *ber, struct ber_element *elm) 877 { 878 struct ber_element *root = elm; 879 880 if (root == NULL) { 881 if ((root = ber_get_element(0)) == NULL) 882 return NULL; 883 } 884 885 DPRINTF("read ber elements, root %p\n", root); 886 887 if (ber_read_element(ber, root) == -1) { 888 /* Cleanup if root was allocated by us */ 889 if (elm == NULL) 890 ber_free_elements(root); 891 return NULL; 892 } 893 894 return root; 895 } 896 897 off_t 898 ber_getpos(struct ber_element *elm) 899 { 900 return elm->be_offs; 901 } 902 903 void 904 ber_free_element(struct ber_element *root) 905 { 906 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE || 907 root->be_encoding == BER_TYPE_SET)) 908 ber_free_elements(root->be_sub); 909 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING || 910 root->be_encoding == BER_TYPE_BITSTRING || 911 root->be_encoding == BER_TYPE_OBJECT)) 912 free(root->be_val); 913 free(root); 914 } 915 916 void 917 ber_free_elements(struct ber_element *root) 918 { 919 if (root == NULL) 920 return; 921 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE || 922 root->be_encoding == BER_TYPE_SET)) 923 ber_free_elements(root->be_sub); 924 if (root->be_next) 925 ber_free_elements(root->be_next); 926 if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING || 927 root->be_encoding == BER_TYPE_BITSTRING || 928 root->be_encoding == BER_TYPE_OBJECT)) 929 free(root->be_val); 930 free(root); 931 } 932 933 size_t 934 ber_calc_len(struct ber_element *root) 935 { 936 unsigned int t; 937 size_t s; 938 size_t size = 2; /* minimum 1 byte head and 1 byte size */ 939 940 /* calculate the real length of a sequence or set */ 941 if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE || 942 root->be_encoding == BER_TYPE_SET)) 943 root->be_len = ber_calc_len(root->be_sub); 944 945 /* fix header length for extended types */ 946 if (root->be_type > BER_TYPE_SINGLE_MAX) 947 for (t = root->be_type; t > 0; t >>= 7) 948 size++; 949 if (root->be_len >= BER_TAG_MORE) 950 for (s = root->be_len; s > 0; s >>= 8) 951 size++; 952 953 /* calculate the length of the following elements */ 954 if (root->be_next) 955 size += ber_calc_len(root->be_next); 956 957 /* This is an empty element, do not use a minimal size */ 958 if (root->be_class == BER_CLASS_UNIVERSAL && 959 root->be_type == BER_TYPE_EOC && root->be_len == 0) 960 return (0); 961 962 return (root->be_len + size); 963 } 964 965 void 966 ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *)) 967 { 968 b->br_application = cb; 969 } 970 971 void 972 ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t), 973 void *arg) 974 { 975 elm->be_cb = cb; 976 elm->be_cbarg = arg; 977 } 978 979 void 980 ber_free(struct ber *b) 981 { 982 free(b->br_wbuf); 983 } 984 985 /* 986 * internal functions 987 */ 988 989 static int 990 ber_dump_element(struct ber *ber, struct ber_element *root) 991 { 992 unsigned long long l; 993 int i; 994 uint8_t u; 995 996 ber_dump_header(ber, root); 997 if (root->be_cb) 998 root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf); 999 1000 switch (root->be_encoding) { 1001 case BER_TYPE_BOOLEAN: 1002 case BER_TYPE_INTEGER: 1003 case BER_TYPE_ENUMERATED: 1004 l = (unsigned long long)root->be_numeric; 1005 for (i = root->be_len; i > 0; i--) { 1006 u = (l >> ((i - 1) * 8)) & 0xff; 1007 ber_putc(ber, u); 1008 } 1009 break; 1010 case BER_TYPE_BITSTRING: 1011 case BER_TYPE_OCTETSTRING: 1012 case BER_TYPE_OBJECT: 1013 ber_write(ber, root->be_val, root->be_len); 1014 break; 1015 case BER_TYPE_NULL: /* no payload */ 1016 case BER_TYPE_EOC: 1017 break; 1018 case BER_TYPE_SEQUENCE: 1019 case BER_TYPE_SET: 1020 if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1) 1021 return -1; 1022 break; 1023 } 1024 1025 if (root->be_next == NULL) 1026 return 0; 1027 return ber_dump_element(ber, root->be_next); 1028 } 1029 1030 static void 1031 ber_dump_header(struct ber *ber, struct ber_element *root) 1032 { 1033 u_char id = 0, t, buf[5]; 1034 unsigned int type; 1035 size_t size; 1036 1037 /* class universal, type encoding depending on type value */ 1038 /* length encoding */ 1039 if (root->be_type <= BER_TYPE_SINGLE_MAX) { 1040 id = root->be_type | (root->be_class << BER_CLASS_SHIFT); 1041 if (root->be_encoding == BER_TYPE_SEQUENCE || 1042 root->be_encoding == BER_TYPE_SET) 1043 id |= BER_TYPE_CONSTRUCTED; 1044 1045 ber_putc(ber, id); 1046 } else { 1047 id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT); 1048 if (root->be_encoding == BER_TYPE_SEQUENCE || 1049 root->be_encoding == BER_TYPE_SET) 1050 id |= BER_TYPE_CONSTRUCTED; 1051 1052 ber_putc(ber, id); 1053 1054 for (t = 0, type = root->be_type; type > 0; type >>= 7) 1055 buf[t++] = type & ~BER_TAG_MORE; 1056 1057 while (t-- > 0) { 1058 if (t > 0) 1059 buf[t] |= BER_TAG_MORE; 1060 ber_putc(ber, buf[t]); 1061 } 1062 } 1063 1064 if (root->be_len < BER_TAG_MORE) { 1065 /* short form */ 1066 ber_putc(ber, root->be_len); 1067 } else { 1068 for (t = 0, size = root->be_len; size > 0; size >>= 8) 1069 buf[t++] = size & 0xff; 1070 1071 ber_putc(ber, t | BER_TAG_MORE); 1072 1073 while (t > 0) 1074 ber_putc(ber, buf[--t]); 1075 } 1076 } 1077 1078 static void 1079 ber_putc(struct ber *ber, u_char c) 1080 { 1081 if (ber->br_wptr + 1 <= ber->br_wend) 1082 *ber->br_wptr = c; 1083 ber->br_wptr++; 1084 } 1085 1086 static void 1087 ber_write(struct ber *ber, void *buf, size_t len) 1088 { 1089 if (ber->br_wptr + len <= ber->br_wend) 1090 bcopy(buf, ber->br_wptr, len); 1091 ber->br_wptr += len; 1092 } 1093 1094 /* 1095 * extract a BER encoded tag. There are two types, a short and long form. 1096 */ 1097 static ssize_t 1098 get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct) 1099 { 1100 u_char u; 1101 size_t i = 0; 1102 unsigned int t = 0; 1103 1104 if (ber_getc(b, &u) == -1) 1105 return -1; 1106 1107 *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK; 1108 *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED; 1109 1110 if ((u & BER_TAG_MASK) != BER_TAG_MASK) { 1111 *tag = u & BER_TAG_MASK; 1112 return 1; 1113 } 1114 1115 do { 1116 if (ber_getc(b, &u) == -1) 1117 return -1; 1118 1119 /* enforce minimal number of octets for tag > 30 */ 1120 if (i == 0 && (u & ~BER_TAG_MORE) == 0) { 1121 errno = EINVAL; 1122 return -1; 1123 } 1124 1125 t = (t << 7) | (u & ~BER_TAG_MORE); 1126 i++; 1127 if (i > sizeof(unsigned int)) { 1128 errno = ERANGE; 1129 return -1; 1130 } 1131 } while (u & BER_TAG_MORE); 1132 1133 *tag = t; 1134 return i + 1; 1135 } 1136 1137 /* 1138 * extract length of a ber object -- if length is unknown an error is returned. 1139 */ 1140 static ssize_t 1141 get_len(struct ber *b, ssize_t *len) 1142 { 1143 u_char u, n; 1144 ssize_t s, r; 1145 1146 if (ber_getc(b, &u) == -1) 1147 return -1; 1148 if ((u & BER_TAG_MORE) == 0) { 1149 /* short form */ 1150 *len = u; 1151 return 1; 1152 } 1153 1154 if (u == 0x80) { 1155 /* Indefinite length not supported. */ 1156 errno = EINVAL; 1157 return -1; 1158 } 1159 1160 if (u == 0xff) { 1161 /* Reserved for future use. */ 1162 errno = EINVAL; 1163 return -1; 1164 } 1165 1166 n = u & ~BER_TAG_MORE; 1167 /* 1168 * Limit to a decent size that works on all of our architectures. 1169 */ 1170 if (sizeof(int32_t) < n) { 1171 errno = ERANGE; 1172 return -1; 1173 } 1174 r = n + 1; 1175 1176 for (s = 0; n > 0; n--) { 1177 if (ber_getc(b, &u) == -1) 1178 return -1; 1179 s = (s << 8) | u; 1180 } 1181 1182 if (s < 0) { 1183 /* overflow */ 1184 errno = ERANGE; 1185 return -1; 1186 } 1187 1188 *len = s; 1189 return r; 1190 } 1191 1192 static ssize_t 1193 ber_read_element(struct ber *ber, struct ber_element *elm) 1194 { 1195 long long val = 0; 1196 struct ber_element *next; 1197 unsigned int type; 1198 int i, class, cstruct, elements = 0; 1199 ssize_t len, r, totlen = 0; 1200 u_char c, last = 0; 1201 1202 if ((r = get_id(ber, &type, &class, &cstruct)) == -1) 1203 return -1; 1204 DPRINTF("ber read got class %d type %u, %s\n", 1205 class, type, cstruct ? "constructed" : "primitive"); 1206 totlen += r; 1207 if ((r = get_len(ber, &len)) == -1) 1208 return -1; 1209 DPRINTF("ber read element size %zd\n", len); 1210 totlen += r + len; 1211 1212 /* The encoding of boolean, integer, enumerated, and null values 1213 * must be primitive. */ 1214 if (class == BER_CLASS_UNIVERSAL) 1215 if (type == BER_TYPE_BOOLEAN || 1216 type == BER_TYPE_INTEGER || 1217 type == BER_TYPE_ENUMERATED || 1218 type == BER_TYPE_NULL) 1219 if (cstruct) { 1220 errno = EINVAL; 1221 return -1; 1222 } 1223 1224 /* If the total size of the element is larger than the buffer 1225 * don't bother to continue. */ 1226 if (len > ber->br_rend - ber->br_rptr) { 1227 errno = ECANCELED; 1228 return -1; 1229 } 1230 1231 elm->be_type = type; 1232 elm->be_len = len; 1233 elm->be_offs = ber->br_offs; /* element position within stream */ 1234 elm->be_class = class; 1235 1236 if (elm->be_encoding == 0) { 1237 /* try to figure out the encoding via class, type and cstruct */ 1238 if (cstruct) 1239 elm->be_encoding = BER_TYPE_SEQUENCE; 1240 else if (class == BER_CLASS_UNIVERSAL) 1241 elm->be_encoding = type; 1242 else if (ber->br_application != NULL) { 1243 /* 1244 * Ask the application to map the encoding to a 1245 * universal type. For example, a SMI IpAddress 1246 * type is defined as 4 byte OCTET STRING. 1247 */ 1248 elm->be_encoding = (*ber->br_application)(elm); 1249 } else 1250 /* last resort option */ 1251 elm->be_encoding = BER_TYPE_NULL; 1252 } 1253 1254 switch (elm->be_encoding) { 1255 case BER_TYPE_EOC: /* End-Of-Content */ 1256 break; 1257 case BER_TYPE_BOOLEAN: 1258 if (len != 1) { 1259 errno = EINVAL; 1260 return -1; 1261 } 1262 case BER_TYPE_INTEGER: 1263 case BER_TYPE_ENUMERATED: 1264 if (len > (ssize_t)sizeof(long long)) 1265 return -1; 1266 for (i = 0; i < len; i++) { 1267 if (ber_getc(ber, &c) != 1) 1268 return -1; 1269 1270 /* smallest number of contents octets only */ 1271 if ((i == 1 && last == 0 && (c & 0x80) == 0) || 1272 (i == 1 && last == 0xff && (c & 0x80) != 0)) 1273 return -1; 1274 1275 val <<= 8; 1276 val |= c; 1277 last = c; 1278 } 1279 1280 /* sign extend if MSB is set */ 1281 if (len < (ssize_t)sizeof(long long) && 1282 (val >> ((len - 1) * 8) & 0x80)) 1283 val |= ULLONG_MAX << (len * 8); 1284 elm->be_numeric = val; 1285 break; 1286 case BER_TYPE_BITSTRING: 1287 elm->be_val = malloc(len); 1288 if (elm->be_val == NULL) 1289 return -1; 1290 elm->be_free = 1; 1291 elm->be_len = len; 1292 ber_read(ber, elm->be_val, len); 1293 break; 1294 case BER_TYPE_OCTETSTRING: 1295 case BER_TYPE_OBJECT: 1296 elm->be_val = malloc(len + 1); 1297 if (elm->be_val == NULL) 1298 return -1; 1299 elm->be_free = 1; 1300 elm->be_len = len; 1301 ber_read(ber, elm->be_val, len); 1302 ((u_char *)elm->be_val)[len] = '\0'; 1303 break; 1304 case BER_TYPE_NULL: /* no payload */ 1305 if (len != 0) 1306 return -1; 1307 break; 1308 case BER_TYPE_SEQUENCE: 1309 case BER_TYPE_SET: 1310 if (elm->be_sub == NULL) { 1311 if ((elm->be_sub = ber_get_element(0)) == NULL) 1312 return -1; 1313 } 1314 next = elm->be_sub; 1315 while (len > 0) { 1316 /* 1317 * Prevent stack overflow from excessive recursion 1318 * depth in ber_free_elements(). 1319 */ 1320 if (elements >= BER_MAX_SEQ_ELEMENTS) { 1321 errno = ERANGE; 1322 return -1; 1323 } 1324 r = ber_read_element(ber, next); 1325 if (r == -1) 1326 return -1; 1327 elements++; 1328 len -= r; 1329 if (len > 0 && next->be_next == NULL) { 1330 if ((next->be_next = ber_get_element(0)) == 1331 NULL) 1332 return -1; 1333 } 1334 next = next->be_next; 1335 } 1336 break; 1337 } 1338 return totlen; 1339 } 1340 1341 static ssize_t 1342 ber_getc(struct ber *b, u_char *c) 1343 { 1344 return ber_read(b, c, 1); 1345 } 1346 1347 static ssize_t 1348 ber_read(struct ber *ber, void *buf, size_t len) 1349 { 1350 size_t sz; 1351 1352 if (ber->br_rbuf == NULL) 1353 return -1; 1354 1355 sz = ber->br_rend - ber->br_rptr; 1356 if (len > sz) { 1357 errno = ECANCELED; 1358 return -1; /* parser wants more data than available */ 1359 } 1360 1361 bcopy(ber->br_rptr, buf, len); 1362 ber->br_rptr += len; 1363 ber->br_offs += len; 1364 1365 return len; 1366 } 1367