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