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