[BACK]Return to aldap.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ldap

Annotation of src/usr.bin/ldap/aldap.c, Revision 1.1

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