1eed7cf8dSMarcelo Araujo /* $Id: aldap.c,v 1.32 2016/04/27 10:53:27 schwarze Exp $ */
2eed7cf8dSMarcelo Araujo /* $OpenBSD: aldap.c,v 1.32 2016/04/27 10:53:27 schwarze Exp $ */
39e7c127fSCraig Rodrigues
49e7c127fSCraig Rodrigues /*
59e7c127fSCraig Rodrigues * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
69e7c127fSCraig Rodrigues * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
79e7c127fSCraig Rodrigues *
89e7c127fSCraig Rodrigues * Permission to use, copy, modify, and distribute this software for any
99e7c127fSCraig Rodrigues * purpose with or without fee is hereby granted, provided that the above
109e7c127fSCraig Rodrigues * copyright notice and this permission notice appear in all copies.
119e7c127fSCraig Rodrigues *
129e7c127fSCraig Rodrigues * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
139e7c127fSCraig Rodrigues * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
149e7c127fSCraig Rodrigues * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
159e7c127fSCraig Rodrigues * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
169e7c127fSCraig Rodrigues * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
179e7c127fSCraig Rodrigues * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
189e7c127fSCraig Rodrigues * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
199e7c127fSCraig Rodrigues */
209e7c127fSCraig Rodrigues
21eed7cf8dSMarcelo Araujo #include <ctype.h>
229e7c127fSCraig Rodrigues #include <errno.h>
239e7c127fSCraig Rodrigues #include <inttypes.h>
249e7c127fSCraig Rodrigues #include <string.h>
259e7c127fSCraig Rodrigues #include <stdlib.h>
269e7c127fSCraig Rodrigues #include <unistd.h>
279e7c127fSCraig Rodrigues
289e7c127fSCraig Rodrigues #include "aldap.h"
299e7c127fSCraig Rodrigues
309e7c127fSCraig Rodrigues #if 0
319e7c127fSCraig Rodrigues #define DEBUG
329e7c127fSCraig Rodrigues #endif
339e7c127fSCraig Rodrigues #define VERSION 3
349e7c127fSCraig Rodrigues
359e7c127fSCraig Rodrigues static struct ber_element *ldap_parse_search_filter(struct ber_element *,
369e7c127fSCraig Rodrigues char *);
379e7c127fSCraig Rodrigues static struct ber_element *ldap_do_parse_search_filter(
389e7c127fSCraig Rodrigues struct ber_element *, char **);
399e7c127fSCraig Rodrigues char **aldap_get_stringset(struct ber_element *);
409e7c127fSCraig Rodrigues char *utoa(char *);
41eed7cf8dSMarcelo Araujo static int isu8cont(unsigned char);
429e7c127fSCraig Rodrigues char *parseval(char *, size_t);
439e7c127fSCraig Rodrigues int aldap_create_page_control(struct ber_element *,
449e7c127fSCraig Rodrigues int, struct aldap_page_control *);
459e7c127fSCraig Rodrigues
469e7c127fSCraig Rodrigues #ifdef DEBUG
479e7c127fSCraig Rodrigues void ldap_debug_elements(struct ber_element *);
489e7c127fSCraig Rodrigues #endif
499e7c127fSCraig Rodrigues
509e7c127fSCraig Rodrigues #ifdef DEBUG
519e7c127fSCraig Rodrigues #define DPRINTF(x...) printf(x)
529e7c127fSCraig Rodrigues #define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0)
539e7c127fSCraig Rodrigues #else
549e7c127fSCraig Rodrigues #define DPRINTF(x...) do { } while (0)
559e7c127fSCraig Rodrigues #define LDAP_DEBUG(x, y) do { } while (0)
569e7c127fSCraig Rodrigues #endif
579e7c127fSCraig Rodrigues
589e7c127fSCraig Rodrigues int
aldap_close(struct aldap * al)599e7c127fSCraig Rodrigues aldap_close(struct aldap *al)
609e7c127fSCraig Rodrigues {
619e7c127fSCraig Rodrigues if (close(al->ber.fd) == -1)
629e7c127fSCraig Rodrigues return (-1);
639e7c127fSCraig Rodrigues
649e7c127fSCraig Rodrigues ber_free(&al->ber);
659e7c127fSCraig Rodrigues free(al);
669e7c127fSCraig Rodrigues
679e7c127fSCraig Rodrigues return (0);
689e7c127fSCraig Rodrigues }
699e7c127fSCraig Rodrigues
709e7c127fSCraig Rodrigues struct aldap *
aldap_init(int fd)719e7c127fSCraig Rodrigues aldap_init(int fd)
729e7c127fSCraig Rodrigues {
739e7c127fSCraig Rodrigues struct aldap *a;
749e7c127fSCraig Rodrigues
759e7c127fSCraig Rodrigues if ((a = calloc(1, sizeof(*a))) == NULL)
769e7c127fSCraig Rodrigues return NULL;
779e7c127fSCraig Rodrigues a->ber.fd = fd;
789e7c127fSCraig Rodrigues
799e7c127fSCraig Rodrigues return a;
809e7c127fSCraig Rodrigues }
819e7c127fSCraig Rodrigues
829e7c127fSCraig Rodrigues int
aldap_bind(struct aldap * ldap,char * binddn,char * bindcred)839e7c127fSCraig Rodrigues aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
849e7c127fSCraig Rodrigues {
859e7c127fSCraig Rodrigues struct ber_element *root = NULL, *elm;
869e7c127fSCraig Rodrigues int error;
879e7c127fSCraig Rodrigues
889e7c127fSCraig Rodrigues if (binddn == NULL)
899e7c127fSCraig Rodrigues binddn = "";
909e7c127fSCraig Rodrigues if (bindcred == NULL)
919e7c127fSCraig Rodrigues bindcred = "";
929e7c127fSCraig Rodrigues
939e7c127fSCraig Rodrigues if ((root = ber_add_sequence(NULL)) == NULL)
949e7c127fSCraig Rodrigues goto fail;
959e7c127fSCraig Rodrigues
969e7c127fSCraig Rodrigues elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
979e7c127fSCraig Rodrigues (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred,
989e7c127fSCraig Rodrigues BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE);
999e7c127fSCraig Rodrigues if (elm == NULL)
1009e7c127fSCraig Rodrigues goto fail;
1019e7c127fSCraig Rodrigues
1029e7c127fSCraig Rodrigues LDAP_DEBUG("aldap_bind", root);
1039e7c127fSCraig Rodrigues
1049e7c127fSCraig Rodrigues error = ber_write_elements(&ldap->ber, root);
1059e7c127fSCraig Rodrigues ber_free_elements(root);
1069e7c127fSCraig Rodrigues root = NULL;
1079e7c127fSCraig Rodrigues if (error == -1)
1089e7c127fSCraig Rodrigues goto fail;
1099e7c127fSCraig Rodrigues
1109e7c127fSCraig Rodrigues return (ldap->msgid);
1119e7c127fSCraig Rodrigues fail:
1129e7c127fSCraig Rodrigues if (root != NULL)
1139e7c127fSCraig Rodrigues ber_free_elements(root);
1149e7c127fSCraig Rodrigues
1159e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_OPERATION_FAILED;
1169e7c127fSCraig Rodrigues return (-1);
1179e7c127fSCraig Rodrigues }
1189e7c127fSCraig Rodrigues
1199e7c127fSCraig Rodrigues int
aldap_unbind(struct aldap * ldap)1209e7c127fSCraig Rodrigues aldap_unbind(struct aldap *ldap)
1219e7c127fSCraig Rodrigues {
1229e7c127fSCraig Rodrigues struct ber_element *root = NULL, *elm;
1239e7c127fSCraig Rodrigues int error;
1249e7c127fSCraig Rodrigues
1259e7c127fSCraig Rodrigues if ((root = ber_add_sequence(NULL)) == NULL)
1269e7c127fSCraig Rodrigues goto fail;
1279e7c127fSCraig Rodrigues elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1289e7c127fSCraig Rodrigues LDAP_REQ_UNBIND_30);
1299e7c127fSCraig Rodrigues if (elm == NULL)
1309e7c127fSCraig Rodrigues goto fail;
1319e7c127fSCraig Rodrigues
1329e7c127fSCraig Rodrigues LDAP_DEBUG("aldap_unbind", root);
1339e7c127fSCraig Rodrigues
1349e7c127fSCraig Rodrigues error = ber_write_elements(&ldap->ber, root);
1359e7c127fSCraig Rodrigues ber_free_elements(root);
1369e7c127fSCraig Rodrigues root = NULL;
1379e7c127fSCraig Rodrigues if (error == -1)
1389e7c127fSCraig Rodrigues goto fail;
1399e7c127fSCraig Rodrigues
1409e7c127fSCraig Rodrigues return (ldap->msgid);
1419e7c127fSCraig Rodrigues fail:
1429e7c127fSCraig Rodrigues if (root != NULL)
1439e7c127fSCraig Rodrigues ber_free_elements(root);
1449e7c127fSCraig Rodrigues
1459e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_OPERATION_FAILED;
1469e7c127fSCraig Rodrigues
1479e7c127fSCraig Rodrigues return (-1);
1489e7c127fSCraig Rodrigues }
1499e7c127fSCraig Rodrigues
1509e7c127fSCraig Rodrigues int
aldap_search(struct aldap * ldap,char * basedn,enum scope scope,char * filter,char ** attrs,int typesonly,int sizelimit,int timelimit,struct aldap_page_control * page)1519e7c127fSCraig Rodrigues aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter,
1529e7c127fSCraig Rodrigues char **attrs, int typesonly, int sizelimit, int timelimit,
1539e7c127fSCraig Rodrigues struct aldap_page_control *page)
1549e7c127fSCraig Rodrigues {
1559e7c127fSCraig Rodrigues struct ber_element *root = NULL, *ber, *c;
1569e7c127fSCraig Rodrigues int i, error;
1579e7c127fSCraig Rodrigues
1589e7c127fSCraig Rodrigues if ((root = ber_add_sequence(NULL)) == NULL)
1599e7c127fSCraig Rodrigues goto fail;
1609e7c127fSCraig Rodrigues
1619e7c127fSCraig Rodrigues ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1629e7c127fSCraig Rodrigues (unsigned long) LDAP_REQ_SEARCH);
1639e7c127fSCraig Rodrigues if (ber == NULL) {
1649e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_OPERATION_FAILED;
1659e7c127fSCraig Rodrigues goto fail;
1669e7c127fSCraig Rodrigues }
1679e7c127fSCraig Rodrigues
1689e7c127fSCraig Rodrigues c = ber;
1699e7c127fSCraig Rodrigues ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope,
1709e7c127fSCraig Rodrigues (long long)LDAP_DEREF_NEVER, sizelimit,
1719e7c127fSCraig Rodrigues timelimit, typesonly);
1729e7c127fSCraig Rodrigues if (ber == NULL) {
1739e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_OPERATION_FAILED;
1749e7c127fSCraig Rodrigues goto fail;
1759e7c127fSCraig Rodrigues }
1769e7c127fSCraig Rodrigues
1779e7c127fSCraig Rodrigues if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) {
1789e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_PARSER_ERROR;
1799e7c127fSCraig Rodrigues goto fail;
1809e7c127fSCraig Rodrigues }
1819e7c127fSCraig Rodrigues
1829e7c127fSCraig Rodrigues if ((ber = ber_add_sequence(ber)) == NULL)
1839e7c127fSCraig Rodrigues goto fail;
1849e7c127fSCraig Rodrigues if (attrs != NULL)
1859e7c127fSCraig Rodrigues for (i = 0; attrs[i] != NULL; i++) {
1869e7c127fSCraig Rodrigues if ((ber = ber_add_string(ber, attrs[i])) == NULL)
1879e7c127fSCraig Rodrigues goto fail;
1889e7c127fSCraig Rodrigues }
1899e7c127fSCraig Rodrigues
1909e7c127fSCraig Rodrigues aldap_create_page_control(c, 100, page);
1919e7c127fSCraig Rodrigues
1929e7c127fSCraig Rodrigues LDAP_DEBUG("aldap_search", root);
1939e7c127fSCraig Rodrigues
1949e7c127fSCraig Rodrigues error = ber_write_elements(&ldap->ber, root);
1959e7c127fSCraig Rodrigues ber_free_elements(root);
1969e7c127fSCraig Rodrigues root = NULL;
1979e7c127fSCraig Rodrigues if (error == -1) {
1989e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_OPERATION_FAILED;
1999e7c127fSCraig Rodrigues goto fail;
2009e7c127fSCraig Rodrigues }
2019e7c127fSCraig Rodrigues
2029e7c127fSCraig Rodrigues return (ldap->msgid);
2039e7c127fSCraig Rodrigues
2049e7c127fSCraig Rodrigues fail:
2059e7c127fSCraig Rodrigues if (root != NULL)
2069e7c127fSCraig Rodrigues ber_free_elements(root);
2079e7c127fSCraig Rodrigues
2089e7c127fSCraig Rodrigues return (-1);
2099e7c127fSCraig Rodrigues }
2109e7c127fSCraig Rodrigues
2119e7c127fSCraig Rodrigues int
aldap_create_page_control(struct ber_element * elm,int size,struct aldap_page_control * page)2129e7c127fSCraig Rodrigues aldap_create_page_control(struct ber_element *elm, int size,
2139e7c127fSCraig Rodrigues struct aldap_page_control *page)
2149e7c127fSCraig Rodrigues {
2159e7c127fSCraig Rodrigues int len;
2169e7c127fSCraig Rodrigues struct ber c;
2179e7c127fSCraig Rodrigues struct ber_element *ber = NULL;
2189e7c127fSCraig Rodrigues
2199e7c127fSCraig Rodrigues c.br_wbuf = NULL;
2209e7c127fSCraig Rodrigues c.fd = -1;
2219e7c127fSCraig Rodrigues
2229e7c127fSCraig Rodrigues ber = ber_add_sequence(NULL);
2239e7c127fSCraig Rodrigues
2249e7c127fSCraig Rodrigues if (page == NULL) {
2259e7c127fSCraig Rodrigues if (ber_printf_elements(ber, "ds", 50, "") == NULL)
2269e7c127fSCraig Rodrigues goto fail;
2279e7c127fSCraig Rodrigues } else {
2289e7c127fSCraig Rodrigues if (ber_printf_elements(ber, "dx", 50, page->cookie,
2299e7c127fSCraig Rodrigues page->cookie_len) == NULL)
2309e7c127fSCraig Rodrigues goto fail;
2319e7c127fSCraig Rodrigues }
2329e7c127fSCraig Rodrigues
2339e7c127fSCraig Rodrigues if ((len = ber_write_elements(&c, ber)) < 1)
2349e7c127fSCraig Rodrigues goto fail;
2359e7c127fSCraig Rodrigues if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
2369e7c127fSCraig Rodrigues c.br_wbuf, (size_t)len) == NULL)
2379e7c127fSCraig Rodrigues goto fail;
2389e7c127fSCraig Rodrigues
2399e7c127fSCraig Rodrigues ber_free_elements(ber);
2409e7c127fSCraig Rodrigues ber_free(&c);
2419e7c127fSCraig Rodrigues return len;
2429e7c127fSCraig Rodrigues fail:
2439e7c127fSCraig Rodrigues if (ber != NULL)
2449e7c127fSCraig Rodrigues ber_free_elements(ber);
2459e7c127fSCraig Rodrigues ber_free(&c);
2469e7c127fSCraig Rodrigues
2479e7c127fSCraig Rodrigues return (-1);
2489e7c127fSCraig Rodrigues }
2499e7c127fSCraig Rodrigues
2509e7c127fSCraig Rodrigues struct aldap_message *
aldap_parse(struct aldap * ldap)2519e7c127fSCraig Rodrigues aldap_parse(struct aldap *ldap)
2529e7c127fSCraig Rodrigues {
2539e7c127fSCraig Rodrigues int class;
2549e7c127fSCraig Rodrigues unsigned long type;
2559e7c127fSCraig Rodrigues long long msgid = 0;
2569e7c127fSCraig Rodrigues struct aldap_message *m;
2579e7c127fSCraig Rodrigues struct ber_element *a = NULL, *ep;
2589e7c127fSCraig Rodrigues
2599e7c127fSCraig Rodrigues if ((m = calloc(1, sizeof(struct aldap_message))) == NULL)
2609e7c127fSCraig Rodrigues return NULL;
2619e7c127fSCraig Rodrigues
2629e7c127fSCraig Rodrigues if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL)
2639e7c127fSCraig Rodrigues goto parsefail;
2649e7c127fSCraig Rodrigues
2659e7c127fSCraig Rodrigues LDAP_DEBUG("message", m->msg);
2669e7c127fSCraig Rodrigues
2679e7c127fSCraig Rodrigues if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
2689e7c127fSCraig Rodrigues goto parsefail;
2699e7c127fSCraig Rodrigues m->msgid = msgid;
2709e7c127fSCraig Rodrigues m->message_type = type;
2719e7c127fSCraig Rodrigues m->protocol_op = a;
2729e7c127fSCraig Rodrigues
2739e7c127fSCraig Rodrigues switch (m->message_type) {
2749e7c127fSCraig Rodrigues case LDAP_RES_BIND:
2759e7c127fSCraig Rodrigues case LDAP_RES_MODIFY:
2769e7c127fSCraig Rodrigues case LDAP_RES_ADD:
2779e7c127fSCraig Rodrigues case LDAP_RES_DELETE:
2789e7c127fSCraig Rodrigues case LDAP_RES_MODRDN:
2799e7c127fSCraig Rodrigues case LDAP_RES_COMPARE:
2809e7c127fSCraig Rodrigues case LDAP_RES_SEARCH_RESULT:
2819e7c127fSCraig Rodrigues if (ber_scanf_elements(m->protocol_op, "{EeSeSe",
2829e7c127fSCraig Rodrigues &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0)
2839e7c127fSCraig Rodrigues goto parsefail;
2849e7c127fSCraig Rodrigues if (m->body.res.rescode == LDAP_REFERRAL)
2859e7c127fSCraig Rodrigues if (ber_scanf_elements(a, "{e", &m->references) != 0)
2869e7c127fSCraig Rodrigues goto parsefail;
2879e7c127fSCraig Rodrigues if (m->msg->be_sub) {
2889e7c127fSCraig Rodrigues for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
2899e7c127fSCraig Rodrigues ber_scanf_elements(ep, "t", &class, &type);
2909e7c127fSCraig Rodrigues if (class == 2 && type == 0)
2919e7c127fSCraig Rodrigues m->page = aldap_parse_page_control(ep->be_sub->be_sub,
2929e7c127fSCraig Rodrigues ep->be_sub->be_sub->be_len);
2939e7c127fSCraig Rodrigues }
2949e7c127fSCraig Rodrigues } else
2959e7c127fSCraig Rodrigues m->page = NULL;
2969e7c127fSCraig Rodrigues break;
2979e7c127fSCraig Rodrigues case LDAP_RES_SEARCH_ENTRY:
2989e7c127fSCraig Rodrigues if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
2999e7c127fSCraig Rodrigues &m->body.search.attrs) != 0)
3009e7c127fSCraig Rodrigues goto parsefail;
3019e7c127fSCraig Rodrigues break;
3029e7c127fSCraig Rodrigues case LDAP_RES_SEARCH_REFERENCE:
3039e7c127fSCraig Rodrigues if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
3049e7c127fSCraig Rodrigues goto parsefail;
3059e7c127fSCraig Rodrigues break;
3069e7c127fSCraig Rodrigues }
3079e7c127fSCraig Rodrigues
3089e7c127fSCraig Rodrigues return m;
3099e7c127fSCraig Rodrigues parsefail:
3109e7c127fSCraig Rodrigues ldap->err = ALDAP_ERR_PARSER_ERROR;
3119e7c127fSCraig Rodrigues aldap_freemsg(m);
3129e7c127fSCraig Rodrigues return NULL;
3139e7c127fSCraig Rodrigues }
3149e7c127fSCraig Rodrigues
3159e7c127fSCraig Rodrigues struct aldap_page_control *
aldap_parse_page_control(struct ber_element * control,size_t len)3169e7c127fSCraig Rodrigues aldap_parse_page_control(struct ber_element *control, size_t len)
3179e7c127fSCraig Rodrigues {
3189e7c127fSCraig Rodrigues char *oid, *s;
3199e7c127fSCraig Rodrigues char *encoded;
3209e7c127fSCraig Rodrigues struct ber b;
3219e7c127fSCraig Rodrigues struct ber_element *elm;
3229e7c127fSCraig Rodrigues struct aldap_page_control *page;
3239e7c127fSCraig Rodrigues
3249e7c127fSCraig Rodrigues b.br_wbuf = NULL;
3259e7c127fSCraig Rodrigues b.fd = -1;
3269e7c127fSCraig Rodrigues ber_scanf_elements(control, "ss", &oid, &encoded);
3279e7c127fSCraig Rodrigues ber_set_readbuf(&b, encoded, control->be_next->be_len);
3289e7c127fSCraig Rodrigues elm = ber_read_elements(&b, NULL);
3299e7c127fSCraig Rodrigues
3309e7c127fSCraig Rodrigues if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
3319e7c127fSCraig Rodrigues if (elm != NULL)
3329e7c127fSCraig Rodrigues ber_free_elements(elm);
3339e7c127fSCraig Rodrigues ber_free(&b);
3349e7c127fSCraig Rodrigues return NULL;
3359e7c127fSCraig Rodrigues }
3369e7c127fSCraig Rodrigues
3379e7c127fSCraig Rodrigues ber_scanf_elements(elm->be_sub, "is", &page->size, &s);
3389e7c127fSCraig Rodrigues page->cookie_len = elm->be_sub->be_next->be_len;
3399e7c127fSCraig Rodrigues
3409e7c127fSCraig Rodrigues if ((page->cookie = malloc(page->cookie_len)) == NULL) {
3419e7c127fSCraig Rodrigues if (elm != NULL)
3429e7c127fSCraig Rodrigues ber_free_elements(elm);
3439e7c127fSCraig Rodrigues ber_free(&b);
3449e7c127fSCraig Rodrigues free(page);
3459e7c127fSCraig Rodrigues return NULL;
3469e7c127fSCraig Rodrigues }
3479e7c127fSCraig Rodrigues memcpy(page->cookie, s, page->cookie_len);
3489e7c127fSCraig Rodrigues
3499e7c127fSCraig Rodrigues ber_free_elements(elm);
3509e7c127fSCraig Rodrigues ber_free(&b);
3519e7c127fSCraig Rodrigues return page;
3529e7c127fSCraig Rodrigues }
3539e7c127fSCraig Rodrigues
3549e7c127fSCraig Rodrigues void
aldap_freepage(struct aldap_page_control * page)3559e7c127fSCraig Rodrigues aldap_freepage(struct aldap_page_control *page)
3569e7c127fSCraig Rodrigues {
3579e7c127fSCraig Rodrigues free(page->cookie);
3589e7c127fSCraig Rodrigues free(page);
3599e7c127fSCraig Rodrigues }
3609e7c127fSCraig Rodrigues
3619e7c127fSCraig Rodrigues void
aldap_freemsg(struct aldap_message * msg)3629e7c127fSCraig Rodrigues aldap_freemsg(struct aldap_message *msg)
3639e7c127fSCraig Rodrigues {
3649e7c127fSCraig Rodrigues if (msg->msg)
3659e7c127fSCraig Rodrigues ber_free_elements(msg->msg);
3669e7c127fSCraig Rodrigues free(msg);
3679e7c127fSCraig Rodrigues }
3689e7c127fSCraig Rodrigues
3699e7c127fSCraig Rodrigues int
aldap_get_resultcode(struct aldap_message * msg)3709e7c127fSCraig Rodrigues aldap_get_resultcode(struct aldap_message *msg)
3719e7c127fSCraig Rodrigues {
3729e7c127fSCraig Rodrigues return msg->body.res.rescode;
3739e7c127fSCraig Rodrigues }
3749e7c127fSCraig Rodrigues
3759e7c127fSCraig Rodrigues char *
aldap_get_dn(struct aldap_message * msg)3769e7c127fSCraig Rodrigues aldap_get_dn(struct aldap_message *msg)
3779e7c127fSCraig Rodrigues {
3789e7c127fSCraig Rodrigues char *dn;
3799e7c127fSCraig Rodrigues
3809e7c127fSCraig Rodrigues if (msg->dn == NULL)
3819e7c127fSCraig Rodrigues return NULL;
3829e7c127fSCraig Rodrigues
3839e7c127fSCraig Rodrigues if (ber_get_string(msg->dn, &dn) == -1)
3849e7c127fSCraig Rodrigues return NULL;
3859e7c127fSCraig Rodrigues
3869e7c127fSCraig Rodrigues return utoa(dn);
3879e7c127fSCraig Rodrigues }
3889e7c127fSCraig Rodrigues
3899e7c127fSCraig Rodrigues char **
aldap_get_references(struct aldap_message * msg)3909e7c127fSCraig Rodrigues aldap_get_references(struct aldap_message *msg)
3919e7c127fSCraig Rodrigues {
3929e7c127fSCraig Rodrigues if (msg->references == NULL)
3939e7c127fSCraig Rodrigues return NULL;
3949e7c127fSCraig Rodrigues return aldap_get_stringset(msg->references);
3959e7c127fSCraig Rodrigues }
3969e7c127fSCraig Rodrigues
3979e7c127fSCraig Rodrigues void
aldap_free_references(char ** values)3989e7c127fSCraig Rodrigues aldap_free_references(char **values)
3999e7c127fSCraig Rodrigues {
4009e7c127fSCraig Rodrigues int i;
4019e7c127fSCraig Rodrigues
4029e7c127fSCraig Rodrigues if (values == NULL)
4039e7c127fSCraig Rodrigues return;
4049e7c127fSCraig Rodrigues
4059e7c127fSCraig Rodrigues for (i = 0; values[i] != NULL; i++)
4069e7c127fSCraig Rodrigues free(values[i]);
4079e7c127fSCraig Rodrigues
4089e7c127fSCraig Rodrigues free(values);
4099e7c127fSCraig Rodrigues }
4109e7c127fSCraig Rodrigues
4119e7c127fSCraig Rodrigues char *
aldap_get_diagmsg(struct aldap_message * msg)4129e7c127fSCraig Rodrigues aldap_get_diagmsg(struct aldap_message *msg)
4139e7c127fSCraig Rodrigues {
4149e7c127fSCraig Rodrigues char *s;
4159e7c127fSCraig Rodrigues
4169e7c127fSCraig Rodrigues if (msg->body.res.diagmsg == NULL)
4179e7c127fSCraig Rodrigues return NULL;
4189e7c127fSCraig Rodrigues
4199e7c127fSCraig Rodrigues if (ber_get_string(msg->body.res.diagmsg, &s) == -1)
4209e7c127fSCraig Rodrigues return NULL;
4219e7c127fSCraig Rodrigues
4229e7c127fSCraig Rodrigues return utoa(s);
4239e7c127fSCraig Rodrigues }
4249e7c127fSCraig Rodrigues
4259e7c127fSCraig Rodrigues int
aldap_count_attrs(struct aldap_message * msg)4269e7c127fSCraig Rodrigues aldap_count_attrs(struct aldap_message *msg)
4279e7c127fSCraig Rodrigues {
4289e7c127fSCraig Rodrigues int i;
4299e7c127fSCraig Rodrigues struct ber_element *a;
4309e7c127fSCraig Rodrigues
4319e7c127fSCraig Rodrigues if (msg->body.search.attrs == NULL)
4329e7c127fSCraig Rodrigues return (-1);
4339e7c127fSCraig Rodrigues
4349e7c127fSCraig Rodrigues for (i = 0, a = msg->body.search.attrs;
4359e7c127fSCraig Rodrigues a != NULL && ber_get_eoc(a) != 0;
4369e7c127fSCraig Rodrigues i++, a = a->be_next)
4379e7c127fSCraig Rodrigues ;
4389e7c127fSCraig Rodrigues
4399e7c127fSCraig Rodrigues return i;
4409e7c127fSCraig Rodrigues }
4419e7c127fSCraig Rodrigues
4429e7c127fSCraig Rodrigues int
aldap_first_attr(struct aldap_message * msg,char ** outkey,char *** outvalues)4439e7c127fSCraig Rodrigues aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
4449e7c127fSCraig Rodrigues {
4459e7c127fSCraig Rodrigues struct ber_element *b, *c;
4469e7c127fSCraig Rodrigues char *key;
4479e7c127fSCraig Rodrigues char **ret;
4489e7c127fSCraig Rodrigues
4499e7c127fSCraig Rodrigues if (msg->body.search.attrs == NULL)
4509e7c127fSCraig Rodrigues goto fail;
4519e7c127fSCraig Rodrigues
4529e7c127fSCraig Rodrigues if (ber_scanf_elements(msg->body.search.attrs, "{s(e)}e",
4539e7c127fSCraig Rodrigues &key, &b, &c) != 0)
4549e7c127fSCraig Rodrigues goto fail;
4559e7c127fSCraig Rodrigues
4569e7c127fSCraig Rodrigues msg->body.search.iter = msg->body.search.attrs->be_next;
4579e7c127fSCraig Rodrigues
4589e7c127fSCraig Rodrigues if ((ret = aldap_get_stringset(b)) == NULL)
4599e7c127fSCraig Rodrigues goto fail;
4609e7c127fSCraig Rodrigues
4619e7c127fSCraig Rodrigues (*outvalues) = ret;
4629e7c127fSCraig Rodrigues (*outkey) = utoa(key);
4639e7c127fSCraig Rodrigues
4649e7c127fSCraig Rodrigues return (1);
4659e7c127fSCraig Rodrigues fail:
4669e7c127fSCraig Rodrigues (*outkey) = NULL;
4679e7c127fSCraig Rodrigues (*outvalues) = NULL;
4689e7c127fSCraig Rodrigues return (-1);
4699e7c127fSCraig Rodrigues }
4709e7c127fSCraig Rodrigues
4719e7c127fSCraig Rodrigues int
aldap_next_attr(struct aldap_message * msg,char ** outkey,char *** outvalues)4729e7c127fSCraig Rodrigues aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
4739e7c127fSCraig Rodrigues {
4749e7c127fSCraig Rodrigues struct ber_element *a, *b;
4759e7c127fSCraig Rodrigues char *key;
4769e7c127fSCraig Rodrigues char **ret;
4779e7c127fSCraig Rodrigues
4789e7c127fSCraig Rodrigues if (msg->body.search.iter == NULL)
4799e7c127fSCraig Rodrigues goto notfound;
4809e7c127fSCraig Rodrigues
4819e7c127fSCraig Rodrigues LDAP_DEBUG("attr", msg->body.search.iter);
4829e7c127fSCraig Rodrigues
4839e7c127fSCraig Rodrigues if (ber_get_eoc(msg->body.search.iter) == 0)
4849e7c127fSCraig Rodrigues goto notfound;
4859e7c127fSCraig Rodrigues
4869e7c127fSCraig Rodrigues if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
4879e7c127fSCraig Rodrigues != 0)
4889e7c127fSCraig Rodrigues goto fail;
4899e7c127fSCraig Rodrigues
4909e7c127fSCraig Rodrigues msg->body.search.iter = msg->body.search.iter->be_next;
4919e7c127fSCraig Rodrigues
4929e7c127fSCraig Rodrigues if ((ret = aldap_get_stringset(a)) == NULL)
4939e7c127fSCraig Rodrigues goto fail;
4949e7c127fSCraig Rodrigues
4959e7c127fSCraig Rodrigues (*outvalues) = ret;
4969e7c127fSCraig Rodrigues (*outkey) = utoa(key);
4979e7c127fSCraig Rodrigues
4989e7c127fSCraig Rodrigues return (1);
4999e7c127fSCraig Rodrigues fail:
5009e7c127fSCraig Rodrigues notfound:
5019e7c127fSCraig Rodrigues (*outkey) = NULL;
5029e7c127fSCraig Rodrigues (*outvalues) = NULL;
5039e7c127fSCraig Rodrigues return (-1);
5049e7c127fSCraig Rodrigues }
5059e7c127fSCraig Rodrigues
5069e7c127fSCraig Rodrigues int
aldap_match_attr(struct aldap_message * msg,char * inkey,char *** outvalues)5079e7c127fSCraig Rodrigues aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues)
5089e7c127fSCraig Rodrigues {
5099e7c127fSCraig Rodrigues struct ber_element *a, *b;
5109e7c127fSCraig Rodrigues char *descr = NULL;
5119e7c127fSCraig Rodrigues char **ret;
5129e7c127fSCraig Rodrigues
5139e7c127fSCraig Rodrigues if (msg->body.search.attrs == NULL)
5149e7c127fSCraig Rodrigues goto fail;
5159e7c127fSCraig Rodrigues
5169e7c127fSCraig Rodrigues LDAP_DEBUG("attr", msg->body.search.attrs);
5179e7c127fSCraig Rodrigues
5189e7c127fSCraig Rodrigues for (a = msg->body.search.attrs;;) {
5199e7c127fSCraig Rodrigues if (a == NULL)
5209e7c127fSCraig Rodrigues goto notfound;
5219e7c127fSCraig Rodrigues if (ber_get_eoc(a) == 0)
5229e7c127fSCraig Rodrigues goto notfound;
5239e7c127fSCraig Rodrigues if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0)
5249e7c127fSCraig Rodrigues goto fail;
5259e7c127fSCraig Rodrigues if (strcasecmp(descr, inkey) == 0)
5269e7c127fSCraig Rodrigues goto attrfound;
5279e7c127fSCraig Rodrigues a = a->be_next;
5289e7c127fSCraig Rodrigues }
5299e7c127fSCraig Rodrigues
5309e7c127fSCraig Rodrigues attrfound:
5319e7c127fSCraig Rodrigues if ((ret = aldap_get_stringset(b)) == NULL)
5329e7c127fSCraig Rodrigues goto fail;
5339e7c127fSCraig Rodrigues
5349e7c127fSCraig Rodrigues (*outvalues) = ret;
5359e7c127fSCraig Rodrigues
5369e7c127fSCraig Rodrigues return (1);
5379e7c127fSCraig Rodrigues fail:
5389e7c127fSCraig Rodrigues notfound:
5399e7c127fSCraig Rodrigues (*outvalues) = NULL;
5409e7c127fSCraig Rodrigues return (-1);
5419e7c127fSCraig Rodrigues }
5429e7c127fSCraig Rodrigues
5439e7c127fSCraig Rodrigues int
aldap_free_attr(char ** values)5449e7c127fSCraig Rodrigues aldap_free_attr(char **values)
5459e7c127fSCraig Rodrigues {
5469e7c127fSCraig Rodrigues int i;
5479e7c127fSCraig Rodrigues
5489e7c127fSCraig Rodrigues if (values == NULL)
5499e7c127fSCraig Rodrigues return -1;
5509e7c127fSCraig Rodrigues
5519e7c127fSCraig Rodrigues for (i = 0; values[i] != NULL; i++)
5529e7c127fSCraig Rodrigues free(values[i]);
5539e7c127fSCraig Rodrigues
5549e7c127fSCraig Rodrigues free(values);
5559e7c127fSCraig Rodrigues
5569e7c127fSCraig Rodrigues return (1);
5579e7c127fSCraig Rodrigues }
5589e7c127fSCraig Rodrigues
5599e7c127fSCraig Rodrigues #if 0
5609e7c127fSCraig Rodrigues void
5619e7c127fSCraig Rodrigues aldap_free_url(struct aldap_url *lu)
5629e7c127fSCraig Rodrigues {
5639e7c127fSCraig Rodrigues free(lu->buffer);
5649e7c127fSCraig Rodrigues free(lu->filter);
5659e7c127fSCraig Rodrigues }
5669e7c127fSCraig Rodrigues
5679e7c127fSCraig Rodrigues int
5689e7c127fSCraig Rodrigues aldap_parse_url(char *url, struct aldap_url *lu)
5699e7c127fSCraig Rodrigues {
5709e7c127fSCraig Rodrigues char *p, *forward, *forward2;
5719e7c127fSCraig Rodrigues const char *errstr = NULL;
5729e7c127fSCraig Rodrigues int i;
5739e7c127fSCraig Rodrigues
5749e7c127fSCraig Rodrigues if ((lu->buffer = p = strdup(url)) == NULL)
5759e7c127fSCraig Rodrigues return (-1);
5769e7c127fSCraig Rodrigues
5779e7c127fSCraig Rodrigues /* protocol */
5789e7c127fSCraig Rodrigues if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0)
5799e7c127fSCraig Rodrigues goto fail;
5809e7c127fSCraig Rodrigues lu->protocol = LDAP;
5819e7c127fSCraig Rodrigues p += strlen(LDAP_URL);
5829e7c127fSCraig Rodrigues
5839e7c127fSCraig Rodrigues /* host and optional port */
5849e7c127fSCraig Rodrigues if ((forward = strchr(p, '/')) != NULL)
5859e7c127fSCraig Rodrigues *forward = '\0';
5869e7c127fSCraig Rodrigues /* find the optional port */
5879e7c127fSCraig Rodrigues if ((forward2 = strchr(p, ':')) != NULL) {
5889e7c127fSCraig Rodrigues *forward2 = '\0';
5899e7c127fSCraig Rodrigues /* if a port is given */
5909e7c127fSCraig Rodrigues if (*(forward2+1) != '\0') {
5919e7c127fSCraig Rodrigues #define PORT_MAX UINT16_MAX
5929e7c127fSCraig Rodrigues lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
5939e7c127fSCraig Rodrigues if (errstr)
5949e7c127fSCraig Rodrigues goto fail;
5959e7c127fSCraig Rodrigues }
5969e7c127fSCraig Rodrigues }
5979e7c127fSCraig Rodrigues /* fail if no host is given */
5989e7c127fSCraig Rodrigues if (strlen(p) == 0)
5999e7c127fSCraig Rodrigues goto fail;
6009e7c127fSCraig Rodrigues lu->host = p;
6019e7c127fSCraig Rodrigues if (forward == NULL)
6029e7c127fSCraig Rodrigues goto done;
6039e7c127fSCraig Rodrigues /* p is assigned either a pointer to a character or to '\0' */
6049e7c127fSCraig Rodrigues p = ++forward;
6059e7c127fSCraig Rodrigues if (strlen(p) == 0)
6069e7c127fSCraig Rodrigues goto done;
6079e7c127fSCraig Rodrigues
6089e7c127fSCraig Rodrigues /* dn */
6099e7c127fSCraig Rodrigues if ((forward = strchr(p, '?')) != NULL)
6109e7c127fSCraig Rodrigues *forward = '\0';
6119e7c127fSCraig Rodrigues lu->dn = p;
6129e7c127fSCraig Rodrigues if (forward == NULL)
6139e7c127fSCraig Rodrigues goto done;
6149e7c127fSCraig Rodrigues /* p is assigned either a pointer to a character or to '\0' */
6159e7c127fSCraig Rodrigues p = ++forward;
6169e7c127fSCraig Rodrigues if (strlen(p) == 0)
6179e7c127fSCraig Rodrigues goto done;
6189e7c127fSCraig Rodrigues
6199e7c127fSCraig Rodrigues /* attributes */
6209e7c127fSCraig Rodrigues if ((forward = strchr(p, '?')) != NULL)
6219e7c127fSCraig Rodrigues *forward = '\0';
6229e7c127fSCraig Rodrigues for (i = 0; i < MAXATTR; i++) {
6239e7c127fSCraig Rodrigues if ((forward2 = strchr(p, ',')) == NULL) {
6249e7c127fSCraig Rodrigues if (strlen(p) == 0)
6259e7c127fSCraig Rodrigues break;
6269e7c127fSCraig Rodrigues lu->attributes[i] = p;
6279e7c127fSCraig Rodrigues break;
6289e7c127fSCraig Rodrigues }
6299e7c127fSCraig Rodrigues *forward2 = '\0';
6309e7c127fSCraig Rodrigues lu->attributes[i] = p;
6319e7c127fSCraig Rodrigues p = ++forward2;
6329e7c127fSCraig Rodrigues }
6339e7c127fSCraig Rodrigues if (forward == NULL)
6349e7c127fSCraig Rodrigues goto done;
6359e7c127fSCraig Rodrigues /* p is assigned either a pointer to a character or to '\0' */
6369e7c127fSCraig Rodrigues p = ++forward;
6379e7c127fSCraig Rodrigues if (strlen(p) == 0)
6389e7c127fSCraig Rodrigues goto done;
6399e7c127fSCraig Rodrigues
6409e7c127fSCraig Rodrigues /* scope */
6419e7c127fSCraig Rodrigues if ((forward = strchr(p, '?')) != NULL)
6429e7c127fSCraig Rodrigues *forward = '\0';
6439e7c127fSCraig Rodrigues if (strcmp(p, "base") == 0)
6449e7c127fSCraig Rodrigues lu->scope = LDAP_SCOPE_BASE;
6459e7c127fSCraig Rodrigues else if (strcmp(p, "one") == 0)
6469e7c127fSCraig Rodrigues lu->scope = LDAP_SCOPE_ONELEVEL;
6479e7c127fSCraig Rodrigues else if (strcmp(p, "sub") == 0)
6489e7c127fSCraig Rodrigues lu->scope = LDAP_SCOPE_SUBTREE;
6499e7c127fSCraig Rodrigues else
6509e7c127fSCraig Rodrigues goto fail;
6519e7c127fSCraig Rodrigues if (forward == NULL)
6529e7c127fSCraig Rodrigues goto done;
6539e7c127fSCraig Rodrigues p = ++forward;
6549e7c127fSCraig Rodrigues if (strlen(p) == 0)
6559e7c127fSCraig Rodrigues goto done;
6569e7c127fSCraig Rodrigues
6579e7c127fSCraig Rodrigues /* filter */
6589e7c127fSCraig Rodrigues if (p)
6599e7c127fSCraig Rodrigues lu->filter = p;
6609e7c127fSCraig Rodrigues done:
6619e7c127fSCraig Rodrigues free(url);
6629e7c127fSCraig Rodrigues return (1);
6639e7c127fSCraig Rodrigues fail:
6649e7c127fSCraig Rodrigues free(lu->buffer);
6659e7c127fSCraig Rodrigues lu->buffer = NULL;
6669e7c127fSCraig Rodrigues return (-1);
6679e7c127fSCraig Rodrigues }
6689e7c127fSCraig Rodrigues
6699e7c127fSCraig Rodrigues int
6709e7c127fSCraig Rodrigues aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
6719e7c127fSCraig Rodrigues int timelimit)
6729e7c127fSCraig Rodrigues {
6739e7c127fSCraig Rodrigues struct aldap_url *lu;
6749e7c127fSCraig Rodrigues
6759e7c127fSCraig Rodrigues if ((lu = calloc(1, sizeof(*lu))) == NULL)
6769e7c127fSCraig Rodrigues return (-1);
6779e7c127fSCraig Rodrigues
6789e7c127fSCraig Rodrigues if (aldap_parse_url(url, lu))
6799e7c127fSCraig Rodrigues goto fail;
6809e7c127fSCraig Rodrigues
6819e7c127fSCraig Rodrigues if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
6829e7c127fSCraig Rodrigues typesonly, sizelimit, timelimit) == -1)
6839e7c127fSCraig Rodrigues goto fail;
6849e7c127fSCraig Rodrigues
6859e7c127fSCraig Rodrigues aldap_free_url(lu);
6869e7c127fSCraig Rodrigues return (ldap->msgid);
6879e7c127fSCraig Rodrigues fail:
6889e7c127fSCraig Rodrigues aldap_free_url(lu);
6899e7c127fSCraig Rodrigues return (-1);
6909e7c127fSCraig Rodrigues }
6919e7c127fSCraig Rodrigues #endif /* 0 */
6929e7c127fSCraig Rodrigues
6939e7c127fSCraig Rodrigues /*
6949e7c127fSCraig Rodrigues * internal functions
6959e7c127fSCraig Rodrigues */
6969e7c127fSCraig Rodrigues
6979e7c127fSCraig Rodrigues char **
aldap_get_stringset(struct ber_element * elm)6989e7c127fSCraig Rodrigues aldap_get_stringset(struct ber_element *elm)
6999e7c127fSCraig Rodrigues {
7009e7c127fSCraig Rodrigues struct ber_element *a;
7019e7c127fSCraig Rodrigues int i;
7029e7c127fSCraig Rodrigues char **ret;
7039e7c127fSCraig Rodrigues char *s;
7049e7c127fSCraig Rodrigues
7059e7c127fSCraig Rodrigues if (elm->be_type != BER_TYPE_OCTETSTRING)
7069e7c127fSCraig Rodrigues return NULL;
7079e7c127fSCraig Rodrigues
7089e7c127fSCraig Rodrigues for (a = elm, i = 1; i > 0 && a != NULL && a->be_type ==
7099e7c127fSCraig Rodrigues BER_TYPE_OCTETSTRING; a = a->be_next, i++)
7109e7c127fSCraig Rodrigues ;
7119e7c127fSCraig Rodrigues if (i == 1)
7129e7c127fSCraig Rodrigues return NULL;
7139e7c127fSCraig Rodrigues
7149e7c127fSCraig Rodrigues if ((ret = calloc(i + 1, sizeof(char *))) == NULL)
7159e7c127fSCraig Rodrigues return NULL;
7169e7c127fSCraig Rodrigues
7179e7c127fSCraig Rodrigues for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
7189d80a8b0SDon Lewis a = a->be_next) {
7199e7c127fSCraig Rodrigues
7209e7c127fSCraig Rodrigues ber_get_string(a, &s);
7219e7c127fSCraig Rodrigues ret[i] = utoa(s);
7229d80a8b0SDon Lewis if (ret[i] != NULL)
7239d80a8b0SDon Lewis i++;
7249d80a8b0SDon Lewis
7259e7c127fSCraig Rodrigues }
7269d80a8b0SDon Lewis if (i == 0) {
7279d80a8b0SDon Lewis free(ret);
7289d80a8b0SDon Lewis return NULL;
7299d80a8b0SDon Lewis }
7309d80a8b0SDon Lewis ret[i] = NULL;
7319e7c127fSCraig Rodrigues
7329e7c127fSCraig Rodrigues return ret;
7339e7c127fSCraig Rodrigues }
7349e7c127fSCraig Rodrigues
7359e7c127fSCraig Rodrigues /*
7369e7c127fSCraig Rodrigues * Base case for ldap_do_parse_search_filter
7379e7c127fSCraig Rodrigues *
7389e7c127fSCraig Rodrigues * returns:
7399e7c127fSCraig Rodrigues * struct ber_element *, ber_element tree
7409e7c127fSCraig Rodrigues * NULL, parse failed
7419e7c127fSCraig Rodrigues */
7429e7c127fSCraig Rodrigues static struct ber_element *
ldap_parse_search_filter(struct ber_element * ber,char * filter)7439e7c127fSCraig Rodrigues ldap_parse_search_filter(struct ber_element *ber, char *filter)
7449e7c127fSCraig Rodrigues {
7459e7c127fSCraig Rodrigues struct ber_element *elm;
7469e7c127fSCraig Rodrigues char *cp;
7479e7c127fSCraig Rodrigues
7489e7c127fSCraig Rodrigues cp = filter;
7499e7c127fSCraig Rodrigues
7509e7c127fSCraig Rodrigues if (cp == NULL || *cp == '\0') {
7519e7c127fSCraig Rodrigues errno = EINVAL;
7529e7c127fSCraig Rodrigues return (NULL);
7539e7c127fSCraig Rodrigues }
7549e7c127fSCraig Rodrigues
7559e7c127fSCraig Rodrigues if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
7569e7c127fSCraig Rodrigues return (NULL);
7579e7c127fSCraig Rodrigues
7589e7c127fSCraig Rodrigues if (*cp != '\0') {
7599e7c127fSCraig Rodrigues ber_free_elements(elm);
7609e7c127fSCraig Rodrigues ber_link_elements(ber, NULL);
7619e7c127fSCraig Rodrigues errno = EINVAL;
7629e7c127fSCraig Rodrigues return (NULL);
7639e7c127fSCraig Rodrigues }
7649e7c127fSCraig Rodrigues
7659e7c127fSCraig Rodrigues return (elm);
7669e7c127fSCraig Rodrigues }
7679e7c127fSCraig Rodrigues
7689e7c127fSCraig Rodrigues /*
7699e7c127fSCraig Rodrigues * Translate RFC4515 search filter string into ber_element tree
7709e7c127fSCraig Rodrigues *
7719e7c127fSCraig Rodrigues * returns:
7729e7c127fSCraig Rodrigues * struct ber_element *, ber_element tree
7739e7c127fSCraig Rodrigues * NULL, parse failed
7749e7c127fSCraig Rodrigues *
7759e7c127fSCraig Rodrigues * notes:
7769e7c127fSCraig Rodrigues * when cp is passed to a recursive invocation, it is updated
7779e7c127fSCraig Rodrigues * to point one character beyond the filter that was passed
7789e7c127fSCraig Rodrigues * i.e., cp jumps to "(filter)" upon return
7799e7c127fSCraig Rodrigues * ^
7809e7c127fSCraig Rodrigues * goto's used to discriminate error-handling based on error type
7819e7c127fSCraig Rodrigues * doesn't handle extended filters (yet)
7829e7c127fSCraig Rodrigues *
7839e7c127fSCraig Rodrigues */
7849e7c127fSCraig Rodrigues static struct ber_element *
ldap_do_parse_search_filter(struct ber_element * prev,char ** cpp)7859e7c127fSCraig Rodrigues ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
7869e7c127fSCraig Rodrigues {
7879e7c127fSCraig Rodrigues struct ber_element *elm, *root = NULL;
7889e7c127fSCraig Rodrigues char *attr_desc, *attr_val, *parsed_val, *cp;
7899e7c127fSCraig Rodrigues size_t len;
7909e7c127fSCraig Rodrigues unsigned long type;
7919e7c127fSCraig Rodrigues
7929e7c127fSCraig Rodrigues root = NULL;
7939e7c127fSCraig Rodrigues
7949e7c127fSCraig Rodrigues /* cpp should pass in pointer to opening parenthesis of "(filter)" */
7959e7c127fSCraig Rodrigues cp = *cpp;
7969e7c127fSCraig Rodrigues if (*cp != '(')
7979e7c127fSCraig Rodrigues goto syntaxfail;
7989e7c127fSCraig Rodrigues
7999e7c127fSCraig Rodrigues switch (*++cp) {
8009e7c127fSCraig Rodrigues case '&': /* AND */
8019e7c127fSCraig Rodrigues case '|': /* OR */
8029e7c127fSCraig Rodrigues if (*cp == '&')
8039e7c127fSCraig Rodrigues type = LDAP_FILT_AND;
8049e7c127fSCraig Rodrigues else
8059e7c127fSCraig Rodrigues type = LDAP_FILT_OR;
8069e7c127fSCraig Rodrigues
8079e7c127fSCraig Rodrigues if ((elm = ber_add_set(prev)) == NULL)
8089e7c127fSCraig Rodrigues goto callfail;
8099e7c127fSCraig Rodrigues root = elm;
8109e7c127fSCraig Rodrigues ber_set_header(elm, BER_CLASS_CONTEXT, type);
8119e7c127fSCraig Rodrigues
8129e7c127fSCraig Rodrigues if (*++cp != '(') /* opening `(` of filter */
8139e7c127fSCraig Rodrigues goto syntaxfail;
8149e7c127fSCraig Rodrigues
8159e7c127fSCraig Rodrigues while (*cp == '(') {
8169e7c127fSCraig Rodrigues if ((elm =
8179e7c127fSCraig Rodrigues ldap_do_parse_search_filter(elm, &cp)) == NULL)
8189e7c127fSCraig Rodrigues goto bad;
8199e7c127fSCraig Rodrigues }
8209e7c127fSCraig Rodrigues
8219e7c127fSCraig Rodrigues if (*cp != ')') /* trailing `)` of filter */
8229e7c127fSCraig Rodrigues goto syntaxfail;
8239e7c127fSCraig Rodrigues break;
8249e7c127fSCraig Rodrigues
8259e7c127fSCraig Rodrigues case '!': /* NOT */
8269e7c127fSCraig Rodrigues if ((root = ber_add_sequence(prev)) == NULL)
8279e7c127fSCraig Rodrigues goto callfail;
8289e7c127fSCraig Rodrigues ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
8299e7c127fSCraig Rodrigues
8309e7c127fSCraig Rodrigues cp++; /* now points to sub-filter */
8319e7c127fSCraig Rodrigues if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
8329e7c127fSCraig Rodrigues goto bad;
8339e7c127fSCraig Rodrigues
8349e7c127fSCraig Rodrigues if (*cp != ')') /* trailing `)` of filter */
8359e7c127fSCraig Rodrigues goto syntaxfail;
8369e7c127fSCraig Rodrigues break;
8379e7c127fSCraig Rodrigues
8389e7c127fSCraig Rodrigues default: /* SIMPLE || PRESENCE */
8399e7c127fSCraig Rodrigues attr_desc = cp;
8409e7c127fSCraig Rodrigues
8419e7c127fSCraig Rodrigues len = strcspn(cp, "()<>~=");
8429e7c127fSCraig Rodrigues cp += len;
8439e7c127fSCraig Rodrigues switch (*cp) {
8449e7c127fSCraig Rodrigues case '~':
8459e7c127fSCraig Rodrigues type = LDAP_FILT_APPR;
8469e7c127fSCraig Rodrigues cp++;
8479e7c127fSCraig Rodrigues break;
8489e7c127fSCraig Rodrigues case '<':
8499e7c127fSCraig Rodrigues type = LDAP_FILT_LE;
8509e7c127fSCraig Rodrigues cp++;
8519e7c127fSCraig Rodrigues break;
8529e7c127fSCraig Rodrigues case '>':
8539e7c127fSCraig Rodrigues type = LDAP_FILT_GE;
8549e7c127fSCraig Rodrigues cp++;
8559e7c127fSCraig Rodrigues break;
8569e7c127fSCraig Rodrigues case '=':
8579e7c127fSCraig Rodrigues type = LDAP_FILT_EQ; /* assume EQ until disproven */
8589e7c127fSCraig Rodrigues break;
8599e7c127fSCraig Rodrigues case '(':
8609e7c127fSCraig Rodrigues case ')':
8619e7c127fSCraig Rodrigues default:
8629e7c127fSCraig Rodrigues goto syntaxfail;
8639e7c127fSCraig Rodrigues }
8649e7c127fSCraig Rodrigues attr_val = ++cp;
8659e7c127fSCraig Rodrigues
8669e7c127fSCraig Rodrigues /* presence filter */
8679e7c127fSCraig Rodrigues if (strncmp(attr_val, "*)", 2) == 0) {
8689e7c127fSCraig Rodrigues cp++; /* point to trailing `)` */
8699e7c127fSCraig Rodrigues if ((root =
8709e7c127fSCraig Rodrigues ber_add_nstring(prev, attr_desc, len)) == NULL)
8719e7c127fSCraig Rodrigues goto bad;
8729e7c127fSCraig Rodrigues
8739e7c127fSCraig Rodrigues ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
8749e7c127fSCraig Rodrigues break;
8759e7c127fSCraig Rodrigues }
8769e7c127fSCraig Rodrigues
8779e7c127fSCraig Rodrigues if ((root = ber_add_sequence(prev)) == NULL)
8789e7c127fSCraig Rodrigues goto callfail;
8799e7c127fSCraig Rodrigues ber_set_header(root, BER_CLASS_CONTEXT, type);
8809e7c127fSCraig Rodrigues
8819e7c127fSCraig Rodrigues if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL)
8829e7c127fSCraig Rodrigues goto callfail;
8839e7c127fSCraig Rodrigues
8849e7c127fSCraig Rodrigues len = strcspn(attr_val, "*)");
8859e7c127fSCraig Rodrigues if (len == 0 && *cp != '*')
8869e7c127fSCraig Rodrigues goto syntaxfail;
8879e7c127fSCraig Rodrigues cp += len;
8889e7c127fSCraig Rodrigues if (*cp == '\0')
8899e7c127fSCraig Rodrigues goto syntaxfail;
8909e7c127fSCraig Rodrigues
8919e7c127fSCraig Rodrigues if (*cp == '*') { /* substring filter */
8929e7c127fSCraig Rodrigues int initial;
8939e7c127fSCraig Rodrigues
8949e7c127fSCraig Rodrigues cp = attr_val;
8959e7c127fSCraig Rodrigues
8969e7c127fSCraig Rodrigues ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
8979e7c127fSCraig Rodrigues
8989e7c127fSCraig Rodrigues if ((elm = ber_add_sequence(elm)) == NULL)
8999e7c127fSCraig Rodrigues goto callfail;
9009e7c127fSCraig Rodrigues
9019e7c127fSCraig Rodrigues for (initial = 1;; cp++, initial = 0) {
9029e7c127fSCraig Rodrigues attr_val = cp;
9039e7c127fSCraig Rodrigues
9049e7c127fSCraig Rodrigues len = strcspn(attr_val, "*)");
9059e7c127fSCraig Rodrigues if (len == 0) {
9069e7c127fSCraig Rodrigues if (*cp == ')')
9079e7c127fSCraig Rodrigues break;
9089e7c127fSCraig Rodrigues else
9099e7c127fSCraig Rodrigues continue;
9109e7c127fSCraig Rodrigues }
9119e7c127fSCraig Rodrigues cp += len;
9129e7c127fSCraig Rodrigues if (*cp == '\0')
9139e7c127fSCraig Rodrigues goto syntaxfail;
9149e7c127fSCraig Rodrigues
9159e7c127fSCraig Rodrigues if (initial)
9169e7c127fSCraig Rodrigues type = LDAP_FILT_SUBS_INIT;
9179e7c127fSCraig Rodrigues else if (*cp == ')')
9189e7c127fSCraig Rodrigues type = LDAP_FILT_SUBS_FIN;
9199e7c127fSCraig Rodrigues else
9209e7c127fSCraig Rodrigues type = LDAP_FILT_SUBS_ANY;
9219e7c127fSCraig Rodrigues
9229e7c127fSCraig Rodrigues if ((parsed_val = parseval(attr_val, len)) ==
9239e7c127fSCraig Rodrigues NULL)
9249e7c127fSCraig Rodrigues goto callfail;
9259e7c127fSCraig Rodrigues elm = ber_add_nstring(elm, parsed_val,
9269e7c127fSCraig Rodrigues strlen(parsed_val));
9279e7c127fSCraig Rodrigues free(parsed_val);
9289e7c127fSCraig Rodrigues if (elm == NULL)
9299e7c127fSCraig Rodrigues goto callfail;
9309e7c127fSCraig Rodrigues ber_set_header(elm, BER_CLASS_CONTEXT, type);
9319e7c127fSCraig Rodrigues if (type == LDAP_FILT_SUBS_FIN)
9329e7c127fSCraig Rodrigues break;
9339e7c127fSCraig Rodrigues }
9349e7c127fSCraig Rodrigues break;
9359e7c127fSCraig Rodrigues }
9369e7c127fSCraig Rodrigues
9379e7c127fSCraig Rodrigues if ((parsed_val = parseval(attr_val, len)) == NULL)
9389e7c127fSCraig Rodrigues goto callfail;
9399e7c127fSCraig Rodrigues elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val));
9409e7c127fSCraig Rodrigues free(parsed_val);
9419e7c127fSCraig Rodrigues if (elm == NULL)
9429e7c127fSCraig Rodrigues goto callfail;
9439e7c127fSCraig Rodrigues break;
9449e7c127fSCraig Rodrigues }
9459e7c127fSCraig Rodrigues
9469e7c127fSCraig Rodrigues cp++; /* now points one char beyond the trailing `)` */
9479e7c127fSCraig Rodrigues
9489e7c127fSCraig Rodrigues *cpp = cp;
9499e7c127fSCraig Rodrigues return (root);
9509e7c127fSCraig Rodrigues
9519e7c127fSCraig Rodrigues syntaxfail: /* XXX -- error reporting */
9529e7c127fSCraig Rodrigues callfail:
9539e7c127fSCraig Rodrigues bad:
9549e7c127fSCraig Rodrigues if (root != NULL)
9559e7c127fSCraig Rodrigues ber_free_elements(root);
9569e7c127fSCraig Rodrigues ber_link_elements(prev, NULL);
9579e7c127fSCraig Rodrigues return (NULL);
9589e7c127fSCraig Rodrigues }
9599e7c127fSCraig Rodrigues
9609e7c127fSCraig Rodrigues #ifdef DEBUG
9619e7c127fSCraig Rodrigues /*
9629e7c127fSCraig Rodrigues * Display a list of ber elements.
9639e7c127fSCraig Rodrigues *
9649e7c127fSCraig Rodrigues */
9659e7c127fSCraig Rodrigues void
ldap_debug_elements(struct ber_element * root)9669e7c127fSCraig Rodrigues ldap_debug_elements(struct ber_element *root)
9679e7c127fSCraig Rodrigues {
9689e7c127fSCraig Rodrigues static int indent = 0;
9699e7c127fSCraig Rodrigues long long v;
9709e7c127fSCraig Rodrigues int d;
9719e7c127fSCraig Rodrigues char *buf;
9729e7c127fSCraig Rodrigues size_t len;
9739e7c127fSCraig Rodrigues u_int i;
9749e7c127fSCraig Rodrigues int constructed;
9759e7c127fSCraig Rodrigues struct ber_oid o;
9769e7c127fSCraig Rodrigues
9779e7c127fSCraig Rodrigues /* calculate lengths */
9789e7c127fSCraig Rodrigues ber_calc_len(root);
9799e7c127fSCraig Rodrigues
9809e7c127fSCraig Rodrigues switch (root->be_encoding) {
9819e7c127fSCraig Rodrigues case BER_TYPE_SEQUENCE:
9829e7c127fSCraig Rodrigues case BER_TYPE_SET:
9839e7c127fSCraig Rodrigues constructed = root->be_encoding;
9849e7c127fSCraig Rodrigues break;
9859e7c127fSCraig Rodrigues default:
9869e7c127fSCraig Rodrigues constructed = 0;
9879e7c127fSCraig Rodrigues break;
9889e7c127fSCraig Rodrigues }
9899e7c127fSCraig Rodrigues
9909e7c127fSCraig Rodrigues fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
9919e7c127fSCraig Rodrigues switch (root->be_class) {
9929e7c127fSCraig Rodrigues case BER_CLASS_UNIVERSAL:
9939e7c127fSCraig Rodrigues fprintf(stderr, "class: universal(%u) type: ", root->be_class);
9949e7c127fSCraig Rodrigues switch (root->be_type) {
9959e7c127fSCraig Rodrigues case BER_TYPE_EOC:
9969e7c127fSCraig Rodrigues fprintf(stderr, "end-of-content");
9979e7c127fSCraig Rodrigues break;
9989e7c127fSCraig Rodrigues case BER_TYPE_BOOLEAN:
9999e7c127fSCraig Rodrigues fprintf(stderr, "boolean");
10009e7c127fSCraig Rodrigues break;
10019e7c127fSCraig Rodrigues case BER_TYPE_INTEGER:
10029e7c127fSCraig Rodrigues fprintf(stderr, "integer");
10039e7c127fSCraig Rodrigues break;
10049e7c127fSCraig Rodrigues case BER_TYPE_BITSTRING:
10059e7c127fSCraig Rodrigues fprintf(stderr, "bit-string");
10069e7c127fSCraig Rodrigues break;
10079e7c127fSCraig Rodrigues case BER_TYPE_OCTETSTRING:
10089e7c127fSCraig Rodrigues fprintf(stderr, "octet-string");
10099e7c127fSCraig Rodrigues break;
10109e7c127fSCraig Rodrigues case BER_TYPE_NULL:
10119e7c127fSCraig Rodrigues fprintf(stderr, "null");
10129e7c127fSCraig Rodrigues break;
10139e7c127fSCraig Rodrigues case BER_TYPE_OBJECT:
10149e7c127fSCraig Rodrigues fprintf(stderr, "object");
10159e7c127fSCraig Rodrigues break;
10169e7c127fSCraig Rodrigues case BER_TYPE_ENUMERATED:
10179e7c127fSCraig Rodrigues fprintf(stderr, "enumerated");
10189e7c127fSCraig Rodrigues break;
10199e7c127fSCraig Rodrigues case BER_TYPE_SEQUENCE:
10209e7c127fSCraig Rodrigues fprintf(stderr, "sequence");
10219e7c127fSCraig Rodrigues break;
10229e7c127fSCraig Rodrigues case BER_TYPE_SET:
10239e7c127fSCraig Rodrigues fprintf(stderr, "set");
10249e7c127fSCraig Rodrigues break;
10259e7c127fSCraig Rodrigues }
10269e7c127fSCraig Rodrigues break;
10279e7c127fSCraig Rodrigues case BER_CLASS_APPLICATION:
10289e7c127fSCraig Rodrigues fprintf(stderr, "class: application(%u) type: ",
10299e7c127fSCraig Rodrigues root->be_class);
10309e7c127fSCraig Rodrigues switch (root->be_type) {
10319e7c127fSCraig Rodrigues case LDAP_REQ_BIND:
10329e7c127fSCraig Rodrigues fprintf(stderr, "bind");
10339e7c127fSCraig Rodrigues break;
10349e7c127fSCraig Rodrigues case LDAP_RES_BIND:
10359e7c127fSCraig Rodrigues fprintf(stderr, "bind");
10369e7c127fSCraig Rodrigues break;
10379e7c127fSCraig Rodrigues case LDAP_REQ_UNBIND_30:
10389e7c127fSCraig Rodrigues break;
10399e7c127fSCraig Rodrigues case LDAP_REQ_SEARCH:
10409e7c127fSCraig Rodrigues fprintf(stderr, "search");
10419e7c127fSCraig Rodrigues break;
10429e7c127fSCraig Rodrigues case LDAP_RES_SEARCH_ENTRY:
10439e7c127fSCraig Rodrigues fprintf(stderr, "search_entry");
10449e7c127fSCraig Rodrigues break;
10459e7c127fSCraig Rodrigues case LDAP_RES_SEARCH_RESULT:
10469e7c127fSCraig Rodrigues fprintf(stderr, "search_result");
10479e7c127fSCraig Rodrigues break;
10489e7c127fSCraig Rodrigues case LDAP_REQ_MODIFY:
10499e7c127fSCraig Rodrigues fprintf(stderr, "modify");
10509e7c127fSCraig Rodrigues break;
10519e7c127fSCraig Rodrigues case LDAP_RES_MODIFY:
10529e7c127fSCraig Rodrigues fprintf(stderr, "modify");
10539e7c127fSCraig Rodrigues break;
10549e7c127fSCraig Rodrigues case LDAP_REQ_ADD:
10559e7c127fSCraig Rodrigues fprintf(stderr, "add");
10569e7c127fSCraig Rodrigues break;
10579e7c127fSCraig Rodrigues case LDAP_RES_ADD:
10589e7c127fSCraig Rodrigues fprintf(stderr, "add");
10599e7c127fSCraig Rodrigues break;
10609e7c127fSCraig Rodrigues case LDAP_REQ_DELETE_30:
10619e7c127fSCraig Rodrigues fprintf(stderr, "delete");
10629e7c127fSCraig Rodrigues break;
10639e7c127fSCraig Rodrigues case LDAP_RES_DELETE:
10649e7c127fSCraig Rodrigues fprintf(stderr, "delete");
10659e7c127fSCraig Rodrigues break;
10669e7c127fSCraig Rodrigues case LDAP_REQ_MODRDN:
10679e7c127fSCraig Rodrigues fprintf(stderr, "modrdn");
10689e7c127fSCraig Rodrigues break;
10699e7c127fSCraig Rodrigues case LDAP_RES_MODRDN:
10709e7c127fSCraig Rodrigues fprintf(stderr, "modrdn");
10719e7c127fSCraig Rodrigues break;
10729e7c127fSCraig Rodrigues case LDAP_REQ_COMPARE:
10739e7c127fSCraig Rodrigues fprintf(stderr, "compare");
10749e7c127fSCraig Rodrigues break;
10759e7c127fSCraig Rodrigues case LDAP_RES_COMPARE:
10769e7c127fSCraig Rodrigues fprintf(stderr, "compare");
10779e7c127fSCraig Rodrigues break;
10789e7c127fSCraig Rodrigues case LDAP_REQ_ABANDON_30:
10799e7c127fSCraig Rodrigues fprintf(stderr, "abandon");
10809e7c127fSCraig Rodrigues break;
10819e7c127fSCraig Rodrigues }
10829e7c127fSCraig Rodrigues break;
10839e7c127fSCraig Rodrigues case BER_CLASS_PRIVATE:
10849e7c127fSCraig Rodrigues fprintf(stderr, "class: private(%u) type: ", root->be_class);
10859e7c127fSCraig Rodrigues fprintf(stderr, "encoding (%lu) type: ", root->be_encoding);
10869e7c127fSCraig Rodrigues break;
10879e7c127fSCraig Rodrigues case BER_CLASS_CONTEXT:
10889e7c127fSCraig Rodrigues /* XXX: this is not correct */
10899e7c127fSCraig Rodrigues fprintf(stderr, "class: context(%u) type: ", root->be_class);
10909e7c127fSCraig Rodrigues switch(root->be_type) {
10919e7c127fSCraig Rodrigues case LDAP_AUTH_SIMPLE:
10929e7c127fSCraig Rodrigues fprintf(stderr, "auth simple");
10939e7c127fSCraig Rodrigues break;
10949e7c127fSCraig Rodrigues }
10959e7c127fSCraig Rodrigues break;
10969e7c127fSCraig Rodrigues default:
10979e7c127fSCraig Rodrigues fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
10989e7c127fSCraig Rodrigues break;
10999e7c127fSCraig Rodrigues }
11009e7c127fSCraig Rodrigues fprintf(stderr, "(%lu) encoding %lu ",
11019e7c127fSCraig Rodrigues root->be_type, root->be_encoding);
11029e7c127fSCraig Rodrigues
11039e7c127fSCraig Rodrigues if (constructed)
11049e7c127fSCraig Rodrigues root->be_encoding = constructed;
11059e7c127fSCraig Rodrigues
11069e7c127fSCraig Rodrigues switch (root->be_encoding) {
11079e7c127fSCraig Rodrigues case BER_TYPE_BOOLEAN:
11089e7c127fSCraig Rodrigues if (ber_get_boolean(root, &d) == -1) {
11099e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11109e7c127fSCraig Rodrigues break;
11119e7c127fSCraig Rodrigues }
11129e7c127fSCraig Rodrigues fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
11139e7c127fSCraig Rodrigues break;
11149e7c127fSCraig Rodrigues case BER_TYPE_INTEGER:
11159e7c127fSCraig Rodrigues if (ber_get_integer(root, &v) == -1) {
11169e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11179e7c127fSCraig Rodrigues break;
11189e7c127fSCraig Rodrigues }
11199e7c127fSCraig Rodrigues fprintf(stderr, "value %lld\n", v);
11209e7c127fSCraig Rodrigues break;
11219e7c127fSCraig Rodrigues case BER_TYPE_ENUMERATED:
11229e7c127fSCraig Rodrigues if (ber_get_enumerated(root, &v) == -1) {
11239e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11249e7c127fSCraig Rodrigues break;
11259e7c127fSCraig Rodrigues }
11269e7c127fSCraig Rodrigues fprintf(stderr, "value %lld\n", v);
11279e7c127fSCraig Rodrigues break;
11289e7c127fSCraig Rodrigues case BER_TYPE_BITSTRING:
11299e7c127fSCraig Rodrigues if (ber_get_bitstring(root, (void *)&buf, &len) == -1) {
11309e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11319e7c127fSCraig Rodrigues break;
11329e7c127fSCraig Rodrigues }
11339e7c127fSCraig Rodrigues fprintf(stderr, "hexdump ");
11349e7c127fSCraig Rodrigues for (i = 0; i < len; i++)
11359e7c127fSCraig Rodrigues fprintf(stderr, "%02x", buf[i]);
11369e7c127fSCraig Rodrigues fprintf(stderr, "\n");
11379e7c127fSCraig Rodrigues break;
11389e7c127fSCraig Rodrigues case BER_TYPE_OBJECT:
11399e7c127fSCraig Rodrigues if (ber_get_oid(root, &o) == -1) {
11409e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11419e7c127fSCraig Rodrigues break;
11429e7c127fSCraig Rodrigues }
11439e7c127fSCraig Rodrigues fprintf(stderr, "\n");
11449e7c127fSCraig Rodrigues break;
11459e7c127fSCraig Rodrigues case BER_TYPE_OCTETSTRING:
11469e7c127fSCraig Rodrigues if (ber_get_nstring(root, (void *)&buf, &len) == -1) {
11479e7c127fSCraig Rodrigues fprintf(stderr, "<INVALID>\n");
11489e7c127fSCraig Rodrigues break;
11499e7c127fSCraig Rodrigues }
11509e7c127fSCraig Rodrigues fprintf(stderr, "string \"%.*s\"\n", len, buf);
11519e7c127fSCraig Rodrigues break;
11529e7c127fSCraig Rodrigues case BER_TYPE_NULL: /* no payload */
11539e7c127fSCraig Rodrigues case BER_TYPE_EOC:
11549e7c127fSCraig Rodrigues case BER_TYPE_SEQUENCE:
11559e7c127fSCraig Rodrigues case BER_TYPE_SET:
11569e7c127fSCraig Rodrigues default:
11579e7c127fSCraig Rodrigues fprintf(stderr, "\n");
11589e7c127fSCraig Rodrigues break;
11599e7c127fSCraig Rodrigues }
11609e7c127fSCraig Rodrigues
11619e7c127fSCraig Rodrigues if (constructed && root->be_sub) {
11629e7c127fSCraig Rodrigues indent += 2;
11639e7c127fSCraig Rodrigues ldap_debug_elements(root->be_sub);
11649e7c127fSCraig Rodrigues indent -= 2;
11659e7c127fSCraig Rodrigues }
11669e7c127fSCraig Rodrigues if (root->be_next)
11679e7c127fSCraig Rodrigues ldap_debug_elements(root->be_next);
11689e7c127fSCraig Rodrigues }
11699e7c127fSCraig Rodrigues #endif
11709e7c127fSCraig Rodrigues
11719e7c127fSCraig Rodrigues /*
1172eed7cf8dSMarcelo Araujo * Strip UTF-8 down to ASCII without validation.
11739e7c127fSCraig Rodrigues * notes:
11749e7c127fSCraig Rodrigues * non-ASCII characters are displayed as '?'
11759e7c127fSCraig Rodrigues * the argument u should be a NULL terminated sequence of UTF-8 bytes.
11769e7c127fSCraig Rodrigues */
11779e7c127fSCraig Rodrigues char *
utoa(char * u)11789e7c127fSCraig Rodrigues utoa(char *u)
11799e7c127fSCraig Rodrigues {
11809e7c127fSCraig Rodrigues int len, i, j;
11819e7c127fSCraig Rodrigues char *str;
11829e7c127fSCraig Rodrigues
11839e7c127fSCraig Rodrigues /* calculate the length to allocate */
1184eed7cf8dSMarcelo Araujo for (len = 0, i = 0; u[i] != '\0'; i++)
1185eed7cf8dSMarcelo Araujo if (!isu8cont(u[i]))
11869e7c127fSCraig Rodrigues len++;
11879e7c127fSCraig Rodrigues
11889e7c127fSCraig Rodrigues if ((str = calloc(len + 1, sizeof(char))) == NULL)
11899e7c127fSCraig Rodrigues return NULL;
11909e7c127fSCraig Rodrigues
11919e7c127fSCraig Rodrigues /* copy the ASCII characters to the newly allocated string */
1192eed7cf8dSMarcelo Araujo for (i = 0, j = 0; u[i] != '\0'; i++)
1193eed7cf8dSMarcelo Araujo if (!isu8cont(u[i]))
1194eed7cf8dSMarcelo Araujo str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?';
11959e7c127fSCraig Rodrigues
11969e7c127fSCraig Rodrigues return str;
11979e7c127fSCraig Rodrigues }
11989e7c127fSCraig Rodrigues
1199eed7cf8dSMarcelo Araujo static int
isu8cont(unsigned char c)1200eed7cf8dSMarcelo Araujo isu8cont(unsigned char c)
1201eed7cf8dSMarcelo Araujo {
1202eed7cf8dSMarcelo Araujo return (c & (0x80 | 0x40)) == 0x80;
1203eed7cf8dSMarcelo Araujo }
1204eed7cf8dSMarcelo Araujo
12059e7c127fSCraig Rodrigues /*
12069e7c127fSCraig Rodrigues * Parse a LDAP value
12079e7c127fSCraig Rodrigues * notes:
120859022591SMarcelo Araujo * the argument p should be a NUL-terminated sequence of ASCII bytes.
12099e7c127fSCraig Rodrigues */
12109e7c127fSCraig Rodrigues char *
parseval(char * p,size_t len)12119e7c127fSCraig Rodrigues parseval(char *p, size_t len)
12129e7c127fSCraig Rodrigues {
12139e7c127fSCraig Rodrigues char hex[3];
1214*85a9cb44SMarcelo Araujo char *buffer;
1215*85a9cb44SMarcelo Araujo size_t i, j;
12169e7c127fSCraig Rodrigues
1217*85a9cb44SMarcelo Araujo if ((buffer = calloc(1, len + 1)) == NULL)
12189e7c127fSCraig Rodrigues return NULL;
12199e7c127fSCraig Rodrigues
12209e7c127fSCraig Rodrigues for (i = j = 0; j < len; i++) {
1221*85a9cb44SMarcelo Araujo if (p[j] == '\\') {
1222*85a9cb44SMarcelo Araujo strlcpy(hex, p + j + 1, sizeof(hex));
12239e7c127fSCraig Rodrigues buffer[i] = (char)strtoumax(hex, NULL, 16);
12249e7c127fSCraig Rodrigues j += 3;
12259e7c127fSCraig Rodrigues } else {
1226*85a9cb44SMarcelo Araujo buffer[i] = p[j];
12279e7c127fSCraig Rodrigues j++;
12289e7c127fSCraig Rodrigues }
12299e7c127fSCraig Rodrigues }
12309e7c127fSCraig Rodrigues
12319e7c127fSCraig Rodrigues return buffer;
12329e7c127fSCraig Rodrigues }
12339e7c127fSCraig Rodrigues
12349e7c127fSCraig Rodrigues int
aldap_get_errno(struct aldap * a,const char ** estr)12359e7c127fSCraig Rodrigues aldap_get_errno(struct aldap *a, const char **estr)
12369e7c127fSCraig Rodrigues {
12379e7c127fSCraig Rodrigues switch (a->err) {
12389e7c127fSCraig Rodrigues case ALDAP_ERR_SUCCESS:
12399e7c127fSCraig Rodrigues *estr = "success";
12409e7c127fSCraig Rodrigues break;
12419e7c127fSCraig Rodrigues case ALDAP_ERR_PARSER_ERROR:
12429e7c127fSCraig Rodrigues *estr = "parser failed";
12439e7c127fSCraig Rodrigues break;
12449e7c127fSCraig Rodrigues case ALDAP_ERR_INVALID_FILTER:
12459e7c127fSCraig Rodrigues *estr = "invalid filter";
12469e7c127fSCraig Rodrigues break;
12479e7c127fSCraig Rodrigues case ALDAP_ERR_OPERATION_FAILED:
12489e7c127fSCraig Rodrigues *estr = "operation failed";
12499e7c127fSCraig Rodrigues break;
12509e7c127fSCraig Rodrigues default:
12519e7c127fSCraig Rodrigues *estr = "unknown";
12529e7c127fSCraig Rodrigues break;
12539e7c127fSCraig Rodrigues }
12549e7c127fSCraig Rodrigues return (a->err);
12559e7c127fSCraig Rodrigues }
1256eed7cf8dSMarcelo Araujo
1257