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