1 /* $Id: aldap.c,v 1.28 2011/08/28 16:37:28 aschrijver Exp $ */ 2 /* $OpenBSD: aldap.c,v 1.28 2011/08/28 16:37:28 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 ber_free(&al->ber); 59 free(al); 60 61 return (0); 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; 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.attrs) != 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; 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_attrs(struct aldap_message *msg) 316 { 317 int i; 318 struct ber_element *a; 319 320 if (msg->body.search.attrs == NULL) 321 return (-1); 322 323 for (i = 0, a = msg->body.search.attrs; 324 a != NULL && ber_get_eoc(a) != 0; 325 i++, a = a->be_next) 326 ; 327 328 return i; 329 } 330 331 int 332 aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues) 333 { 334 struct ber_element *b, *c; 335 char *key; 336 char **ret; 337 338 if (msg->body.search.attrs == NULL) 339 goto fail; 340 341 if (ber_scanf_elements(msg->body.search.attrs, "{s(e)}e", 342 &key, &b, &c) != 0) 343 goto fail; 344 345 msg->body.search.iter = msg->body.search.attrs->be_next; 346 347 if ((ret = aldap_get_stringset(b)) == NULL) 348 goto fail; 349 350 (*outvalues) = ret; 351 (*outkey) = utoa(key); 352 353 return (1); 354 fail: 355 (*outkey) = NULL; 356 (*outvalues) = NULL; 357 return (-1); 358 } 359 360 int 361 aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues) 362 { 363 struct ber_element *a, *b; 364 char *key; 365 char **ret; 366 367 if (msg->body.search.iter == NULL) 368 goto notfound; 369 370 LDAP_DEBUG("attr", msg->body.search.iter); 371 372 if (ber_get_eoc(msg->body.search.iter) == 0) 373 goto notfound; 374 375 if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) 376 != 0) 377 goto fail; 378 379 msg->body.search.iter = msg->body.search.iter->be_next; 380 381 if ((ret = aldap_get_stringset(a)) == NULL) 382 goto fail; 383 384 (*outvalues) = ret; 385 (*outkey) = utoa(key); 386 387 return (1); 388 fail: 389 notfound: 390 (*outkey) = NULL; 391 (*outvalues) = NULL; 392 return (-1); 393 } 394 395 int 396 aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues) 397 { 398 struct ber_element *a, *b; 399 char *descr = NULL; 400 char **ret; 401 402 if (msg->body.search.attrs == NULL) 403 return (-1); 404 405 LDAP_DEBUG("attr", msg->body.search.attrs); 406 407 for (a = msg->body.search.attrs;;) { 408 if (a == NULL) 409 goto notfound; 410 if (ber_get_eoc(a) == 0) 411 goto notfound; 412 if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) 413 goto fail; 414 if (strcasecmp(descr, inkey) == 0) 415 goto attrfound; 416 a = a->be_next; 417 } 418 419 attrfound: 420 if ((ret = aldap_get_stringset(b)) == NULL) 421 goto fail; 422 423 (*outvalues) = ret; 424 425 return (1); 426 fail: 427 notfound: 428 (*outvalues) = NULL; 429 return (-1); 430 } 431 432 int 433 aldap_free_attr(char **values) 434 { 435 int i; 436 437 if (values == NULL) 438 return -1; 439 440 for (i = 0; values[i] != NULL; i++) 441 free(values[i]); 442 443 free(values); 444 445 return (1); 446 } 447 448 #if 0 449 void 450 aldap_free_url(struct aldap_url *lu) 451 { 452 free(lu->buffer); 453 free(lu->filter); 454 } 455 456 int 457 aldap_parse_url(char *url, struct aldap_url *lu) 458 { 459 char *p, *forward, *forward2; 460 const char *errstr = NULL; 461 int i; 462 463 if ((lu->buffer = p = strdup(url)) == NULL) 464 return (-1); 465 466 /* protocol */ 467 if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0) 468 goto fail; 469 lu->protocol = LDAP; 470 p += strlen(LDAP_URL); 471 472 /* host and optional port */ 473 if ((forward = strchr(p, '/')) != NULL) 474 *forward = '\0'; 475 /* find the optional port */ 476 if ((forward2 = strchr(p, ':')) != NULL) { 477 *forward2 = '\0'; 478 /* if a port is given */ 479 if (*(forward2+1) != '\0') { 480 #define PORT_MAX UINT16_MAX 481 lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr); 482 if (errstr) 483 goto fail; 484 } 485 } 486 /* fail if no host is given */ 487 if (strlen(p) == 0) 488 goto fail; 489 lu->host = p; 490 if (forward == NULL) 491 goto done; 492 /* p is assigned either a pointer to a character or to '\0' */ 493 p = ++forward; 494 if (strlen(p) == 0) 495 goto done; 496 497 /* dn */ 498 if ((forward = strchr(p, '?')) != NULL) 499 *forward = '\0'; 500 lu->dn = p; 501 if (forward == NULL) 502 goto done; 503 /* p is assigned either a pointer to a character or to '\0' */ 504 p = ++forward; 505 if (strlen(p) == 0) 506 goto done; 507 508 /* attributes */ 509 if ((forward = strchr(p, '?')) != NULL) 510 *forward = '\0'; 511 for (i = 0; i < MAXATTR; i++) { 512 if ((forward2 = strchr(p, ',')) == NULL) { 513 if (strlen(p) == 0) 514 break; 515 lu->attributes[i] = p; 516 break; 517 } 518 *forward2 = '\0'; 519 lu->attributes[i] = p; 520 p = ++forward2; 521 } 522 if (forward == NULL) 523 goto done; 524 /* p is assigned either a pointer to a character or to '\0' */ 525 p = ++forward; 526 if (strlen(p) == 0) 527 goto done; 528 529 /* scope */ 530 if ((forward = strchr(p, '?')) != NULL) 531 *forward = '\0'; 532 if (strcmp(p, "base") == 0) 533 lu->scope = LDAP_SCOPE_BASE; 534 else if (strcmp(p, "one") == 0) 535 lu->scope = LDAP_SCOPE_ONELEVEL; 536 else if (strcmp(p, "sub") == 0) 537 lu->scope = LDAP_SCOPE_SUBTREE; 538 else 539 goto fail; 540 if (forward == NULL) 541 goto done; 542 p = ++forward; 543 if (strlen(p) == 0) 544 goto done; 545 546 /* filter */ 547 if (p) 548 lu->filter = p; 549 done: 550 free(url); 551 return (1); 552 fail: 553 free(lu->buffer); 554 lu->buffer = NULL; 555 return (-1); 556 } 557 558 int 559 aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit, 560 int timelimit) 561 { 562 struct aldap_url *lu; 563 564 if ((lu = calloc(1, sizeof(*lu))) == NULL) 565 return (-1); 566 567 if (aldap_parse_url(url, lu)) 568 goto fail; 569 570 if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes, 571 typesonly, sizelimit, timelimit) == -1) 572 goto fail; 573 574 aldap_free_url(lu); 575 return (ldap->msgid); 576 fail: 577 aldap_free_url(lu); 578 return (-1); 579 } 580 #endif /* 0 */ 581 582 /* 583 * internal functions 584 */ 585 586 char ** 587 aldap_get_stringset(struct ber_element *elm) 588 { 589 struct ber_element *a; 590 int i; 591 char **ret; 592 char *s; 593 594 if (elm->be_type != BER_TYPE_OCTETSTRING) 595 return NULL; 596 597 for (a = elm, i = 1; i > 0 && a != NULL && a->be_type == 598 BER_TYPE_OCTETSTRING; a = a->be_next, i++) 599 ; 600 if (i == 1) 601 return NULL; 602 603 if ((ret = calloc(i + 1, sizeof(char *))) == NULL) 604 return NULL; 605 606 for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING; 607 a = a->be_next, i++) { 608 609 ber_get_string(a, &s); 610 ret[i] = utoa(s); 611 } 612 ret[i + 1] = NULL; 613 614 return ret; 615 } 616 617 /* 618 * Base case for ldap_do_parse_search_filter 619 * 620 * returns: 621 * struct ber_element *, ber_element tree 622 * NULL, parse failed 623 */ 624 static struct ber_element * 625 ldap_parse_search_filter(struct ber_element *ber, char *filter) 626 { 627 struct ber_element *elm; 628 char *cp; 629 630 cp = filter; 631 632 if (cp == NULL || *cp == '\0') { 633 errno = EINVAL; 634 return (NULL); 635 } 636 637 if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) 638 return (NULL); 639 640 if (*cp != '\0') { 641 ber_free_elements(elm); 642 ber_link_elements(ber, NULL); 643 errno = EINVAL; 644 return (NULL); 645 } 646 647 return (elm); 648 } 649 650 /* 651 * Translate RFC4515 search filter string into ber_element tree 652 * 653 * returns: 654 * struct ber_element *, ber_element tree 655 * NULL, parse failed 656 * 657 * notes: 658 * when cp is passed to a recursive invocation, it is updated 659 * to point one character beyond the filter that was passed 660 * i.e., cp jumps to "(filter)" upon return 661 * ^ 662 * goto's used to discriminate error-handling based on error type 663 * doesn't handle extended filters (yet) 664 * 665 */ 666 static struct ber_element * 667 ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) 668 { 669 struct ber_element *elm, *root = NULL; 670 char *attr_desc, *attr_val, *parsed_val, *cp; 671 size_t len; 672 unsigned long type; 673 674 root = NULL; 675 676 /* cpp should pass in pointer to opening parenthesis of "(filter)" */ 677 cp = *cpp; 678 if (*cp != '(') 679 goto syntaxfail; 680 681 switch (*++cp) { 682 case '&': /* AND */ 683 case '|': /* OR */ 684 if (*cp == '&') 685 type = LDAP_FILT_AND; 686 else 687 type = LDAP_FILT_OR; 688 689 if ((elm = ber_add_set(prev)) == NULL) 690 goto callfail; 691 root = elm; 692 ber_set_header(elm, BER_CLASS_CONTEXT, type); 693 694 if (*++cp != '(') /* opening `(` of filter */ 695 goto syntaxfail; 696 697 while (*cp == '(') { 698 if ((elm = 699 ldap_do_parse_search_filter(elm, &cp)) == NULL) 700 goto bad; 701 } 702 703 if (*cp != ')') /* trailing `)` of filter */ 704 goto syntaxfail; 705 break; 706 707 case '!': /* NOT */ 708 if ((root = ber_add_sequence(prev)) == NULL) 709 goto callfail; 710 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT); 711 712 cp++; /* now points to sub-filter */ 713 if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL) 714 goto bad; 715 716 if (*cp != ')') /* trailing `)` of filter */ 717 goto syntaxfail; 718 break; 719 720 default: /* SIMPLE || PRESENCE */ 721 attr_desc = cp; 722 723 len = strcspn(cp, "()<>~="); 724 cp += len; 725 switch (*cp) { 726 case '~': 727 type = LDAP_FILT_APPR; 728 cp++; 729 break; 730 case '<': 731 type = LDAP_FILT_LE; 732 cp++; 733 break; 734 case '>': 735 type = LDAP_FILT_GE; 736 cp++; 737 break; 738 case '=': 739 type = LDAP_FILT_EQ; /* assume EQ until disproven */ 740 break; 741 case '(': 742 case ')': 743 default: 744 goto syntaxfail; 745 } 746 attr_val = ++cp; 747 748 /* presence filter */ 749 if (strncmp(attr_val, "*)", 2) == 0) { 750 cp++; /* point to trailing `)` */ 751 if ((root = 752 ber_add_nstring(prev, attr_desc, len)) == NULL) 753 goto bad; 754 755 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES); 756 break; 757 } 758 759 if ((root = ber_add_sequence(prev)) == NULL) 760 goto callfail; 761 ber_set_header(root, BER_CLASS_CONTEXT, type); 762 763 if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL) 764 goto callfail; 765 766 len = strcspn(attr_val, "*)"); 767 if (len == 0 && *cp != '*') 768 goto syntaxfail; 769 cp += len; 770 if (*cp == '\0') 771 goto syntaxfail; 772 773 if (*cp == '*') { /* substring filter */ 774 int initial; 775 776 cp = attr_val; 777 778 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS); 779 780 if ((elm = ber_add_sequence(elm)) == NULL) 781 goto callfail; 782 783 for (initial = 1;; cp++, initial = 0) { 784 attr_val = cp; 785 786 len = strcspn(attr_val, "*)"); 787 if (len == 0) { 788 if (*cp == ')') 789 break; 790 else 791 continue; 792 } 793 cp += len; 794 if (*cp == '\0') 795 goto syntaxfail; 796 797 if (initial) 798 type = LDAP_FILT_SUBS_INIT; 799 else if (*cp == ')') 800 type = LDAP_FILT_SUBS_FIN; 801 else 802 type = LDAP_FILT_SUBS_ANY; 803 804 if ((parsed_val = parseval(attr_val, len)) == 805 NULL) 806 goto callfail; 807 elm = ber_add_nstring(elm, parsed_val, 808 strlen(parsed_val)); 809 free(parsed_val); 810 if (elm == NULL) 811 goto callfail; 812 ber_set_header(elm, BER_CLASS_CONTEXT, type); 813 if (type == LDAP_FILT_SUBS_FIN) 814 break; 815 } 816 break; 817 } 818 819 if ((parsed_val = parseval(attr_val, len)) == NULL) 820 goto callfail; 821 elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val)); 822 free(parsed_val); 823 if (elm == NULL) 824 goto callfail; 825 break; 826 } 827 828 cp++; /* now points one char beyond the trailing `)` */ 829 830 *cpp = cp; 831 return (root); 832 833 syntaxfail: /* XXX -- error reporting */ 834 callfail: 835 bad: 836 if (root != NULL) 837 ber_free_elements(root); 838 ber_link_elements(prev, NULL); 839 return (NULL); 840 } 841 842 #ifdef DEBUG 843 /* 844 * Display a list of ber elements. 845 * 846 */ 847 void 848 ldap_debug_elements(struct ber_element *root) 849 { 850 static int indent = 0; 851 long long v; 852 int d; 853 char *buf; 854 size_t len; 855 u_int i; 856 int constructed; 857 struct ber_oid o; 858 859 /* calculate lengths */ 860 ber_calc_len(root); 861 862 switch (root->be_encoding) { 863 case BER_TYPE_SEQUENCE: 864 case BER_TYPE_SET: 865 constructed = root->be_encoding; 866 break; 867 default: 868 constructed = 0; 869 break; 870 } 871 872 fprintf(stderr, "%*slen %lu ", indent, "", root->be_len); 873 switch (root->be_class) { 874 case BER_CLASS_UNIVERSAL: 875 fprintf(stderr, "class: universal(%u) type: ", root->be_class); 876 switch (root->be_type) { 877 case BER_TYPE_EOC: 878 fprintf(stderr, "end-of-content"); 879 break; 880 case BER_TYPE_BOOLEAN: 881 fprintf(stderr, "boolean"); 882 break; 883 case BER_TYPE_INTEGER: 884 fprintf(stderr, "integer"); 885 break; 886 case BER_TYPE_BITSTRING: 887 fprintf(stderr, "bit-string"); 888 break; 889 case BER_TYPE_OCTETSTRING: 890 fprintf(stderr, "octet-string"); 891 break; 892 case BER_TYPE_NULL: 893 fprintf(stderr, "null"); 894 break; 895 case BER_TYPE_OBJECT: 896 fprintf(stderr, "object"); 897 break; 898 case BER_TYPE_ENUMERATED: 899 fprintf(stderr, "enumerated"); 900 break; 901 case BER_TYPE_SEQUENCE: 902 fprintf(stderr, "sequence"); 903 break; 904 case BER_TYPE_SET: 905 fprintf(stderr, "set"); 906 break; 907 } 908 break; 909 case BER_CLASS_APPLICATION: 910 fprintf(stderr, "class: application(%u) type: ", 911 root->be_class); 912 switch (root->be_type) { 913 case LDAP_REQ_BIND: 914 fprintf(stderr, "bind"); 915 break; 916 case LDAP_RES_BIND: 917 fprintf(stderr, "bind"); 918 break; 919 case LDAP_REQ_UNBIND_30: 920 break; 921 case LDAP_REQ_SEARCH: 922 fprintf(stderr, "search"); 923 break; 924 case LDAP_RES_SEARCH_ENTRY: 925 fprintf(stderr, "search_entry"); 926 break; 927 case LDAP_RES_SEARCH_RESULT: 928 fprintf(stderr, "search_result"); 929 break; 930 case LDAP_REQ_MODIFY: 931 fprintf(stderr, "modify"); 932 break; 933 case LDAP_RES_MODIFY: 934 fprintf(stderr, "modify"); 935 break; 936 case LDAP_REQ_ADD: 937 fprintf(stderr, "add"); 938 break; 939 case LDAP_RES_ADD: 940 fprintf(stderr, "add"); 941 break; 942 case LDAP_REQ_DELETE_30: 943 fprintf(stderr, "delete"); 944 break; 945 case LDAP_RES_DELETE: 946 fprintf(stderr, "delete"); 947 break; 948 case LDAP_REQ_MODRDN: 949 fprintf(stderr, "modrdn"); 950 break; 951 case LDAP_RES_MODRDN: 952 fprintf(stderr, "modrdn"); 953 break; 954 case LDAP_REQ_COMPARE: 955 fprintf(stderr, "compare"); 956 break; 957 case LDAP_RES_COMPARE: 958 fprintf(stderr, "compare"); 959 break; 960 case LDAP_REQ_ABANDON_30: 961 fprintf(stderr, "abandon"); 962 break; 963 } 964 break; 965 case BER_CLASS_PRIVATE: 966 fprintf(stderr, "class: private(%u) type: ", root->be_class); 967 fprintf(stderr, "encoding (%lu) type: ", root->be_encoding); 968 break; 969 case BER_CLASS_CONTEXT: 970 /* XXX: this is not correct */ 971 fprintf(stderr, "class: context(%u) type: ", root->be_class); 972 switch(root->be_type) { 973 case LDAP_AUTH_SIMPLE: 974 fprintf(stderr, "auth simple"); 975 break; 976 } 977 break; 978 default: 979 fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class); 980 break; 981 } 982 fprintf(stderr, "(%lu) encoding %lu ", 983 root->be_type, root->be_encoding); 984 985 if (constructed) 986 root->be_encoding = constructed; 987 988 switch (root->be_encoding) { 989 case BER_TYPE_BOOLEAN: 990 if (ber_get_boolean(root, &d) == -1) { 991 fprintf(stderr, "<INVALID>\n"); 992 break; 993 } 994 fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d); 995 break; 996 case BER_TYPE_INTEGER: 997 if (ber_get_integer(root, &v) == -1) { 998 fprintf(stderr, "<INVALID>\n"); 999 break; 1000 } 1001 fprintf(stderr, "value %lld\n", v); 1002 break; 1003 case BER_TYPE_ENUMERATED: 1004 if (ber_get_enumerated(root, &v) == -1) { 1005 fprintf(stderr, "<INVALID>\n"); 1006 break; 1007 } 1008 fprintf(stderr, "value %lld\n", v); 1009 break; 1010 case BER_TYPE_BITSTRING: 1011 if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { 1012 fprintf(stderr, "<INVALID>\n"); 1013 break; 1014 } 1015 fprintf(stderr, "hexdump "); 1016 for (i = 0; i < len; i++) 1017 fprintf(stderr, "%02x", buf[i]); 1018 fprintf(stderr, "\n"); 1019 break; 1020 case BER_TYPE_OBJECT: 1021 if (ber_get_oid(root, &o) == -1) { 1022 fprintf(stderr, "<INVALID>\n"); 1023 break; 1024 } 1025 fprintf(stderr, "\n"); 1026 break; 1027 case BER_TYPE_OCTETSTRING: 1028 if (ber_get_nstring(root, (void *)&buf, &len) == -1) { 1029 fprintf(stderr, "<INVALID>\n"); 1030 break; 1031 } 1032 fprintf(stderr, "string \"%.*s\"\n", len, buf); 1033 break; 1034 case BER_TYPE_NULL: /* no payload */ 1035 case BER_TYPE_EOC: 1036 case BER_TYPE_SEQUENCE: 1037 case BER_TYPE_SET: 1038 default: 1039 fprintf(stderr, "\n"); 1040 break; 1041 } 1042 1043 if (constructed && root->be_sub) { 1044 indent += 2; 1045 ldap_debug_elements(root->be_sub); 1046 indent -= 2; 1047 } 1048 if (root->be_next) 1049 ldap_debug_elements(root->be_next); 1050 } 1051 #endif 1052 1053 /* 1054 * Convert UTF-8 to ASCII. 1055 * notes: 1056 * non-ASCII characters are displayed as '?' 1057 * the argument u should be a NULL terminated sequence of UTF-8 bytes. 1058 */ 1059 char * 1060 utoa(char *u) 1061 { 1062 int len, i, j; 1063 char *str; 1064 1065 /* calculate the length to allocate */ 1066 for (len = 0, i = 0; u[i] != '\0'; ) { 1067 if ((u[i] & 0xF0) == 0xF0) 1068 i += 4; 1069 else if ((u[i] & 0xE0) == 0xE0) 1070 i += 3; 1071 else if ((u[i] & 0xC0) == 0xC0) 1072 i += 2; 1073 else 1074 i += 1; 1075 len++; 1076 } 1077 1078 if ((str = calloc(len + 1, sizeof(char))) == NULL) 1079 return NULL; 1080 1081 /* copy the ASCII characters to the newly allocated string */ 1082 for (i = 0, j = 0; u[i] != '\0'; j++) { 1083 if ((u[i] & 0xF0) == 0xF0) { 1084 str[j] = '?'; 1085 i += 4; 1086 } else if ((u[i] & 0xE0) == 0xE0) { 1087 str[j] = '?'; 1088 i += 3; 1089 } else if ((u[i] & 0xC0) == 0xC0) { 1090 str[j] = '?'; 1091 i += 2; 1092 } else { 1093 str[j] = u[i]; 1094 i += 1; 1095 } 1096 } 1097 1098 return str; 1099 } 1100 1101 /* 1102 * Parse a LDAP value 1103 * notes: 1104 * the argument u should be a NULL terminated sequence of ASCII bytes. 1105 */ 1106 char * 1107 parseval(char *p, size_t len) 1108 { 1109 char hex[3]; 1110 char *cp = p, *buffer, *newbuffer; 1111 size_t size, newsize, i, j; 1112 1113 size = 50; 1114 if ((buffer = calloc(1, size)) == NULL) 1115 return NULL; 1116 1117 for (i = j = 0; j < len; i++) { 1118 if (i >= size) { 1119 newsize = size + 1024; 1120 if ((newbuffer = realloc(buffer, newsize)) == NULL) { 1121 free(buffer); 1122 return (NULL); 1123 } 1124 buffer = newbuffer; 1125 size = newsize; 1126 } 1127 1128 if (cp[j] == '\\') { 1129 strlcpy(hex, cp + j + 1, sizeof(hex)); 1130 buffer[i] = (char)strtoumax(hex, NULL, 16); 1131 j += 3; 1132 } else { 1133 buffer[i] = cp[j]; 1134 j++; 1135 } 1136 } 1137 1138 return buffer; 1139 } 1140 1141 int 1142 aldap_get_errno(struct aldap *a, const char **estr) 1143 { 1144 switch (a->err) { 1145 case ALDAP_ERR_SUCCESS: 1146 *estr = "success"; 1147 break; 1148 case ALDAP_ERR_PARSER_ERROR: 1149 *estr = "parser failed"; 1150 break; 1151 case ALDAP_ERR_INVALID_FILTER: 1152 *estr = "invalid filter"; 1153 break; 1154 case ALDAP_ERR_OPERATION_FAILED: 1155 *estr = "operation failed"; 1156 break; 1157 default: 1158 *estr = "unknown"; 1159 break; 1160 } 1161 return (a->err); 1162 } 1163