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