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