1 /* $Id: aldap.c,v 1.19 2009/01/29 11:43:31 aschrijver Exp $ */ 2 /* $OpenBSD: aldap.c,v 1.19 2009/01/29 11:43:31 aschrijver Exp $ */ 3 4 /* 5 * Copyright (c) 2008 Alexander Schrijver <aschrijver@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 <errno.h> 22 #include <inttypes.h> 23 #include <string.h> 24 #include <stdlib.h> 25 #include <unistd.h> 26 27 #include "aldap.h" 28 29 #if 0 30 #define DEBUG 31 #endif 32 #define VERSION 3 33 34 static struct ber_element *ldap_parse_search_filter(struct ber_element*, char *); 35 static struct ber_element *ldap_do_parse_search_filter(struct ber_element*, char **); 36 char **aldap_get_stringset(struct ber_element *); 37 char *utoa(char *); 38 char *parseval(char *, size_t); 39 40 #ifdef DEBUG 41 void ldap_debug_elements(struct ber_element *); 42 #endif 43 44 #ifdef DEBUG 45 #define DPRINTF(x...) printf(x) 46 #define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0) 47 #else 48 #define DPRINTF(x...) do { } while (0) 49 #define LDAP_DEBUG(x, y) do { } while (0) 50 #endif 51 52 int 53 aldap_close(struct aldap *al) 54 { 55 if (close(al->ber.fd) == -1) 56 return (-1); 57 58 free(al); 59 60 return (0); 61 } 62 63 64 struct aldap * 65 aldap_init(int fd) 66 { 67 struct aldap *a; 68 69 if ((a = calloc(1, sizeof(*a))) == NULL) 70 return NULL; 71 a->ber.fd = fd; 72 73 return a; 74 } 75 76 int 77 aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) 78 { 79 struct ber_element *root = NULL, *elm; 80 int error; 81 82 if (binddn == NULL) 83 binddn = ""; 84 if (bindcred == NULL) 85 bindcred = ""; 86 87 if ((root = ber_add_sequence(NULL)) == NULL) 88 goto fail; 89 90 elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP, 91 (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred, 92 BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE); 93 if (elm == NULL) 94 goto fail; 95 96 LDAP_DEBUG("aldap_bind", root); 97 98 error = ber_write_elements(&ldap->ber, root); 99 ber_free_elements(root); 100 root = NULL; 101 if (error == -1) 102 goto fail; 103 104 return (ldap->msgid); 105 fail: 106 if (root != NULL) 107 ber_free_elements(root); 108 109 ldap->err = ALDAP_ERR_OPERATION_FAILED; 110 return (-1); 111 } 112 113 int 114 aldap_unbind(struct aldap *ldap) 115 { 116 struct ber_element *root = NULL, *elm; 117 int error; 118 119 if ((root = ber_add_sequence(NULL)) == NULL) 120 goto fail; 121 elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, 122 LDAP_REQ_UNBIND_30); 123 if (elm == NULL) 124 goto fail; 125 126 LDAP_DEBUG("aldap_unbind", root); 127 128 error = ber_write_elements(&ldap->ber, root); 129 ber_free_elements(root); 130 root = NULL; 131 if (error == -1) 132 goto fail; 133 134 return (ldap->msgid); 135 fail: 136 if (root != NULL) 137 ber_free_elements(root); 138 139 ldap->err = ALDAP_ERR_OPERATION_FAILED; 140 141 return (-1); 142 } 143 144 int 145 aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, 146 char **attrs, int typesonly, int sizelimit, int timelimit) 147 { 148 struct ber_element *root = NULL, *ber; 149 int i, error; 150 151 if ((root = ber_add_sequence(NULL)) == NULL) 152 goto fail; 153 154 ber = ber_printf_elements(root, "d{tsEEddb", ++ldap->msgid, BER_CLASS_APP, 155 (unsigned long)LDAP_REQ_SEARCH, basedn, (long long)scope, 156 (long long)LDAP_DEREF_NEVER, sizelimit, timelimit, typesonly); 157 if (ber == NULL) { 158 ldap->err = ALDAP_ERR_OPERATION_FAILED; 159 goto fail; 160 } 161 162 if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) { 163 ldap->err = ALDAP_ERR_PARSER_ERROR; 164 goto fail; 165 } 166 167 if ((ber = ber_add_sequence(ber)) == NULL) 168 goto fail; 169 if (attrs != NULL) 170 for (i = 0; i >= 0 && attrs[i] != NULL; i++) { 171 if ((ber = ber_add_string(ber, attrs[i])) == NULL) 172 goto fail; 173 } 174 175 LDAP_DEBUG("aldap_search", root); 176 177 error = ber_write_elements(&ldap->ber, root); 178 ber_free_elements(root); 179 root = NULL; 180 if (error == -1) { 181 ldap->err = ALDAP_ERR_OPERATION_FAILED; 182 goto fail; 183 } 184 185 return (ldap->msgid); 186 187 fail: 188 if (root != NULL) 189 ber_free_elements(root); 190 191 return (-1); 192 } 193 194 struct aldap_message * 195 aldap_parse(struct aldap *ldap) 196 { 197 int class = 0; 198 long long msgid = 0; 199 unsigned long type = 0; 200 struct aldap_message *m; 201 struct ber_element *a = NULL; 202 203 if ((m = calloc(1, sizeof(struct aldap_message))) == NULL) 204 return NULL; 205 206 if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL) 207 goto parsefail; 208 209 LDAP_DEBUG("message", m->msg); 210 211 if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0) 212 goto parsefail; 213 m->msgid = msgid; 214 m->message_type = type; 215 m->protocol_op = a; 216 217 switch (m->message_type) { 218 case LDAP_RES_BIND: 219 case LDAP_RES_MODIFY: 220 case LDAP_RES_ADD: 221 case LDAP_RES_DELETE: 222 case LDAP_RES_MODRDN: 223 case LDAP_RES_COMPARE: 224 case LDAP_RES_SEARCH_RESULT: 225 if (ber_scanf_elements(m->protocol_op, "{EeSeSe", 226 &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0) 227 goto parsefail; 228 if (m->body.res.rescode == LDAP_REFERRAL) 229 if (ber_scanf_elements(a, "{e", &m->references) != 0) 230 goto parsefail; 231 break; 232 case LDAP_RES_SEARCH_ENTRY: 233 if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn, 234 &m->body.search.entries) != 0) 235 goto parsefail; 236 break; 237 case LDAP_RES_SEARCH_REFERENCE: 238 if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) 239 goto parsefail; 240 break; 241 } 242 243 return m; 244 parsefail: 245 ldap->err = ALDAP_ERR_PARSER_ERROR; 246 aldap_freemsg(m); 247 return NULL; 248 } 249 250 void 251 aldap_freemsg(struct aldap_message *msg) 252 { 253 if (msg->msg) 254 ber_free_elements(msg->msg); 255 free(msg); 256 } 257 258 int 259 aldap_get_resultcode(struct aldap_message *msg) 260 { 261 return msg->body.res.rescode; 262 } 263 264 char * 265 aldap_get_dn(struct aldap_message *msg) 266 { 267 char *dn; 268 269 if (msg->dn == NULL) 270 return NULL; 271 272 if (ber_get_string(msg->dn, &dn) == -1) 273 return NULL; 274 275 return utoa(dn); 276 } 277 278 char ** 279 aldap_get_references(struct aldap_message *msg) 280 { 281 if (msg->references == NULL) 282 return NULL; 283 return aldap_get_stringset(msg->references); 284 } 285 286 void 287 aldap_free_references(char **values) 288 { 289 int i; 290 291 if (values == NULL) 292 return; 293 294 for (i = 0; i >= 0 && values[i] != NULL; i++) 295 free(values[i]); 296 297 free(values); 298 } 299 300 char * 301 aldap_get_diagmsg(struct aldap_message *msg) 302 { 303 char *s; 304 305 if (msg->body.res.diagmsg == NULL) 306 return NULL; 307 308 if (ber_get_string(msg->body.res.diagmsg, &s) == -1) 309 return NULL; 310 311 return utoa(s); 312 } 313 314 int 315 aldap_count_entries(struct aldap_message *msg) 316 { 317 int i; 318 struct ber_element *a; 319 320 if (msg->body.search.entries == NULL) 321 return (-1); 322 323 for (i = 0, a = msg->body.search.entries; i >= 0 && a != NULL && ber_get_eoc(a) != 0; 324 i++, a = a->be_next) 325 ; 326 327 return i; 328 } 329 330 int 331 aldap_first_entry(struct aldap_message *msg, char **outkey, char ***outvalues) 332 { 333 struct ber_element *b, *c; 334 char *key; 335 char **ret; 336 337 if (msg->body.search.entries == NULL) 338 goto fail; 339 340 if (ber_scanf_elements(msg->body.search.entries, "{s(e)}e", &key, &b, 341 &c) != 0) 342 goto fail; 343 344 msg->body.search.iter = msg->body.search.entries->be_next; 345 346 if ((ret = aldap_get_stringset(b)) == NULL) 347 goto fail; 348 349 (*outvalues) = ret; 350 (*outkey) = utoa(key); 351 352 return (1); 353 fail: 354 (*outkey) = NULL; 355 (*outvalues) = NULL; 356 return (-1); 357 } 358 359 int 360 aldap_next_entry(struct aldap_message *msg, char **outkey, char ***outvalues) 361 { 362 struct ber_element *a, *b; 363 char *key; 364 char **ret; 365 366 if (msg->body.search.iter == NULL) 367 goto notfound; 368 369 LDAP_DEBUG("entry", msg->body.search.iter); 370 371 if (ber_get_eoc(msg->body.search.iter) == 0) 372 goto notfound; 373 374 if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) 375 != 0) 376 goto fail; 377 378 msg->body.search.iter = msg->body.search.iter->be_next; 379 380 if ((ret = aldap_get_stringset(a)) == NULL) 381 goto fail; 382 383 (*outvalues) = ret; 384 (*outkey) = utoa(key); 385 386 return (1); 387 fail: 388 notfound: 389 (*outkey) = NULL; 390 (*outvalues) = NULL; 391 return (-1); 392 } 393 394 int 395 aldap_match_entry(struct aldap_message *msg, char *inkey, char ***outvalues) 396 { 397 struct ber_element *a, *b; 398 char *descr = NULL; 399 char **ret; 400 401 if (msg->body.search.entries == NULL) 402 return (-1); 403 404 LDAP_DEBUG("entry", msg->body.search.entries); 405 406 for (a = msg->body.search.entries;;) { 407 if (a == NULL) 408 goto notfound; 409 if (ber_get_eoc(a) == 0) 410 goto notfound; 411 if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) 412 goto fail; 413 if (strcasecmp(descr, inkey) == 0) 414 goto attrfound; 415 a = a->be_next; 416 } 417 418 attrfound: 419 if ((ret = aldap_get_stringset(b)) == NULL) 420 goto fail; 421 422 (*outvalues) = ret; 423 424 return (1); 425 fail: 426 notfound: 427 (*outvalues) = NULL; 428 return (-1); 429 } 430 431 int 432 aldap_free_entry(char **values) 433 { 434 int i; 435 436 if (values == NULL) 437 return -1; 438 439 for (i = 0; i >= 0 && values[i] != NULL; i++) 440 free(values[i]); 441 442 free(values); 443 444 return (1); 445 } 446 447 void 448 aldap_free_url(struct aldap_url *lu) 449 { 450 int i; 451 free(lu->host); 452 free(lu->dn); 453 for (i = 0; i < MAXATTR && lu->attributes[i] != NULL; i++) { 454 free(lu->attributes[i]); 455 } 456 free(lu->filter); 457 } 458 459 int 460 aldap_parse_url(char *url, struct aldap_url *lu) 461 { 462 char *dupstr, *p, *forward, *forward2; 463 const char *errstr = NULL; 464 int i; 465 466 p = dupstr = strdup(url); 467 468 /* protocol */ 469 if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0) 470 goto fail; 471 lu->protocol = LDAP; 472 p += strlen(LDAP_URL); 473 474 /* host and optional port */ 475 if ((forward = strchr(p, '/')) != NULL) 476 *forward = '\0'; 477 /* find the optional port */ 478 if ((forward2 = strchr(p, ':')) != NULL) { 479 *forward2 = '\0'; 480 /* if a port is given */ 481 if (*(forward2+1) != '\0') { 482 #define PORT_MAX UINT16_MAX 483 lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr); 484 if (errstr) 485 goto fail; 486 } 487 } 488 /* fail if no host is given */ 489 if (strlen(p) == 0) 490 goto fail; 491 lu->host = strdup(p); 492 if (forward == NULL) 493 goto done; 494 /* p is assigned either a pointer to a character or to '\0' */ 495 p = ++forward; 496 if (strlen(p) == 0) 497 goto done; 498 499 /* dn */ 500 if ((forward = strchr(p, '?')) != NULL) 501 *forward = '\0'; 502 lu->dn = strdup(p); 503 if (forward == NULL) 504 goto done; 505 /* p is assigned either a pointer to a character or to '\0' */ 506 p = ++forward; 507 if (strlen(p) == 0) 508 goto done; 509 510 /* attributes */ 511 if ((forward = strchr(p, '?')) != NULL) 512 *forward = '\0'; 513 for (i = 0; i < MAXATTR; i++) { 514 if ((forward2 = strchr(p, ',')) == NULL) { 515 if (strlen(p) == 0) 516 break; 517 lu->attributes[i] = strdup(p); 518 break; 519 } 520 *forward2 = '\0'; 521 lu->attributes[i] = strdup(p); 522 p = ++forward2; 523 } 524 if (forward == NULL) 525 goto done; 526 /* p is assigned either a pointer to a character or to '\0' */ 527 p = ++forward; 528 if (strlen(p) == 0) 529 goto done; 530 531 /* scope */ 532 if ((forward = strchr(p, '?')) != NULL) 533 *forward = '\0'; 534 if (strcmp(p, "base") == 0) 535 lu->scope = LDAP_SCOPE_BASE; 536 else if (strcmp(p, "one") == 0) 537 lu->scope = LDAP_SCOPE_ONELEVEL; 538 else if (strcmp(p, "sub") == 0) 539 lu->scope = LDAP_SCOPE_SUBTREE; 540 if (forward == NULL) 541 goto done; 542 p = ++forward; 543 if (strlen(p) == 0) 544 goto done; 545 546 /* filter */ 547 if (p == NULL) 548 goto done; 549 lu->filter = strdup(p); 550 551 done: 552 free(dupstr); 553 return (1); 554 fail: 555 free(dupstr); 556 return (-1); 557 } 558 559 /* 560 * internal functions 561 */ 562 563 char ** 564 aldap_get_stringset(struct ber_element *elm) 565 { 566 struct ber_element *a; 567 int i; 568 char **ret; 569 char *s; 570 571 if (elm->be_type != BER_TYPE_OCTETSTRING) 572 return NULL; 573 574 for (a = elm, i = 1; i > 0 && a != NULL && a->be_type == 575 BER_TYPE_OCTETSTRING; a = a->be_next, i++) 576 ; 577 if (i == 1) 578 return NULL; 579 580 if ((ret = calloc(i + 1, sizeof(char *))) == NULL) 581 return NULL; 582 583 for (a = elm, i = 0; i >= 0 && a->be_type == BER_TYPE_OCTETSTRING; 584 a = a->be_next, i++) { 585 586 ber_get_string(a, &s); 587 ret[i] = utoa(s); 588 } 589 ret[i + 1] = NULL; 590 591 return ret; 592 } 593 594 /* 595 * Base case for ldap_do_parse_search_filter 596 * 597 * returns: 598 * struct ber_element *, ber_element tree 599 * NULL, parse failed 600 */ 601 static struct ber_element * 602 ldap_parse_search_filter(struct ber_element *ber, char *filter) 603 { 604 struct ber_element *elm; 605 char *cp; 606 607 cp = filter; 608 609 if (cp == NULL || *cp == '\0') { 610 errno = EINVAL; 611 return (NULL); 612 } 613 614 if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) 615 return (NULL); 616 617 if (*cp != '\0') { 618 ber_free_elements(elm); 619 ber_link_elements(ber, NULL); 620 errno = EINVAL; 621 return (NULL); 622 } 623 624 return (elm); 625 } 626 627 /* 628 * Translate RFC4515 search filter string into ber_element tree 629 * 630 * returns: 631 * struct ber_element *, ber_element tree 632 * NULL, parse failed 633 * 634 * notes: 635 * when cp is passed to a recursive invocation, it is updated 636 * to point one character beyond the filter that was passed 637 * i.e., cp jumps to "(filter)" 638 * ^ 639 * goto's used to discriminate error-handling based on error type 640 * doesn't handle extended filters (yet) 641 * 642 */ 643 static struct ber_element * 644 ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) 645 { 646 struct ber_element *elm, *root = NULL; 647 char *attr_desc, *attr_val, *parsed_val, *cp; 648 size_t len; 649 unsigned long type; 650 651 root = NULL; 652 653 /* cpp should pass in pointer to opening parenthesis of "(filter)" */ 654 cp = *cpp; 655 if (*cp != '(') 656 goto syntaxfail; 657 658 switch (*++cp) { 659 case '&': /* AND */ 660 case '|': /* OR */ 661 if (*cp == '&') 662 type = LDAP_FILT_AND; 663 else 664 type = LDAP_FILT_OR; 665 666 if ((elm = ber_add_set(prev)) == NULL) 667 goto callfail; 668 root = elm; 669 ber_set_header(elm, BER_CLASS_APP, type); 670 671 if (*++cp != '(') /* opening `(` of filter */ 672 goto syntaxfail; 673 674 while (*cp == '(') { 675 if ((elm = 676 ldap_do_parse_search_filter(elm, &cp)) == NULL) 677 goto bad; 678 } 679 680 if (*cp != ')') /* trailing `)` of filter */ 681 goto syntaxfail; 682 break; 683 684 case '!': /* NOT */ 685 if ((root = ber_add_sequence(prev)) == NULL) 686 goto callfail; 687 ber_set_header(root, BER_CLASS_APP, LDAP_FILT_NOT); 688 689 cp++; /* now points to sub-filter */ 690 if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL) 691 goto bad; 692 693 if (*cp != ')') /* trailing `)` of filter */ 694 goto syntaxfail; 695 break; 696 697 default: /* SIMPLE || PRESENCE */ 698 attr_desc = cp; 699 700 len = strcspn(cp, "()<>~="); 701 cp += len; 702 switch (*cp) { 703 case '~': 704 type = LDAP_FILT_APPR; 705 cp++; 706 break; 707 case '<': 708 type = LDAP_FILT_LE; 709 cp++; 710 break; 711 case '>': 712 type = LDAP_FILT_GE; 713 cp++; 714 break; 715 case '=': 716 type = LDAP_FILT_EQ; /* assume EQ until disproven */ 717 break; 718 case '(': 719 case ')': 720 default: 721 goto syntaxfail; 722 } 723 attr_val = ++cp; 724 725 /* presence filter */ 726 if (strncmp(attr_val, "*)", 2) == 0) { 727 cp++; /* point to trailing `)` */ 728 if ((root = 729 ber_add_nstring(prev, attr_desc, len)) == NULL) 730 goto bad; 731 732 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES); 733 break; 734 } 735 736 if ((root = ber_add_sequence(prev)) == NULL) 737 goto callfail; 738 ber_set_header(root, BER_CLASS_CONTEXT, type); 739 740 if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL) 741 goto callfail; 742 743 len = strcspn(attr_val, "*)"); 744 if (len == 0 && *cp != '*') 745 goto syntaxfail; 746 cp += len; 747 if (*cp == '\0') 748 goto syntaxfail; 749 750 if (*cp == '*') { /* substring filter */ 751 int initial; 752 753 cp = attr_val; 754 755 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS); 756 757 if ((elm = ber_add_sequence(elm)) == NULL) 758 goto callfail; 759 760 for (initial = 1;; cp++, initial = 0) { 761 attr_val = cp; 762 763 len = strcspn(attr_val, "*)"); 764 if (len == 0) { 765 if (*cp == ')') 766 break; 767 else 768 continue; 769 } 770 cp += len; 771 if (*cp == '\0') 772 goto syntaxfail; 773 774 if (initial) 775 type = LDAP_FILT_SUBS_INIT; 776 else if (*cp == ')') 777 type = LDAP_FILT_SUBS_FIN; 778 else 779 type = LDAP_FILT_SUBS_ANY; 780 781 if ((parsed_val = parseval(attr_val, len)) == 782 NULL) 783 goto callfail; 784 if ((elm = 785 ber_add_nstring(elm, parsed_val, 786 strlen(parsed_val))) == NULL) 787 goto callfail; 788 free(parsed_val); 789 ber_set_header(elm, BER_CLASS_CONTEXT, type); 790 if (type == LDAP_FILT_SUBS_FIN) 791 break; 792 } 793 break; 794 } 795 796 if ((parsed_val = parseval(attr_val, len)) == NULL) 797 goto callfail; 798 if ((elm = ber_add_nstring(elm, parsed_val, 799 strlen(parsed_val))) == NULL) 800 goto callfail; 801 free(parsed_val); 802 break; 803 } 804 805 cp++; /* now points one char beyond the trailing `)` */ 806 807 *cpp = cp; 808 return (root); 809 810 syntaxfail: /* XXX -- error reporting */ 811 callfail: 812 bad: 813 if (root != NULL) 814 ber_free_elements(root); 815 ber_link_elements(prev, NULL); 816 return (NULL); 817 } 818 819 #ifdef DEBUG 820 /* 821 * Display a list of ber elements. 822 * 823 */ 824 void 825 ldap_debug_elements(struct ber_element *root) 826 { 827 static int indent = 0; 828 long long v; 829 int d; 830 char *buf; 831 size_t len; 832 u_int i; 833 int constructed; 834 struct ber_oid o; 835 836 /* calculate lengths */ 837 ber_calc_len(root); 838 839 switch (root->be_encoding) { 840 case BER_TYPE_SEQUENCE: 841 case BER_TYPE_SET: 842 constructed = root->be_encoding; 843 break; 844 default: 845 constructed = 0; 846 break; 847 } 848 849 fprintf(stderr, "%*slen %lu ", indent, "", root->be_len); 850 switch (root->be_class) { 851 case BER_CLASS_UNIVERSAL: 852 fprintf(stderr, "class: universal(%u) type: ", root->be_class); 853 switch (root->be_type) { 854 case BER_TYPE_EOC: 855 fprintf(stderr, "end-of-content"); 856 break; 857 case BER_TYPE_BOOLEAN: 858 fprintf(stderr, "boolean"); 859 break; 860 case BER_TYPE_INTEGER: 861 fprintf(stderr, "integer"); 862 break; 863 case BER_TYPE_BITSTRING: 864 fprintf(stderr, "bit-string"); 865 break; 866 case BER_TYPE_OCTETSTRING: 867 fprintf(stderr, "octet-string"); 868 break; 869 case BER_TYPE_NULL: 870 fprintf(stderr, "null"); 871 break; 872 case BER_TYPE_OBJECT: 873 fprintf(stderr, "object"); 874 break; 875 case BER_TYPE_ENUMERATED: 876 fprintf(stderr, "enumerated"); 877 break; 878 case BER_TYPE_SEQUENCE: 879 fprintf(stderr, "sequence"); 880 break; 881 case BER_TYPE_SET: 882 fprintf(stderr, "set"); 883 break; 884 } 885 break; 886 case BER_CLASS_APPLICATION: 887 fprintf(stderr, "class: application(%u) type: ", 888 root->be_class); 889 switch (root->be_type) { 890 case LDAP_REQ_BIND: 891 fprintf(stderr, "bind"); 892 break; 893 case LDAP_RES_BIND: 894 fprintf(stderr, "bind"); 895 break; 896 case LDAP_REQ_UNBIND_30: 897 break; 898 case LDAP_REQ_SEARCH: 899 fprintf(stderr, "search"); 900 break; 901 case LDAP_RES_SEARCH_ENTRY: 902 fprintf(stderr, "search_entry"); 903 break; 904 case LDAP_RES_SEARCH_RESULT: 905 fprintf(stderr, "search_result"); 906 break; 907 case LDAP_REQ_MODIFY: 908 fprintf(stderr, "modify"); 909 break; 910 case LDAP_RES_MODIFY: 911 fprintf(stderr, "modify"); 912 break; 913 case LDAP_REQ_ADD: 914 fprintf(stderr, "add"); 915 break; 916 case LDAP_RES_ADD: 917 fprintf(stderr, "add"); 918 break; 919 case LDAP_REQ_DELETE_30: 920 fprintf(stderr, "delete"); 921 break; 922 case LDAP_RES_DELETE: 923 fprintf(stderr, "delete"); 924 break; 925 case LDAP_REQ_MODRDN: 926 fprintf(stderr, "modrdn"); 927 break; 928 case LDAP_RES_MODRDN: 929 fprintf(stderr, "modrdn"); 930 break; 931 case LDAP_REQ_COMPARE: 932 fprintf(stderr, "compare"); 933 break; 934 case LDAP_RES_COMPARE: 935 fprintf(stderr, "compare"); 936 break; 937 case LDAP_REQ_ABANDON_30: 938 fprintf(stderr, "abandon"); 939 break; 940 } 941 break; 942 case BER_CLASS_PRIVATE: 943 fprintf(stderr, "class: private(%u) type: ", root->be_class); 944 fprintf(stderr, "encoding (%lu) type: ", root->be_encoding); 945 break; 946 case BER_CLASS_CONTEXT: 947 /* XXX: this is not correct */ 948 fprintf(stderr, "class: context(%u) type: ", root->be_class); 949 switch(root->be_type) { 950 case LDAP_AUTH_SIMPLE: 951 fprintf(stderr, "auth simple"); 952 break; 953 } 954 break; 955 default: 956 fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class); 957 break; 958 } 959 fprintf(stderr, "(%lu) encoding %lu ", 960 root->be_type, root->be_encoding); 961 962 if (constructed) 963 root->be_encoding = constructed; 964 965 switch (root->be_encoding) { 966 case BER_TYPE_BOOLEAN: 967 if (ber_get_boolean(root, &d) == -1) { 968 fprintf(stderr, "<INVALID>\n"); 969 break; 970 } 971 fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d); 972 break; 973 case BER_TYPE_INTEGER: 974 if (ber_get_integer(root, &v) == -1) { 975 fprintf(stderr, "<INVALID>\n"); 976 break; 977 } 978 fprintf(stderr, "value %lld\n", v); 979 break; 980 case BER_TYPE_ENUMERATED: 981 if (ber_get_enumerated(root, &v) == -1) { 982 fprintf(stderr, "<INVALID>\n"); 983 break; 984 } 985 fprintf(stderr, "value %lld\n", v); 986 break; 987 case BER_TYPE_BITSTRING: 988 if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { 989 fprintf(stderr, "<INVALID>\n"); 990 break; 991 } 992 fprintf(stderr, "hexdump "); 993 for (i = 0; i < len; i++) 994 fprintf(stderr, "%02x", buf[i]); 995 fprintf(stderr, "\n"); 996 break; 997 case BER_TYPE_OBJECT: 998 if (ber_get_oid(root, &o) == -1) { 999 fprintf(stderr, "<INVALID>\n"); 1000 break; 1001 } 1002 fprintf(stderr, "\n"); 1003 break; 1004 case BER_TYPE_OCTETSTRING: 1005 if (ber_get_nstring(root, (void *)&buf, &len) == -1) { 1006 fprintf(stderr, "<INVALID>\n"); 1007 break; 1008 } 1009 fprintf(stderr, "string \"%.*s\"\n", len, buf); 1010 break; 1011 case BER_TYPE_NULL: /* no payload */ 1012 case BER_TYPE_EOC: 1013 case BER_TYPE_SEQUENCE: 1014 case BER_TYPE_SET: 1015 default: 1016 fprintf(stderr, "\n"); 1017 break; 1018 } 1019 1020 if (constructed && root->be_sub) { 1021 indent += 2; 1022 ldap_debug_elements(root->be_sub); 1023 indent -= 2; 1024 } 1025 if (root->be_next) 1026 ldap_debug_elements(root->be_next); 1027 } 1028 #endif 1029 1030 /* 1031 * Convert UTF-8 to ASCII. 1032 * notes: 1033 * non-ASCII characters are displayed as '?' 1034 * the argument u should be a NULL terminated sequence of UTF-8 bytes. 1035 */ 1036 char * 1037 utoa(char *u) 1038 { 1039 int len, i, j; 1040 char *str; 1041 1042 /* calculate the length to allocate */ 1043 for (len = 0, i = 0; u[i] != NULL; ) { 1044 if ((u[i] & 0xF0) == 0xF0) 1045 i += 4; 1046 else if ((u[i] & 0xE0) == 0xE0) 1047 i += 3; 1048 else if ((u[i] & 0xC0) == 0xC0) 1049 i += 2; 1050 else 1051 i += 1; 1052 len++; 1053 } 1054 1055 if ((str = calloc(len + 1, sizeof(char))) == NULL) 1056 return NULL; 1057 1058 /* copy the ASCII characters to the newly allocated string */ 1059 for (i = 0, j = 0; u[i] != NULL; j++) { 1060 if ((u[i] & 0xF0) == 0xF0) { 1061 str[j] = '?'; 1062 i += 4; 1063 } else if ((u[i] & 0xE0) == 0xE0) { 1064 str[j] = '?'; 1065 i += 3; 1066 } else if ((u[i] & 0xC0) == 0xC0) { 1067 str[j] = '?'; 1068 i += 2; 1069 } else { 1070 str[j] = u[i]; 1071 i += 1; 1072 } 1073 } 1074 1075 return str; 1076 } 1077 1078 /* 1079 * Parse a LDAP value 1080 * notes: 1081 * the argument u should be a NULL terminated sequence of ASCII bytes. 1082 */ 1083 char * 1084 parseval(char *p, size_t len) 1085 { 1086 char hex[3]; 1087 char *cp = p, *buffer, *newbuffer; 1088 size_t size, newsize, i, j; 1089 1090 size = 50; 1091 if ((buffer = calloc(1, size)) == NULL) 1092 return NULL; 1093 1094 for (i = 0, j = 0; i >= 0 && j < len; i++) { 1095 if (i >= size) { 1096 newsize = size + 1024; 1097 if ((newbuffer = realloc(buffer, newsize)) == NULL) { 1098 free(buffer); 1099 return (NULL); 1100 } 1101 buffer = newbuffer; 1102 size = newsize; 1103 } 1104 1105 if (cp[j] == '\\') { 1106 strlcpy(hex, cp + j + 1, sizeof(hex)); 1107 buffer[i] = (char)strtoumax(hex, NULL, 16); 1108 j += 3; 1109 } else { 1110 buffer[i] = cp[j]; 1111 j++; 1112 } 1113 } 1114 1115 return buffer; 1116 } 1117 int 1118 aldap_get_errno(struct aldap *a, const char **estr) 1119 { 1120 switch (a->err) { 1121 case ALDAP_ERR_SUCCESS: 1122 *estr = "success"; 1123 break; 1124 case ALDAP_ERR_PARSER_ERROR: 1125 *estr = "parser failed"; 1126 break; 1127 case ALDAP_ERR_INVALID_FILTER: 1128 *estr = "invalid filter"; 1129 break; 1130 case ALDAP_ERR_OPERATION_FAILED: 1131 *estr = "operation failed"; 1132 break; 1133 default: 1134 *estr = "unknown"; 1135 break; 1136 } 1137 return (a->err); 1138 } 1139