1 /* $Id: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */ 2 /* $OpenBSD: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */ 3 /* $FreeBSD$ */ 4 5 /* 6 * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> 7 * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <errno.h> 23 #include <inttypes.h> 24 #include <string.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 28 #include "aldap.h" 29 30 #if 0 31 #define DEBUG 32 #endif 33 #define VERSION 3 34 35 static struct ber_element *ldap_parse_search_filter(struct ber_element *, 36 char *); 37 static struct ber_element *ldap_do_parse_search_filter( 38 struct ber_element *, char **); 39 char **aldap_get_stringset(struct ber_element *); 40 char *utoa(char *); 41 char *parseval(char *, size_t); 42 int aldap_create_page_control(struct ber_element *, 43 int, struct aldap_page_control *); 44 45 #ifdef DEBUG 46 void ldap_debug_elements(struct ber_element *); 47 #endif 48 49 #ifdef DEBUG 50 #define DPRINTF(x...) printf(x) 51 #define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0) 52 #else 53 #define DPRINTF(x...) do { } while (0) 54 #define LDAP_DEBUG(x, y) do { } while (0) 55 #endif 56 57 int 58 aldap_close(struct aldap *al) 59 { 60 if (close(al->ber.fd) == -1) 61 return (-1); 62 63 ber_free(&al->ber); 64 free(al); 65 66 return (0); 67 } 68 69 struct aldap * 70 aldap_init(int fd) 71 { 72 struct aldap *a; 73 74 if ((a = calloc(1, sizeof(*a))) == NULL) 75 return NULL; 76 a->ber.fd = fd; 77 78 return a; 79 } 80 81 int 82 aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) 83 { 84 struct ber_element *root = NULL, *elm; 85 int error; 86 87 if (binddn == NULL) 88 binddn = ""; 89 if (bindcred == NULL) 90 bindcred = ""; 91 92 if ((root = ber_add_sequence(NULL)) == NULL) 93 goto fail; 94 95 elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP, 96 (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred, 97 BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE); 98 if (elm == NULL) 99 goto fail; 100 101 LDAP_DEBUG("aldap_bind", root); 102 103 error = ber_write_elements(&ldap->ber, root); 104 ber_free_elements(root); 105 root = NULL; 106 if (error == -1) 107 goto fail; 108 109 return (ldap->msgid); 110 fail: 111 if (root != NULL) 112 ber_free_elements(root); 113 114 ldap->err = ALDAP_ERR_OPERATION_FAILED; 115 return (-1); 116 } 117 118 int 119 aldap_unbind(struct aldap *ldap) 120 { 121 struct ber_element *root = NULL, *elm; 122 int error; 123 124 if ((root = ber_add_sequence(NULL)) == NULL) 125 goto fail; 126 elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, 127 LDAP_REQ_UNBIND_30); 128 if (elm == NULL) 129 goto fail; 130 131 LDAP_DEBUG("aldap_unbind", root); 132 133 error = ber_write_elements(&ldap->ber, root); 134 ber_free_elements(root); 135 root = NULL; 136 if (error == -1) 137 goto fail; 138 139 return (ldap->msgid); 140 fail: 141 if (root != NULL) 142 ber_free_elements(root); 143 144 ldap->err = ALDAP_ERR_OPERATION_FAILED; 145 146 return (-1); 147 } 148 149 int 150 aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, 151 char **attrs, int typesonly, int sizelimit, int timelimit, 152 struct aldap_page_control *page) 153 { 154 struct ber_element *root = NULL, *ber, *c; 155 int i, error; 156 157 if ((root = ber_add_sequence(NULL)) == NULL) 158 goto fail; 159 160 ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, 161 (unsigned long) LDAP_REQ_SEARCH); 162 if (ber == NULL) { 163 ldap->err = ALDAP_ERR_OPERATION_FAILED; 164 goto fail; 165 } 166 167 c = ber; 168 ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope, 169 (long long)LDAP_DEREF_NEVER, sizelimit, 170 timelimit, typesonly); 171 if (ber == NULL) { 172 ldap->err = ALDAP_ERR_OPERATION_FAILED; 173 goto fail; 174 } 175 176 if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) { 177 ldap->err = ALDAP_ERR_PARSER_ERROR; 178 goto fail; 179 } 180 181 if ((ber = ber_add_sequence(ber)) == NULL) 182 goto fail; 183 if (attrs != NULL) 184 for (i = 0; attrs[i] != NULL; i++) { 185 if ((ber = ber_add_string(ber, attrs[i])) == NULL) 186 goto fail; 187 } 188 189 aldap_create_page_control(c, 100, page); 190 191 LDAP_DEBUG("aldap_search", root); 192 193 error = ber_write_elements(&ldap->ber, root); 194 ber_free_elements(root); 195 root = NULL; 196 if (error == -1) { 197 ldap->err = ALDAP_ERR_OPERATION_FAILED; 198 goto fail; 199 } 200 201 return (ldap->msgid); 202 203 fail: 204 if (root != NULL) 205 ber_free_elements(root); 206 207 return (-1); 208 } 209 210 int 211 aldap_create_page_control(struct ber_element *elm, int size, 212 struct aldap_page_control *page) 213 { 214 int len; 215 struct ber c; 216 struct ber_element *ber = NULL; 217 218 c.br_wbuf = NULL; 219 c.fd = -1; 220 221 ber = ber_add_sequence(NULL); 222 223 if (page == NULL) { 224 if (ber_printf_elements(ber, "ds", 50, "") == NULL) 225 goto fail; 226 } else { 227 if (ber_printf_elements(ber, "dx", 50, page->cookie, 228 page->cookie_len) == NULL) 229 goto fail; 230 } 231 232 if ((len = ber_write_elements(&c, ber)) < 1) 233 goto fail; 234 if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID, 235 c.br_wbuf, (size_t)len) == NULL) 236 goto fail; 237 238 ber_free_elements(ber); 239 ber_free(&c); 240 return len; 241 fail: 242 if (ber != NULL) 243 ber_free_elements(ber); 244 ber_free(&c); 245 246 return (-1); 247 } 248 249 struct aldap_message * 250 aldap_parse(struct aldap *ldap) 251 { 252 int class; 253 unsigned long type; 254 long long msgid = 0; 255 struct aldap_message *m; 256 struct ber_element *a = NULL, *ep; 257 258 if ((m = calloc(1, sizeof(struct aldap_message))) == NULL) 259 return NULL; 260 261 if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL) 262 goto parsefail; 263 264 LDAP_DEBUG("message", m->msg); 265 266 if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0) 267 goto parsefail; 268 m->msgid = msgid; 269 m->message_type = type; 270 m->protocol_op = a; 271 272 switch (m->message_type) { 273 case LDAP_RES_BIND: 274 case LDAP_RES_MODIFY: 275 case LDAP_RES_ADD: 276 case LDAP_RES_DELETE: 277 case LDAP_RES_MODRDN: 278 case LDAP_RES_COMPARE: 279 case LDAP_RES_SEARCH_RESULT: 280 if (ber_scanf_elements(m->protocol_op, "{EeSeSe", 281 &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0) 282 goto parsefail; 283 if (m->body.res.rescode == LDAP_REFERRAL) 284 if (ber_scanf_elements(a, "{e", &m->references) != 0) 285 goto parsefail; 286 if (m->msg->be_sub) { 287 for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) { 288 ber_scanf_elements(ep, "t", &class, &type); 289 if (class == 2 && type == 0) 290 m->page = aldap_parse_page_control(ep->be_sub->be_sub, 291 ep->be_sub->be_sub->be_len); 292 } 293 } else 294 m->page = NULL; 295 break; 296 case LDAP_RES_SEARCH_ENTRY: 297 if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn, 298 &m->body.search.attrs) != 0) 299 goto parsefail; 300 break; 301 case LDAP_RES_SEARCH_REFERENCE: 302 if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) 303 goto parsefail; 304 break; 305 } 306 307 return m; 308 parsefail: 309 ldap->err = ALDAP_ERR_PARSER_ERROR; 310 aldap_freemsg(m); 311 return NULL; 312 } 313 314 struct aldap_page_control * 315 aldap_parse_page_control(struct ber_element *control, size_t len) 316 { 317 char *oid, *s; 318 char *encoded; 319 struct ber b; 320 struct ber_element *elm; 321 struct aldap_page_control *page; 322 323 b.br_wbuf = NULL; 324 b.fd = -1; 325 ber_scanf_elements(control, "ss", &oid, &encoded); 326 ber_set_readbuf(&b, encoded, control->be_next->be_len); 327 elm = ber_read_elements(&b, NULL); 328 329 if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) { 330 if (elm != NULL) 331 ber_free_elements(elm); 332 ber_free(&b); 333 return NULL; 334 } 335 336 ber_scanf_elements(elm->be_sub, "is", &page->size, &s); 337 page->cookie_len = elm->be_sub->be_next->be_len; 338 339 if ((page->cookie = malloc(page->cookie_len)) == NULL) { 340 if (elm != NULL) 341 ber_free_elements(elm); 342 ber_free(&b); 343 free(page); 344 return NULL; 345 } 346 memcpy(page->cookie, s, page->cookie_len); 347 348 ber_free_elements(elm); 349 ber_free(&b); 350 return page; 351 } 352 353 void 354 aldap_freepage(struct aldap_page_control *page) 355 { 356 if (page->cookie) 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 * Convert UTF-8 to ASCII. 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'; ) { 1178 if ((u[i] & 0xF0) == 0xF0) 1179 i += 4; 1180 else if ((u[i] & 0xE0) == 0xE0) 1181 i += 3; 1182 else if ((u[i] & 0xC0) == 0xC0) 1183 i += 2; 1184 else 1185 i += 1; 1186 len++; 1187 } 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'; j++) { 1194 if ((u[i] & 0xF0) == 0xF0) { 1195 str[j] = '?'; 1196 i += 4; 1197 } else if ((u[i] & 0xE0) == 0xE0) { 1198 str[j] = '?'; 1199 i += 3; 1200 } else if ((u[i] & 0xC0) == 0xC0) { 1201 str[j] = '?'; 1202 i += 2; 1203 } else { 1204 str[j] = u[i]; 1205 i += 1; 1206 } 1207 } 1208 1209 return str; 1210 } 1211 1212 /* 1213 * Parse a LDAP value 1214 * notes: 1215 * the argument u should be a NULL terminated sequence of ASCII bytes. 1216 */ 1217 char * 1218 parseval(char *p, size_t len) 1219 { 1220 char hex[3]; 1221 char *cp = p, *buffer, *newbuffer; 1222 size_t size, newsize, i, j; 1223 1224 size = 50; 1225 if ((buffer = calloc(1, size)) == NULL) 1226 return NULL; 1227 1228 for (i = j = 0; j < len; i++) { 1229 if (i >= size) { 1230 newsize = size + 1024; 1231 if ((newbuffer = realloc(buffer, newsize)) == NULL) { 1232 free(buffer); 1233 return (NULL); 1234 } 1235 buffer = newbuffer; 1236 size = newsize; 1237 } 1238 1239 if (cp[j] == '\\') { 1240 strlcpy(hex, cp + j + 1, sizeof(hex)); 1241 buffer[i] = (char)strtoumax(hex, NULL, 16); 1242 j += 3; 1243 } else { 1244 buffer[i] = cp[j]; 1245 j++; 1246 } 1247 } 1248 1249 return buffer; 1250 } 1251 1252 int 1253 aldap_get_errno(struct aldap *a, const char **estr) 1254 { 1255 switch (a->err) { 1256 case ALDAP_ERR_SUCCESS: 1257 *estr = "success"; 1258 break; 1259 case ALDAP_ERR_PARSER_ERROR: 1260 *estr = "parser failed"; 1261 break; 1262 case ALDAP_ERR_INVALID_FILTER: 1263 *estr = "invalid filter"; 1264 break; 1265 case ALDAP_ERR_OPERATION_FAILED: 1266 *estr = "operation failed"; 1267 break; 1268 default: 1269 *estr = "unknown"; 1270 break; 1271 } 1272 return (a->err); 1273 } 1274