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, i++) { 719 720 ber_get_string(a, &s); 721 ret[i] = utoa(s); 722 } 723 ret[i + 1] = NULL; 724 725 return ret; 726 } 727 728 /* 729 * Base case for ldap_do_parse_search_filter 730 * 731 * returns: 732 * struct ber_element *, ber_element tree 733 * NULL, parse failed 734 */ 735 static struct ber_element * 736 ldap_parse_search_filter(struct ber_element *ber, char *filter) 737 { 738 struct ber_element *elm; 739 char *cp; 740 741 cp = filter; 742 743 if (cp == NULL || *cp == '\0') { 744 errno = EINVAL; 745 return (NULL); 746 } 747 748 if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) 749 return (NULL); 750 751 if (*cp != '\0') { 752 ber_free_elements(elm); 753 ber_link_elements(ber, NULL); 754 errno = EINVAL; 755 return (NULL); 756 } 757 758 return (elm); 759 } 760 761 /* 762 * Translate RFC4515 search filter string into ber_element tree 763 * 764 * returns: 765 * struct ber_element *, ber_element tree 766 * NULL, parse failed 767 * 768 * notes: 769 * when cp is passed to a recursive invocation, it is updated 770 * to point one character beyond the filter that was passed 771 * i.e., cp jumps to "(filter)" upon return 772 * ^ 773 * goto's used to discriminate error-handling based on error type 774 * doesn't handle extended filters (yet) 775 * 776 */ 777 static struct ber_element * 778 ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) 779 { 780 struct ber_element *elm, *root = NULL; 781 char *attr_desc, *attr_val, *parsed_val, *cp; 782 size_t len; 783 unsigned long type; 784 785 root = NULL; 786 787 /* cpp should pass in pointer to opening parenthesis of "(filter)" */ 788 cp = *cpp; 789 if (*cp != '(') 790 goto syntaxfail; 791 792 switch (*++cp) { 793 case '&': /* AND */ 794 case '|': /* OR */ 795 if (*cp == '&') 796 type = LDAP_FILT_AND; 797 else 798 type = LDAP_FILT_OR; 799 800 if ((elm = ber_add_set(prev)) == NULL) 801 goto callfail; 802 root = elm; 803 ber_set_header(elm, BER_CLASS_CONTEXT, type); 804 805 if (*++cp != '(') /* opening `(` of filter */ 806 goto syntaxfail; 807 808 while (*cp == '(') { 809 if ((elm = 810 ldap_do_parse_search_filter(elm, &cp)) == NULL) 811 goto bad; 812 } 813 814 if (*cp != ')') /* trailing `)` of filter */ 815 goto syntaxfail; 816 break; 817 818 case '!': /* NOT */ 819 if ((root = ber_add_sequence(prev)) == NULL) 820 goto callfail; 821 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT); 822 823 cp++; /* now points to sub-filter */ 824 if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL) 825 goto bad; 826 827 if (*cp != ')') /* trailing `)` of filter */ 828 goto syntaxfail; 829 break; 830 831 default: /* SIMPLE || PRESENCE */ 832 attr_desc = cp; 833 834 len = strcspn(cp, "()<>~="); 835 cp += len; 836 switch (*cp) { 837 case '~': 838 type = LDAP_FILT_APPR; 839 cp++; 840 break; 841 case '<': 842 type = LDAP_FILT_LE; 843 cp++; 844 break; 845 case '>': 846 type = LDAP_FILT_GE; 847 cp++; 848 break; 849 case '=': 850 type = LDAP_FILT_EQ; /* assume EQ until disproven */ 851 break; 852 case '(': 853 case ')': 854 default: 855 goto syntaxfail; 856 } 857 attr_val = ++cp; 858 859 /* presence filter */ 860 if (strncmp(attr_val, "*)", 2) == 0) { 861 cp++; /* point to trailing `)` */ 862 if ((root = 863 ber_add_nstring(prev, attr_desc, len)) == NULL) 864 goto bad; 865 866 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES); 867 break; 868 } 869 870 if ((root = ber_add_sequence(prev)) == NULL) 871 goto callfail; 872 ber_set_header(root, BER_CLASS_CONTEXT, type); 873 874 if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL) 875 goto callfail; 876 877 len = strcspn(attr_val, "*)"); 878 if (len == 0 && *cp != '*') 879 goto syntaxfail; 880 cp += len; 881 if (*cp == '\0') 882 goto syntaxfail; 883 884 if (*cp == '*') { /* substring filter */ 885 int initial; 886 887 cp = attr_val; 888 889 ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS); 890 891 if ((elm = ber_add_sequence(elm)) == NULL) 892 goto callfail; 893 894 for (initial = 1;; cp++, initial = 0) { 895 attr_val = cp; 896 897 len = strcspn(attr_val, "*)"); 898 if (len == 0) { 899 if (*cp == ')') 900 break; 901 else 902 continue; 903 } 904 cp += len; 905 if (*cp == '\0') 906 goto syntaxfail; 907 908 if (initial) 909 type = LDAP_FILT_SUBS_INIT; 910 else if (*cp == ')') 911 type = LDAP_FILT_SUBS_FIN; 912 else 913 type = LDAP_FILT_SUBS_ANY; 914 915 if ((parsed_val = parseval(attr_val, len)) == 916 NULL) 917 goto callfail; 918 elm = ber_add_nstring(elm, parsed_val, 919 strlen(parsed_val)); 920 free(parsed_val); 921 if (elm == NULL) 922 goto callfail; 923 ber_set_header(elm, BER_CLASS_CONTEXT, type); 924 if (type == LDAP_FILT_SUBS_FIN) 925 break; 926 } 927 break; 928 } 929 930 if ((parsed_val = parseval(attr_val, len)) == NULL) 931 goto callfail; 932 elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val)); 933 free(parsed_val); 934 if (elm == NULL) 935 goto callfail; 936 break; 937 } 938 939 cp++; /* now points one char beyond the trailing `)` */ 940 941 *cpp = cp; 942 return (root); 943 944 syntaxfail: /* XXX -- error reporting */ 945 callfail: 946 bad: 947 if (root != NULL) 948 ber_free_elements(root); 949 ber_link_elements(prev, NULL); 950 return (NULL); 951 } 952 953 #ifdef DEBUG 954 /* 955 * Display a list of ber elements. 956 * 957 */ 958 void 959 ldap_debug_elements(struct ber_element *root) 960 { 961 static int indent = 0; 962 long long v; 963 int d; 964 char *buf; 965 size_t len; 966 u_int i; 967 int constructed; 968 struct ber_oid o; 969 970 /* calculate lengths */ 971 ber_calc_len(root); 972 973 switch (root->be_encoding) { 974 case BER_TYPE_SEQUENCE: 975 case BER_TYPE_SET: 976 constructed = root->be_encoding; 977 break; 978 default: 979 constructed = 0; 980 break; 981 } 982 983 fprintf(stderr, "%*slen %lu ", indent, "", root->be_len); 984 switch (root->be_class) { 985 case BER_CLASS_UNIVERSAL: 986 fprintf(stderr, "class: universal(%u) type: ", root->be_class); 987 switch (root->be_type) { 988 case BER_TYPE_EOC: 989 fprintf(stderr, "end-of-content"); 990 break; 991 case BER_TYPE_BOOLEAN: 992 fprintf(stderr, "boolean"); 993 break; 994 case BER_TYPE_INTEGER: 995 fprintf(stderr, "integer"); 996 break; 997 case BER_TYPE_BITSTRING: 998 fprintf(stderr, "bit-string"); 999 break; 1000 case BER_TYPE_OCTETSTRING: 1001 fprintf(stderr, "octet-string"); 1002 break; 1003 case BER_TYPE_NULL: 1004 fprintf(stderr, "null"); 1005 break; 1006 case BER_TYPE_OBJECT: 1007 fprintf(stderr, "object"); 1008 break; 1009 case BER_TYPE_ENUMERATED: 1010 fprintf(stderr, "enumerated"); 1011 break; 1012 case BER_TYPE_SEQUENCE: 1013 fprintf(stderr, "sequence"); 1014 break; 1015 case BER_TYPE_SET: 1016 fprintf(stderr, "set"); 1017 break; 1018 } 1019 break; 1020 case BER_CLASS_APPLICATION: 1021 fprintf(stderr, "class: application(%u) type: ", 1022 root->be_class); 1023 switch (root->be_type) { 1024 case LDAP_REQ_BIND: 1025 fprintf(stderr, "bind"); 1026 break; 1027 case LDAP_RES_BIND: 1028 fprintf(stderr, "bind"); 1029 break; 1030 case LDAP_REQ_UNBIND_30: 1031 break; 1032 case LDAP_REQ_SEARCH: 1033 fprintf(stderr, "search"); 1034 break; 1035 case LDAP_RES_SEARCH_ENTRY: 1036 fprintf(stderr, "search_entry"); 1037 break; 1038 case LDAP_RES_SEARCH_RESULT: 1039 fprintf(stderr, "search_result"); 1040 break; 1041 case LDAP_REQ_MODIFY: 1042 fprintf(stderr, "modify"); 1043 break; 1044 case LDAP_RES_MODIFY: 1045 fprintf(stderr, "modify"); 1046 break; 1047 case LDAP_REQ_ADD: 1048 fprintf(stderr, "add"); 1049 break; 1050 case LDAP_RES_ADD: 1051 fprintf(stderr, "add"); 1052 break; 1053 case LDAP_REQ_DELETE_30: 1054 fprintf(stderr, "delete"); 1055 break; 1056 case LDAP_RES_DELETE: 1057 fprintf(stderr, "delete"); 1058 break; 1059 case LDAP_REQ_MODRDN: 1060 fprintf(stderr, "modrdn"); 1061 break; 1062 case LDAP_RES_MODRDN: 1063 fprintf(stderr, "modrdn"); 1064 break; 1065 case LDAP_REQ_COMPARE: 1066 fprintf(stderr, "compare"); 1067 break; 1068 case LDAP_RES_COMPARE: 1069 fprintf(stderr, "compare"); 1070 break; 1071 case LDAP_REQ_ABANDON_30: 1072 fprintf(stderr, "abandon"); 1073 break; 1074 } 1075 break; 1076 case BER_CLASS_PRIVATE: 1077 fprintf(stderr, "class: private(%u) type: ", root->be_class); 1078 fprintf(stderr, "encoding (%lu) type: ", root->be_encoding); 1079 break; 1080 case BER_CLASS_CONTEXT: 1081 /* XXX: this is not correct */ 1082 fprintf(stderr, "class: context(%u) type: ", root->be_class); 1083 switch(root->be_type) { 1084 case LDAP_AUTH_SIMPLE: 1085 fprintf(stderr, "auth simple"); 1086 break; 1087 } 1088 break; 1089 default: 1090 fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class); 1091 break; 1092 } 1093 fprintf(stderr, "(%lu) encoding %lu ", 1094 root->be_type, root->be_encoding); 1095 1096 if (constructed) 1097 root->be_encoding = constructed; 1098 1099 switch (root->be_encoding) { 1100 case BER_TYPE_BOOLEAN: 1101 if (ber_get_boolean(root, &d) == -1) { 1102 fprintf(stderr, "<INVALID>\n"); 1103 break; 1104 } 1105 fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d); 1106 break; 1107 case BER_TYPE_INTEGER: 1108 if (ber_get_integer(root, &v) == -1) { 1109 fprintf(stderr, "<INVALID>\n"); 1110 break; 1111 } 1112 fprintf(stderr, "value %lld\n", v); 1113 break; 1114 case BER_TYPE_ENUMERATED: 1115 if (ber_get_enumerated(root, &v) == -1) { 1116 fprintf(stderr, "<INVALID>\n"); 1117 break; 1118 } 1119 fprintf(stderr, "value %lld\n", v); 1120 break; 1121 case BER_TYPE_BITSTRING: 1122 if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { 1123 fprintf(stderr, "<INVALID>\n"); 1124 break; 1125 } 1126 fprintf(stderr, "hexdump "); 1127 for (i = 0; i < len; i++) 1128 fprintf(stderr, "%02x", buf[i]); 1129 fprintf(stderr, "\n"); 1130 break; 1131 case BER_TYPE_OBJECT: 1132 if (ber_get_oid(root, &o) == -1) { 1133 fprintf(stderr, "<INVALID>\n"); 1134 break; 1135 } 1136 fprintf(stderr, "\n"); 1137 break; 1138 case BER_TYPE_OCTETSTRING: 1139 if (ber_get_nstring(root, (void *)&buf, &len) == -1) { 1140 fprintf(stderr, "<INVALID>\n"); 1141 break; 1142 } 1143 fprintf(stderr, "string \"%.*s\"\n", len, buf); 1144 break; 1145 case BER_TYPE_NULL: /* no payload */ 1146 case BER_TYPE_EOC: 1147 case BER_TYPE_SEQUENCE: 1148 case BER_TYPE_SET: 1149 default: 1150 fprintf(stderr, "\n"); 1151 break; 1152 } 1153 1154 if (constructed && root->be_sub) { 1155 indent += 2; 1156 ldap_debug_elements(root->be_sub); 1157 indent -= 2; 1158 } 1159 if (root->be_next) 1160 ldap_debug_elements(root->be_next); 1161 } 1162 #endif 1163 1164 /* 1165 * Strip UTF-8 down to ASCII without validation. 1166 * notes: 1167 * non-ASCII characters are displayed as '?' 1168 * the argument u should be a NULL terminated sequence of UTF-8 bytes. 1169 */ 1170 char * 1171 utoa(char *u) 1172 { 1173 int len, i, j; 1174 char *str; 1175 1176 /* calculate the length to allocate */ 1177 for (len = 0, i = 0; u[i] != '\0'; i++) 1178 if (!isu8cont(u[i])) 1179 len++; 1180 1181 if ((str = calloc(len + 1, sizeof(char))) == NULL) 1182 return NULL; 1183 1184 /* copy the ASCII characters to the newly allocated string */ 1185 for (i = 0, j = 0; u[i] != '\0'; i++) 1186 if (!isu8cont(u[i])) 1187 str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?'; 1188 1189 return str; 1190 } 1191 1192 static int 1193 isu8cont(unsigned char c) 1194 { 1195 return (c & (0x80 | 0x40)) == 0x80; 1196 } 1197 1198 /* 1199 * Parse a LDAP value 1200 * notes: 1201 * the argument u should be a NULL terminated sequence of ASCII bytes. 1202 */ 1203 char * 1204 parseval(char *p, size_t len) 1205 { 1206 char hex[3]; 1207 char *cp = p, *buffer, *newbuffer; 1208 size_t size, newsize, i, j; 1209 1210 size = 50; 1211 if ((buffer = calloc(1, size)) == NULL) 1212 return NULL; 1213 1214 for (i = j = 0; j < len; i++) { 1215 if (i >= size) { 1216 newsize = size + 1024; 1217 if ((newbuffer = realloc(buffer, newsize)) == NULL) { 1218 free(buffer); 1219 return (NULL); 1220 } 1221 buffer = newbuffer; 1222 size = newsize; 1223 } 1224 1225 if (cp[j] == '\\') { 1226 strlcpy(hex, cp + j + 1, sizeof(hex)); 1227 buffer[i] = (char)strtoumax(hex, NULL, 16); 1228 j += 3; 1229 } else { 1230 buffer[i] = cp[j]; 1231 j++; 1232 } 1233 } 1234 1235 return buffer; 1236 } 1237 1238 int 1239 aldap_get_errno(struct aldap *a, const char **estr) 1240 { 1241 switch (a->err) { 1242 case ALDAP_ERR_SUCCESS: 1243 *estr = "success"; 1244 break; 1245 case ALDAP_ERR_PARSER_ERROR: 1246 *estr = "parser failed"; 1247 break; 1248 case ALDAP_ERR_INVALID_FILTER: 1249 *estr = "invalid filter"; 1250 break; 1251 case ALDAP_ERR_OPERATION_FAILED: 1252 *estr = "operation failed"; 1253 break; 1254 default: 1255 *estr = "unknown"; 1256 break; 1257 } 1258 return (a->err); 1259 } 1260