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