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