Date: Mon, 16 Nov 2015 16:48:43 +0000 (UTC) From: Craig Rodrigues <rodrigc@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r290931 - head/usr.sbin/ypldap Message-ID: <201511161648.tAGGmh6q052192@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rodrigc Date: Mon Nov 16 16:48:43 2015 New Revision: 290931 URL: https://svnweb.freebsd.org/changeset/base/290931 Log: Import ypldap from OpenBSD. ypldap -- Intended to be a drop-in replacement for ypserv, gluing in a LDAP directory and thus providing support for users and groups stored in LDAP for the get{pw,gr}ent family of functions. Added: head/usr.sbin/ypldap/ head/usr.sbin/ypldap/Makefile (contents, props changed) head/usr.sbin/ypldap/aldap.c (contents, props changed) head/usr.sbin/ypldap/aldap.h (contents, props changed) head/usr.sbin/ypldap/ber.c (contents, props changed) head/usr.sbin/ypldap/ber.h (contents, props changed) head/usr.sbin/ypldap/entries.c (contents, props changed) head/usr.sbin/ypldap/ldapclient.c (contents, props changed) head/usr.sbin/ypldap/log.c (contents, props changed) head/usr.sbin/ypldap/parse.y (contents, props changed) head/usr.sbin/ypldap/yp.c (contents, props changed) head/usr.sbin/ypldap/ypldap.8 (contents, props changed) head/usr.sbin/ypldap/ypldap.c (contents, props changed) head/usr.sbin/ypldap/ypldap.conf.5 (contents, props changed) head/usr.sbin/ypldap/ypldap.h (contents, props changed) head/usr.sbin/ypldap/ypldap_dns.c (contents, props changed) Added: head/usr.sbin/ypldap/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/ypldap/Makefile Mon Nov 16 16:48:43 2015 (r290931) @@ -0,0 +1,21 @@ +# $OpenBSD: Makefile,v 1.8 2015/09/09 15:33:18 deraadt Exp $ +# $FreeBSD$ + +PROG= ypldap +SRCS= parse.y ypldap.c log.c \ + ldapclient.c entries.c yp.c \ + aldap.c ber.c \ + ypldap_dns.c + +MAN= ypldap.8 ypldap.conf.5 + +DPADD= ${LIBEVENT} ${LIBUTIL} ${LIBRPCSVC} +LDADD= -levent -lutil -lrpcsvc +CFLAGS+= -I${.CURDIR} +CFLAGS+= -Wall +CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+= -Wmissing-declarations +CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+= -Wsign-compare + +.include <bsd.prog.mk> Added: head/usr.sbin/ypldap/aldap.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/ypldap/aldap.c Mon Nov 16 16:48:43 2015 (r290931) @@ -0,0 +1,1273 @@ +/* $Id: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */ +/* $OpenBSD: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */ +/* $FreeBSD$ */ + +/* + * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> + * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <inttypes.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "aldap.h" + +#if 0 +#define DEBUG +#endif +#define VERSION 3 + +static struct ber_element *ldap_parse_search_filter(struct ber_element *, + char *); +static struct ber_element *ldap_do_parse_search_filter( + struct ber_element *, char **); +char **aldap_get_stringset(struct ber_element *); +char *utoa(char *); +char *parseval(char *, size_t); +int aldap_create_page_control(struct ber_element *, + int, struct aldap_page_control *); + +#ifdef DEBUG +void ldap_debug_elements(struct ber_element *); +#endif + +#ifdef DEBUG +#define DPRINTF(x...) printf(x) +#define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0) +#else +#define DPRINTF(x...) do { } while (0) +#define LDAP_DEBUG(x, y) do { } while (0) +#endif + +int +aldap_close(struct aldap *al) +{ + if (close(al->ber.fd) == -1) + return (-1); + + ber_free(&al->ber); + free(al); + + return (0); +} + +struct aldap * +aldap_init(int fd) +{ + struct aldap *a; + + if ((a = calloc(1, sizeof(*a))) == NULL) + return NULL; + a->ber.fd = fd; + + return a; +} + +int +aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) +{ + struct ber_element *root = NULL, *elm; + int error; + + if (binddn == NULL) + binddn = ""; + if (bindcred == NULL) + bindcred = ""; + + if ((root = ber_add_sequence(NULL)) == NULL) + goto fail; + + elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP, + (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred, + BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE); + if (elm == NULL) + goto fail; + + LDAP_DEBUG("aldap_bind", root); + + error = ber_write_elements(&ldap->ber, root); + ber_free_elements(root); + root = NULL; + if (error == -1) + goto fail; + + return (ldap->msgid); +fail: + if (root != NULL) + ber_free_elements(root); + + ldap->err = ALDAP_ERR_OPERATION_FAILED; + return (-1); +} + +int +aldap_unbind(struct aldap *ldap) +{ + struct ber_element *root = NULL, *elm; + int error; + + if ((root = ber_add_sequence(NULL)) == NULL) + goto fail; + elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, + LDAP_REQ_UNBIND_30); + if (elm == NULL) + goto fail; + + LDAP_DEBUG("aldap_unbind", root); + + error = ber_write_elements(&ldap->ber, root); + ber_free_elements(root); + root = NULL; + if (error == -1) + goto fail; + + return (ldap->msgid); +fail: + if (root != NULL) + ber_free_elements(root); + + ldap->err = ALDAP_ERR_OPERATION_FAILED; + + return (-1); +} + +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) +{ + struct ber_element *root = NULL, *ber, *c; + int i, error; + + if ((root = ber_add_sequence(NULL)) == NULL) + goto fail; + + ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP, + (unsigned long) LDAP_REQ_SEARCH); + if (ber == NULL) { + ldap->err = ALDAP_ERR_OPERATION_FAILED; + goto fail; + } + + c = ber; + ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope, + (long long)LDAP_DEREF_NEVER, sizelimit, + timelimit, typesonly); + if (ber == NULL) { + ldap->err = ALDAP_ERR_OPERATION_FAILED; + goto fail; + } + + if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) { + ldap->err = ALDAP_ERR_PARSER_ERROR; + goto fail; + } + + if ((ber = ber_add_sequence(ber)) == NULL) + goto fail; + if (attrs != NULL) + for (i = 0; attrs[i] != NULL; i++) { + if ((ber = ber_add_string(ber, attrs[i])) == NULL) + goto fail; + } + + aldap_create_page_control(c, 100, page); + + LDAP_DEBUG("aldap_search", root); + + error = ber_write_elements(&ldap->ber, root); + ber_free_elements(root); + root = NULL; + if (error == -1) { + ldap->err = ALDAP_ERR_OPERATION_FAILED; + goto fail; + } + + return (ldap->msgid); + +fail: + if (root != NULL) + ber_free_elements(root); + + return (-1); +} + +int +aldap_create_page_control(struct ber_element *elm, int size, + struct aldap_page_control *page) +{ + int len; + struct ber c; + struct ber_element *ber = NULL; + + c.br_wbuf = NULL; + c.fd = -1; + + ber = ber_add_sequence(NULL); + + if (page == NULL) { + if (ber_printf_elements(ber, "ds", 50, "") == NULL) + goto fail; + } else { + if (ber_printf_elements(ber, "dx", 50, page->cookie, + page->cookie_len) == NULL) + goto fail; + } + + if ((len = ber_write_elements(&c, ber)) < 1) + goto fail; + if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID, + c.br_wbuf, (size_t)len) == NULL) + goto fail; + + ber_free_elements(ber); + ber_free(&c); + return len; +fail: + if (ber != NULL) + ber_free_elements(ber); + ber_free(&c); + + return (-1); +} + +struct aldap_message * +aldap_parse(struct aldap *ldap) +{ + int class; + unsigned long type; + long long msgid = 0; + struct aldap_message *m; + struct ber_element *a = NULL, *ep; + + if ((m = calloc(1, sizeof(struct aldap_message))) == NULL) + return NULL; + + if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL) + goto parsefail; + + LDAP_DEBUG("message", m->msg); + + if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0) + goto parsefail; + m->msgid = msgid; + m->message_type = type; + m->protocol_op = a; + + switch (m->message_type) { + case LDAP_RES_BIND: + case LDAP_RES_MODIFY: + case LDAP_RES_ADD: + case LDAP_RES_DELETE: + case LDAP_RES_MODRDN: + case LDAP_RES_COMPARE: + case LDAP_RES_SEARCH_RESULT: + if (ber_scanf_elements(m->protocol_op, "{EeSeSe", + &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0) + goto parsefail; + if (m->body.res.rescode == LDAP_REFERRAL) + if (ber_scanf_elements(a, "{e", &m->references) != 0) + goto parsefail; + if (m->msg->be_sub) { + for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) { + ber_scanf_elements(ep, "t", &class, &type); + if (class == 2 && type == 0) + m->page = aldap_parse_page_control(ep->be_sub->be_sub, + ep->be_sub->be_sub->be_len); + } + } else + m->page = NULL; + break; + case LDAP_RES_SEARCH_ENTRY: + if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn, + &m->body.search.attrs) != 0) + goto parsefail; + break; + case LDAP_RES_SEARCH_REFERENCE: + if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) + goto parsefail; + break; + } + + return m; +parsefail: + ldap->err = ALDAP_ERR_PARSER_ERROR; + aldap_freemsg(m); + return NULL; +} + +struct aldap_page_control * +aldap_parse_page_control(struct ber_element *control, size_t len) +{ + char *oid, *s; + char *encoded; + struct ber b; + struct ber_element *elm; + struct aldap_page_control *page; + + b.br_wbuf = NULL; + b.fd = -1; + ber_scanf_elements(control, "ss", &oid, &encoded); + ber_set_readbuf(&b, encoded, control->be_next->be_len); + elm = ber_read_elements(&b, NULL); + + if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) { + if (elm != NULL) + ber_free_elements(elm); + ber_free(&b); + return NULL; + } + + ber_scanf_elements(elm->be_sub, "is", &page->size, &s); + page->cookie_len = elm->be_sub->be_next->be_len; + + if ((page->cookie = malloc(page->cookie_len)) == NULL) { + if (elm != NULL) + ber_free_elements(elm); + ber_free(&b); + free(page); + return NULL; + } + memcpy(page->cookie, s, page->cookie_len); + + ber_free_elements(elm); + ber_free(&b); + return page; +} + +void +aldap_freepage(struct aldap_page_control *page) +{ + if (page->cookie) + free(page->cookie); + free(page); +} + +void +aldap_freemsg(struct aldap_message *msg) +{ + if (msg->msg) + ber_free_elements(msg->msg); + free(msg); +} + +int +aldap_get_resultcode(struct aldap_message *msg) +{ + return msg->body.res.rescode; +} + +char * +aldap_get_dn(struct aldap_message *msg) +{ + char *dn; + + if (msg->dn == NULL) + return NULL; + + if (ber_get_string(msg->dn, &dn) == -1) + return NULL; + + return utoa(dn); +} + +char ** +aldap_get_references(struct aldap_message *msg) +{ + if (msg->references == NULL) + return NULL; + return aldap_get_stringset(msg->references); +} + +void +aldap_free_references(char **values) +{ + int i; + + if (values == NULL) + return; + + for (i = 0; values[i] != NULL; i++) + free(values[i]); + + free(values); +} + +char * +aldap_get_diagmsg(struct aldap_message *msg) +{ + char *s; + + if (msg->body.res.diagmsg == NULL) + return NULL; + + if (ber_get_string(msg->body.res.diagmsg, &s) == -1) + return NULL; + + return utoa(s); +} + +int +aldap_count_attrs(struct aldap_message *msg) +{ + int i; + struct ber_element *a; + + if (msg->body.search.attrs == NULL) + return (-1); + + for (i = 0, a = msg->body.search.attrs; + a != NULL && ber_get_eoc(a) != 0; + i++, a = a->be_next) + ; + + return i; +} + +int +aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues) +{ + struct ber_element *b, *c; + char *key; + char **ret; + + if (msg->body.search.attrs == NULL) + goto fail; + + if (ber_scanf_elements(msg->body.search.attrs, "{s(e)}e", + &key, &b, &c) != 0) + goto fail; + + msg->body.search.iter = msg->body.search.attrs->be_next; + + if ((ret = aldap_get_stringset(b)) == NULL) + goto fail; + + (*outvalues) = ret; + (*outkey) = utoa(key); + + return (1); +fail: + (*outkey) = NULL; + (*outvalues) = NULL; + return (-1); +} + +int +aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues) +{ + struct ber_element *a, *b; + char *key; + char **ret; + + if (msg->body.search.iter == NULL) + goto notfound; + + LDAP_DEBUG("attr", msg->body.search.iter); + + if (ber_get_eoc(msg->body.search.iter) == 0) + goto notfound; + + if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b) + != 0) + goto fail; + + msg->body.search.iter = msg->body.search.iter->be_next; + + if ((ret = aldap_get_stringset(a)) == NULL) + goto fail; + + (*outvalues) = ret; + (*outkey) = utoa(key); + + return (1); +fail: +notfound: + (*outkey) = NULL; + (*outvalues) = NULL; + return (-1); +} + +int +aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues) +{ + struct ber_element *a, *b; + char *descr = NULL; + char **ret; + + if (msg->body.search.attrs == NULL) + goto fail; + + LDAP_DEBUG("attr", msg->body.search.attrs); + + for (a = msg->body.search.attrs;;) { + if (a == NULL) + goto notfound; + if (ber_get_eoc(a) == 0) + goto notfound; + if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0) + goto fail; + if (strcasecmp(descr, inkey) == 0) + goto attrfound; + a = a->be_next; + } + +attrfound: + if ((ret = aldap_get_stringset(b)) == NULL) + goto fail; + + (*outvalues) = ret; + + return (1); +fail: +notfound: + (*outvalues) = NULL; + return (-1); +} + +int +aldap_free_attr(char **values) +{ + int i; + + if (values == NULL) + return -1; + + for (i = 0; values[i] != NULL; i++) + free(values[i]); + + free(values); + + return (1); +} + +#if 0 +void +aldap_free_url(struct aldap_url *lu) +{ + free(lu->buffer); + free(lu->filter); +} + +int +aldap_parse_url(char *url, struct aldap_url *lu) +{ + char *p, *forward, *forward2; + const char *errstr = NULL; + int i; + + if ((lu->buffer = p = strdup(url)) == NULL) + return (-1); + + /* protocol */ + if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0) + goto fail; + lu->protocol = LDAP; + p += strlen(LDAP_URL); + + /* host and optional port */ + if ((forward = strchr(p, '/')) != NULL) + *forward = '\0'; + /* find the optional port */ + if ((forward2 = strchr(p, ':')) != NULL) { + *forward2 = '\0'; + /* if a port is given */ + if (*(forward2+1) != '\0') { +#define PORT_MAX UINT16_MAX + lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr); + if (errstr) + goto fail; + } + } + /* fail if no host is given */ + if (strlen(p) == 0) + goto fail; + lu->host = p; + if (forward == NULL) + goto done; + /* p is assigned either a pointer to a character or to '\0' */ + p = ++forward; + if (strlen(p) == 0) + goto done; + + /* dn */ + if ((forward = strchr(p, '?')) != NULL) + *forward = '\0'; + lu->dn = p; + if (forward == NULL) + goto done; + /* p is assigned either a pointer to a character or to '\0' */ + p = ++forward; + if (strlen(p) == 0) + goto done; + + /* attributes */ + if ((forward = strchr(p, '?')) != NULL) + *forward = '\0'; + for (i = 0; i < MAXATTR; i++) { + if ((forward2 = strchr(p, ',')) == NULL) { + if (strlen(p) == 0) + break; + lu->attributes[i] = p; + break; + } + *forward2 = '\0'; + lu->attributes[i] = p; + p = ++forward2; + } + if (forward == NULL) + goto done; + /* p is assigned either a pointer to a character or to '\0' */ + p = ++forward; + if (strlen(p) == 0) + goto done; + + /* scope */ + if ((forward = strchr(p, '?')) != NULL) + *forward = '\0'; + if (strcmp(p, "base") == 0) + lu->scope = LDAP_SCOPE_BASE; + else if (strcmp(p, "one") == 0) + lu->scope = LDAP_SCOPE_ONELEVEL; + else if (strcmp(p, "sub") == 0) + lu->scope = LDAP_SCOPE_SUBTREE; + else + goto fail; + if (forward == NULL) + goto done; + p = ++forward; + if (strlen(p) == 0) + goto done; + + /* filter */ + if (p) + lu->filter = p; +done: + free(url); + return (1); +fail: + free(lu->buffer); + lu->buffer = NULL; + return (-1); +} + +int +aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit, + int timelimit) +{ + struct aldap_url *lu; + + if ((lu = calloc(1, sizeof(*lu))) == NULL) + return (-1); + + if (aldap_parse_url(url, lu)) + goto fail; + + if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes, + typesonly, sizelimit, timelimit) == -1) + goto fail; + + aldap_free_url(lu); + return (ldap->msgid); +fail: + aldap_free_url(lu); + return (-1); +} +#endif /* 0 */ + +/* + * internal functions + */ + +char ** +aldap_get_stringset(struct ber_element *elm) +{ + struct ber_element *a; + int i; + char **ret; + char *s; + + if (elm->be_type != BER_TYPE_OCTETSTRING) + return NULL; + + for (a = elm, i = 1; i > 0 && a != NULL && a->be_type == + BER_TYPE_OCTETSTRING; a = a->be_next, i++) + ; + if (i == 1) + return NULL; + + if ((ret = calloc(i + 1, sizeof(char *))) == NULL) + return NULL; + + for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING; + a = a->be_next, i++) { + + ber_get_string(a, &s); + ret[i] = utoa(s); + } + ret[i + 1] = NULL; + + return ret; +} + +/* + * Base case for ldap_do_parse_search_filter + * + * returns: + * struct ber_element *, ber_element tree + * NULL, parse failed + */ +static struct ber_element * +ldap_parse_search_filter(struct ber_element *ber, char *filter) +{ + struct ber_element *elm; + char *cp; + + cp = filter; + + if (cp == NULL || *cp == '\0') { + errno = EINVAL; + return (NULL); + } + + if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL) + return (NULL); + + if (*cp != '\0') { + ber_free_elements(elm); + ber_link_elements(ber, NULL); + errno = EINVAL; + return (NULL); + } + + return (elm); +} + +/* + * Translate RFC4515 search filter string into ber_element tree + * + * returns: + * struct ber_element *, ber_element tree + * NULL, parse failed + * + * notes: + * when cp is passed to a recursive invocation, it is updated + * to point one character beyond the filter that was passed + * i.e., cp jumps to "(filter)" upon return + * ^ + * goto's used to discriminate error-handling based on error type + * doesn't handle extended filters (yet) + * + */ +static struct ber_element * +ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) +{ + struct ber_element *elm, *root = NULL; + char *attr_desc, *attr_val, *parsed_val, *cp; + size_t len; + unsigned long type; + + root = NULL; + + /* cpp should pass in pointer to opening parenthesis of "(filter)" */ + cp = *cpp; + if (*cp != '(') + goto syntaxfail; + + switch (*++cp) { + case '&': /* AND */ + case '|': /* OR */ + if (*cp == '&') + type = LDAP_FILT_AND; + else + type = LDAP_FILT_OR; + + if ((elm = ber_add_set(prev)) == NULL) + goto callfail; + root = elm; + ber_set_header(elm, BER_CLASS_CONTEXT, type); + + if (*++cp != '(') /* opening `(` of filter */ + goto syntaxfail; + + while (*cp == '(') { + if ((elm = + ldap_do_parse_search_filter(elm, &cp)) == NULL) + goto bad; + } + + if (*cp != ')') /* trailing `)` of filter */ + goto syntaxfail; + break; + + case '!': /* NOT */ + if ((root = ber_add_sequence(prev)) == NULL) + goto callfail; + ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT); + + cp++; /* now points to sub-filter */ + if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL) + goto bad; + + if (*cp != ')') /* trailing `)` of filter */ + goto syntaxfail; + break; + + default: /* SIMPLE || PRESENCE */ + attr_desc = cp; + + len = strcspn(cp, "()<>~="); + cp += len; + switch (*cp) { + case '~': + type = LDAP_FILT_APPR; + cp++; + break; + case '<': + type = LDAP_FILT_LE; + cp++; + break; + case '>': + type = LDAP_FILT_GE; + cp++; + break; + case '=': + type = LDAP_FILT_EQ; /* assume EQ until disproven */ + break; + case '(': + case ')': + default: + goto syntaxfail; + } + attr_val = ++cp; + + /* presence filter */ + if (strncmp(attr_val, "*)", 2) == 0) { + cp++; /* point to trailing `)` */ + if ((root = + ber_add_nstring(prev, attr_desc, len)) == NULL) + goto bad; + + ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES); + break; + } + + if ((root = ber_add_sequence(prev)) == NULL) + goto callfail; + ber_set_header(root, BER_CLASS_CONTEXT, type); + + if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL) + goto callfail; + + len = strcspn(attr_val, "*)"); + if (len == 0 && *cp != '*') + goto syntaxfail; + cp += len; + if (*cp == '\0') + goto syntaxfail; + + if (*cp == '*') { /* substring filter */ + int initial; + + cp = attr_val; + + ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS); + + if ((elm = ber_add_sequence(elm)) == NULL) + goto callfail; + + for (initial = 1;; cp++, initial = 0) { + attr_val = cp; + + len = strcspn(attr_val, "*)"); + if (len == 0) { + if (*cp == ')') + break; + else + continue; + } + cp += len; + if (*cp == '\0') + goto syntaxfail; + + if (initial) + type = LDAP_FILT_SUBS_INIT; + else if (*cp == ')') + type = LDAP_FILT_SUBS_FIN; + else + type = LDAP_FILT_SUBS_ANY; + + if ((parsed_val = parseval(attr_val, len)) == + NULL) + goto callfail; + elm = ber_add_nstring(elm, parsed_val, + strlen(parsed_val)); + free(parsed_val); + if (elm == NULL) + goto callfail; + ber_set_header(elm, BER_CLASS_CONTEXT, type); + if (type == LDAP_FILT_SUBS_FIN) + break; + } + break; + } + + if ((parsed_val = parseval(attr_val, len)) == NULL) + goto callfail; + elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val)); + free(parsed_val); + if (elm == NULL) + goto callfail; + break; + } + + cp++; /* now points one char beyond the trailing `)` */ + + *cpp = cp; + return (root); + +syntaxfail: /* XXX -- error reporting */ +callfail: +bad: + if (root != NULL) + ber_free_elements(root); + ber_link_elements(prev, NULL); + return (NULL); +} + +#ifdef DEBUG +/* + * Display a list of ber elements. + * + */ +void +ldap_debug_elements(struct ber_element *root) +{ + static int indent = 0; + long long v; + int d; + char *buf; + size_t len; + u_int i; + int constructed; + struct ber_oid o; + + /* calculate lengths */ + ber_calc_len(root); + + switch (root->be_encoding) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511161648.tAGGmh6q052192>