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