[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.6

1.6     ! martijn     1: /*     $Id: aldap.c,v 1.5 2018/08/12 22:04:09 rob Exp $ */
        !             2: /*     $OpenBSD: aldap.c,v 1.5 2018/08/12 22:04:09 rob Exp $ */
1.1       reyk        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 **);
1.6     ! martijn    42: struct aldap_stringset         *aldap_get_stringset(struct ber_element *);
1.1       reyk       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 *);
1.3       claudio    50: unsigned int                   aldap_application(struct ber_element *);
1.1       reyk       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:
1.3       claudio    64: unsigned int
1.1       reyk       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:        void *ptr;
                    130:        char *data;
                    131:        size_t len, done;
1.5       rob       132:        ssize_t error, wrote;
1.1       reyk      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,
1.3       claudio   171:            LDAP_REQ_EXTENDED, LDAP_STARTTLS_OID, BER_CLASS_CONTEXT, 0);
1.1       reyk      172:        if (ber == NULL) {
                    173:                ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    174:                goto fail;
                    175:        }
                    176:
                    177:        if (aldap_send(ldap, root) == -1)
                    178:                goto fail;
                    179:
                    180:        return (ldap->msgid);
                    181: fail:
                    182:        if (root != NULL)
                    183:                ber_free_elements(root);
                    184:
                    185:        ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    186:        return (-1);
                    187: }
                    188:
                    189: int
                    190: aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
                    191: {
                    192:        struct ber_element *root = NULL, *elm;
                    193:
                    194:        if (binddn == NULL)
                    195:                binddn = "";
                    196:        if (bindcred == NULL)
                    197:                bindcred = "";
                    198:
                    199:        if ((root = ber_add_sequence(NULL)) == NULL)
                    200:                goto fail;
                    201:
                    202:        elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
1.3       claudio   203:            LDAP_REQ_BIND, VERSION, binddn, bindcred, BER_CLASS_CONTEXT,
                    204:            LDAP_AUTH_SIMPLE);
1.1       reyk      205:        if (elm == NULL)
                    206:                goto fail;
                    207:
                    208:        LDAP_DEBUG("aldap_bind", root);
                    209:
                    210:        if (aldap_send(ldap, root) == -1) {
                    211:                root = NULL;
                    212:                goto fail;
                    213:        }
                    214:        return (ldap->msgid);
                    215: fail:
                    216:        if (root != NULL)
                    217:                ber_free_elements(root);
                    218:
                    219:        ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    220:        return (-1);
                    221: }
                    222:
                    223: int
                    224: aldap_unbind(struct aldap *ldap)
                    225: {
                    226:        struct ber_element *root = NULL, *elm;
                    227:
                    228:        if ((root = ber_add_sequence(NULL)) == NULL)
                    229:                goto fail;
                    230:        elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
                    231:            LDAP_REQ_UNBIND_30);
                    232:        if (elm == NULL)
                    233:                goto fail;
                    234:
                    235:        LDAP_DEBUG("aldap_unbind", root);
                    236:
                    237:        if (aldap_send(ldap, root) == -1) {
                    238:                root = NULL;
                    239:                goto fail;
                    240:        }
                    241:        return (ldap->msgid);
                    242: fail:
                    243:        if (root != NULL)
                    244:                ber_free_elements(root);
                    245:
                    246:        ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    247:
                    248:        return (-1);
                    249: }
                    250:
                    251: int
                    252: aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter,
                    253:     char **attrs, int typesonly, int sizelimit, int timelimit,
                    254:     struct aldap_page_control *page)
                    255: {
                    256:        struct ber_element *root = NULL, *ber, *c;
                    257:        int i;
                    258:
                    259:        if ((root = ber_add_sequence(NULL)) == NULL)
                    260:                goto fail;
                    261:
                    262:        ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1.3       claudio   263:            LDAP_REQ_SEARCH);
1.1       reyk      264:        if (ber == NULL) {
                    265:                ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    266:                goto fail;
                    267:        }
                    268:
                    269:        c = ber;
                    270:        ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope,
                    271:                                 (long long)LDAP_DEREF_NEVER, sizelimit,
                    272:                                 timelimit, typesonly);
                    273:        if (ber == NULL) {
                    274:                ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    275:                goto fail;
                    276:        }
                    277:
                    278:        if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) {
                    279:                ldap->err = ALDAP_ERR_PARSER_ERROR;
                    280:                goto fail;
                    281:        }
                    282:
                    283:        if ((ber = ber_add_sequence(ber)) == NULL)
                    284:                goto fail;
                    285:        if (attrs != NULL)
                    286:                for (i = 0; attrs[i] != NULL; i++) {
                    287:                        if ((ber = ber_add_string(ber, attrs[i])) == NULL)
                    288:                                goto fail;
                    289:                }
                    290:
                    291:        aldap_create_page_control(c, 100, page);
                    292:
                    293:        LDAP_DEBUG("aldap_search", root);
                    294:
                    295:        if (aldap_send(ldap, root) == -1) {
                    296:                root = NULL;
                    297:                ldap->err = ALDAP_ERR_OPERATION_FAILED;
                    298:                goto fail;
                    299:        }
                    300:
                    301:        return (ldap->msgid);
                    302:
                    303: fail:
                    304:        if (root != NULL)
                    305:                ber_free_elements(root);
                    306:
                    307:        return (-1);
                    308: }
                    309:
                    310: int
                    311: aldap_create_page_control(struct ber_element *elm, int size,
                    312:     struct aldap_page_control *page)
                    313: {
1.5       rob       314:        ssize_t len;
1.1       reyk      315:        struct ber c;
                    316:        struct ber_element *ber = NULL;
                    317:
                    318:        c.br_wbuf = NULL;
                    319:
                    320:        ber = ber_add_sequence(NULL);
                    321:
                    322:        if (page == NULL) {
                    323:                if (ber_printf_elements(ber, "ds", 50, "") == NULL)
                    324:                        goto fail;
                    325:        } else {
                    326:                if (ber_printf_elements(ber, "dx", 50, page->cookie,
                    327:                            page->cookie_len) == NULL)
                    328:                        goto fail;
                    329:        }
                    330:
                    331:        if ((len = ber_write_elements(&c, ber)) < 1)
                    332:                goto fail;
                    333:        if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
                    334:                                c.br_wbuf, (size_t)len) == NULL)
                    335:                goto fail;
                    336:
                    337:        ber_free_elements(ber);
                    338:        ber_free(&c);
                    339:        return len;
                    340: fail:
                    341:        if (ber != NULL)
                    342:                ber_free_elements(ber);
                    343:        ber_free(&c);
                    344:
                    345:        return (-1);
                    346: }
                    347:
                    348: struct aldap_message *
                    349: aldap_parse(struct aldap *ldap)
                    350: {
                    351:        int                      class;
1.3       claudio   352:        unsigned int             type;
1.1       reyk      353:        long long                msgid = 0;
                    354:        struct aldap_message    *m;
                    355:        struct ber_element      *a = NULL, *ep;
                    356:        char                     rbuf[512];
                    357:        int                      ret, retry;
                    358:
                    359:        if ((m = calloc(1, sizeof(struct aldap_message))) == NULL)
                    360:                return NULL;
                    361:
                    362:        retry = 0;
                    363:        while (m->msg == NULL) {
                    364:                if (retry || EVBUFFER_LENGTH(ldap->buf) == 0) {
                    365:                        if (ldap->tls) {
                    366:                                ret = tls_read(ldap->tls, rbuf, sizeof(rbuf));
                    367:                                if (ret == TLS_WANT_POLLIN ||
                    368:                                    ret == TLS_WANT_POLLOUT)
                    369:                                        continue;
                    370:                        } else
                    371:                                ret = read(ldap->fd, rbuf, sizeof(rbuf));
                    372:
                    373:                        if (ret == -1) {
                    374:                                goto parsefail;
                    375:                        }
                    376:
                    377:                        evbuffer_add(ldap->buf, rbuf, ret);
                    378:                }
                    379:
                    380:                if (EVBUFFER_LENGTH(ldap->buf) > 0) {
                    381:                        ber_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf),
                    382:                            EVBUFFER_LENGTH(ldap->buf));
                    383:                        errno = 0;
                    384:                        m->msg = ber_read_elements(&ldap->ber, NULL);
                    385:                        if (errno != 0 && errno != ECANCELED) {
                    386:                                goto parsefail;
                    387:                        }
                    388:
                    389:                        retry = 1;
                    390:                }
                    391:        }
                    392:
                    393:        evbuffer_drain(ldap->buf, ldap->ber.br_rptr - ldap->ber.br_rbuf);
                    394:
                    395:        LDAP_DEBUG("message", m->msg);
                    396:
                    397:        if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
                    398:                goto parsefail;
                    399:        m->msgid = msgid;
                    400:        m->message_type = type;
                    401:        m->protocol_op = a;
                    402:
                    403:        switch (m->message_type) {
                    404:        case LDAP_RES_BIND:
                    405:        case LDAP_RES_MODIFY:
                    406:        case LDAP_RES_ADD:
                    407:        case LDAP_RES_DELETE:
                    408:        case LDAP_RES_MODRDN:
                    409:        case LDAP_RES_COMPARE:
                    410:        case LDAP_RES_SEARCH_RESULT:
                    411:                if (ber_scanf_elements(m->protocol_op, "{EeSeSe",
                    412:                    &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0)
                    413:                        goto parsefail;
                    414:                if (m->body.res.rescode == LDAP_REFERRAL)
                    415:                        if (ber_scanf_elements(a, "{e", &m->references) != 0)
                    416:                                goto parsefail;
                    417:                if (m->msg->be_sub) {
                    418:                        for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
                    419:                                ber_scanf_elements(ep, "t", &class, &type);
                    420:                                if (class == 2 && type == 0)
                    421:                                        m->page = aldap_parse_page_control(ep->be_sub->be_sub,
                    422:                                            ep->be_sub->be_sub->be_len);
                    423:                        }
                    424:                } else
                    425:                        m->page = NULL;
                    426:                break;
                    427:        case LDAP_RES_SEARCH_ENTRY:
                    428:                if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
                    429:                    &m->body.search.attrs) != 0)
                    430:                        goto parsefail;
                    431:                break;
                    432:        case LDAP_RES_SEARCH_REFERENCE:
                    433:                if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
                    434:                        goto parsefail;
                    435:                break;
                    436:        case LDAP_RES_EXTENDED:
                    437:                if (ber_scanf_elements(m->protocol_op, "{E",
                    438:                    &m->body.res.rescode) != 0) {
                    439:                        goto parsefail;
                    440:                }
                    441:                break;
                    442:        }
                    443:
                    444:        return m;
                    445: parsefail:
                    446:        evbuffer_drain(ldap->buf, EVBUFFER_LENGTH(ldap->buf));
                    447:        ldap->err = ALDAP_ERR_PARSER_ERROR;
                    448:        aldap_freemsg(m);
                    449:        return NULL;
                    450: }
                    451:
                    452: struct aldap_page_control *
                    453: aldap_parse_page_control(struct ber_element *control, size_t len)
                    454: {
                    455:        char *oid, *s;
                    456:        char *encoded;
                    457:        struct ber b;
                    458:        struct ber_element *elm;
                    459:        struct aldap_page_control *page;
                    460:
                    461:        b.br_wbuf = NULL;
                    462:        ber_scanf_elements(control, "ss", &oid, &encoded);
                    463:        ber_set_readbuf(&b, encoded, control->be_next->be_len);
                    464:        elm = ber_read_elements(&b, NULL);
                    465:
                    466:        if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
                    467:                if (elm != NULL)
                    468:                        ber_free_elements(elm);
                    469:                ber_free(&b);
                    470:                return NULL;
                    471:        }
                    472:
                    473:        ber_scanf_elements(elm->be_sub, "is", &page->size, &s);
                    474:        page->cookie_len = elm->be_sub->be_next->be_len;
                    475:
                    476:        if ((page->cookie = malloc(page->cookie_len)) == NULL) {
                    477:                if (elm != NULL)
                    478:                        ber_free_elements(elm);
                    479:                ber_free(&b);
                    480:                free(page);
                    481:                return NULL;
                    482:        }
                    483:        memcpy(page->cookie, s, page->cookie_len);
                    484:
                    485:        ber_free_elements(elm);
                    486:        ber_free(&b);
                    487:        return page;
                    488: }
                    489:
                    490: void
                    491: aldap_freepage(struct aldap_page_control *page)
                    492: {
                    493:        free(page->cookie);
                    494:        free(page);
                    495: }
                    496:
                    497: void
                    498: aldap_freemsg(struct aldap_message *msg)
                    499: {
                    500:        if (msg->msg)
                    501:                ber_free_elements(msg->msg);
                    502:        free(msg);
                    503: }
                    504:
                    505: int
                    506: aldap_get_resultcode(struct aldap_message *msg)
                    507: {
                    508:        return msg->body.res.rescode;
                    509: }
                    510:
                    511: char *
                    512: aldap_get_dn(struct aldap_message *msg)
                    513: {
                    514:        char *dn;
                    515:
                    516:        if (msg->dn == NULL)
                    517:                return NULL;
                    518:
                    519:        if (ber_get_string(msg->dn, &dn) == -1)
                    520:                return NULL;
                    521:
                    522:        return utoa(dn);
                    523: }
                    524:
1.6     ! martijn   525: struct aldap_stringset *
1.1       reyk      526: aldap_get_references(struct aldap_message *msg)
                    527: {
                    528:        if (msg->references == NULL)
                    529:                return NULL;
                    530:        return aldap_get_stringset(msg->references);
                    531: }
                    532:
                    533: void
                    534: aldap_free_references(char **values)
                    535: {
                    536:        int i;
                    537:
                    538:        if (values == NULL)
                    539:                return;
                    540:
                    541:        for (i = 0; values[i] != NULL; i++)
                    542:                free(values[i]);
                    543:
                    544:        free(values);
                    545: }
                    546:
                    547: char *
                    548: aldap_get_diagmsg(struct aldap_message *msg)
                    549: {
                    550:        char *s;
                    551:
                    552:        if (msg->body.res.diagmsg == NULL)
                    553:                return NULL;
                    554:
                    555:        if (ber_get_string(msg->body.res.diagmsg, &s) == -1)
                    556:                return NULL;
                    557:
                    558:        return utoa(s);
                    559: }
                    560:
                    561: int
                    562: aldap_count_attrs(struct aldap_message *msg)
                    563: {
                    564:        int i;
                    565:        struct ber_element *a;
                    566:
                    567:        if (msg->body.search.attrs == NULL)
                    568:                return (-1);
                    569:
                    570:        for (i = 0, a = msg->body.search.attrs;
                    571:            a != NULL && ber_get_eoc(a) != 0;
                    572:            i++, a = a->be_next)
                    573:                ;
                    574:
                    575:        return i;
                    576: }
                    577:
                    578: int
1.6     ! martijn   579: aldap_first_attr(struct aldap_message *msg, char **outkey,
        !           580:     struct aldap_stringset **outvalues)
1.1       reyk      581: {
                    582:        struct ber_element *b, *c;
                    583:        char *key;
1.6     ! martijn   584:        struct aldap_stringset *ret;
1.1       reyk      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
1.6     ! martijn   609: aldap_next_attr(struct aldap_message *msg, char **outkey,
        !           610:     struct aldap_stringset **outvalues)
1.1       reyk      611: {
                    612:        struct ber_element *a, *b;
                    613:        char *key;
1.6     ! martijn   614:        struct aldap_stringset *ret;
1.1       reyk      615:
                    616:        if (msg->body.search.iter == NULL)
                    617:                goto notfound;
                    618:
                    619:        LDAP_DEBUG("attr", msg->body.search.iter);
                    620:
                    621:        if (ber_get_eoc(msg->body.search.iter) == 0)
                    622:                goto notfound;
                    623:
                    624:        if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
                    625:            != 0)
                    626:                goto fail;
                    627:
                    628:        msg->body.search.iter = msg->body.search.iter->be_next;
                    629:
                    630:        if ((ret = aldap_get_stringset(a)) == NULL)
                    631:                goto fail;
                    632:
                    633:        (*outvalues) = ret;
                    634:        (*outkey) = utoa(key);
                    635:
                    636:        return (1);
                    637: fail:
                    638: notfound:
                    639:        (*outkey) = NULL;
                    640:        (*outvalues) = NULL;
                    641:        return (-1);
                    642: }
                    643:
                    644: int
1.6     ! martijn   645: aldap_match_attr(struct aldap_message *msg, char *inkey,
        !           646:     struct aldap_stringset **outvalues)
1.1       reyk      647: {
                    648:        struct ber_element *a, *b;
                    649:        char *descr = NULL;
1.6     ! martijn   650:        struct aldap_stringset *ret;
1.1       reyk      651:
                    652:        if (msg->body.search.attrs == NULL)
                    653:                goto fail;
                    654:
                    655:        LDAP_DEBUG("attr", msg->body.search.attrs);
                    656:
                    657:        for (a = msg->body.search.attrs;;) {
                    658:                if (a == NULL)
                    659:                        goto notfound;
                    660:                if (ber_get_eoc(a) == 0)
                    661:                        goto notfound;
                    662:                if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0)
                    663:                        goto fail;
                    664:                if (strcasecmp(descr, inkey) == 0)
                    665:                        goto attrfound;
                    666:                a = a->be_next;
                    667:        }
                    668:
                    669: attrfound:
                    670:        if ((ret = aldap_get_stringset(b)) == NULL)
                    671:                goto fail;
                    672:
                    673:        (*outvalues) = ret;
                    674:
                    675:        return (1);
                    676: fail:
                    677: notfound:
                    678:        (*outvalues) = NULL;
                    679:        return (-1);
                    680: }
                    681:
                    682: int
1.6     ! martijn   683: aldap_free_attr(struct aldap_stringset *values)
1.1       reyk      684: {
                    685:        if (values == NULL)
                    686:                return -1;
                    687:
1.6     ! martijn   688:        free(values->str);
1.1       reyk      689:        free(values);
                    690:
                    691:        return (1);
                    692: }
                    693:
                    694: void
                    695: aldap_free_url(struct aldap_url *lu)
                    696: {
                    697:        free(lu->buffer);
                    698: }
                    699:
                    700: int
                    701: aldap_parse_url(const char *url, struct aldap_url *lu)
                    702: {
                    703:        char            *p, *forward, *forward2;
                    704:        const char      *errstr = NULL;
                    705:        int              i;
                    706:
                    707:        if ((lu->buffer = p = strdup(url)) == NULL)
                    708:                return (-1);
                    709:
                    710:        /* protocol */
                    711:        if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
                    712:                lu->protocol = LDAP;
                    713:                p += strlen(LDAP_URL);
                    714:        } else if (strncasecmp(LDAPS_URL, p, strlen(LDAPS_URL)) == 0) {
                    715:                lu->protocol = LDAPS;
                    716:                p += strlen(LDAPS_URL);
                    717:        } else if (strncasecmp(LDAPTLS_URL, p, strlen(LDAPTLS_URL)) == 0) {
                    718:                lu->protocol = LDAPTLS;
                    719:                p += strlen(LDAPTLS_URL);
                    720:        } else if (strncasecmp(LDAPI_URL, p, strlen(LDAPI_URL)) == 0) {
                    721:                lu->protocol = LDAPI;
                    722:                p += strlen(LDAPI_URL);
                    723:        } else
                    724:                lu->protocol = -1;
                    725:
                    726:        /* host and optional port */
                    727:        if ((forward = strchr(p, '/')) != NULL)
                    728:                *forward = '\0';
                    729:        /* find the optional port */
                    730:        if ((forward2 = strchr(p, ':')) != NULL) {
                    731:                *forward2 = '\0';
                    732:                /* if a port is given */
                    733:                if (*(forward2+1) != '\0') {
                    734: #define PORT_MAX UINT16_MAX
                    735:                        lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
                    736:                        if (errstr)
                    737:                                goto fail;
                    738:                }
                    739:        }
                    740:        /* fail if no host is given */
                    741:        if (strlen(p) == 0)
                    742:                goto fail;
                    743:        lu->host = p;
                    744:        if (forward == NULL)
                    745:                goto done;
                    746:        /* p is assigned either a pointer to a character or to '\0' */
                    747:        p = ++forward;
                    748:        if (strlen(p) == 0)
                    749:                goto done;
                    750:
                    751:        /* dn */
                    752:        if ((forward = strchr(p, '?')) != NULL)
                    753:                *forward = '\0';
                    754:        lu->dn = p;
                    755:        if (forward == NULL)
                    756:                goto done;
                    757:        /* p is assigned either a pointer to a character or to '\0' */
                    758:        p = ++forward;
                    759:        if (strlen(p) == 0)
                    760:                goto done;
                    761:
                    762:        /* attributes */
                    763:        if ((forward = strchr(p, '?')) != NULL)
                    764:                *forward = '\0';
                    765:        for (i = 0; i < MAXATTR; i++) {
                    766:                if ((forward2 = strchr(p, ',')) == NULL) {
                    767:                        if (strlen(p) == 0)
                    768:                                break;
                    769:                        lu->attributes[i] = p;
                    770:                        break;
                    771:                }
                    772:                *forward2 = '\0';
                    773:                lu->attributes[i] = p;
                    774:                p = ++forward2;
                    775:        }
                    776:        if (forward == NULL)
                    777:                goto done;
                    778:        /* p is assigned either a pointer to a character or to '\0' */
                    779:        p = ++forward;
                    780:        if (strlen(p) == 0)
                    781:                goto done;
                    782:
                    783:        /* scope */
                    784:        if ((forward = strchr(p, '?')) != NULL)
                    785:                *forward = '\0';
                    786:        if (strcmp(p, "base") == 0)
                    787:                lu->scope = LDAP_SCOPE_BASE;
                    788:        else if (strcmp(p, "one") == 0)
                    789:                lu->scope = LDAP_SCOPE_ONELEVEL;
                    790:        else if (strcmp(p, "sub") == 0)
                    791:                lu->scope = LDAP_SCOPE_SUBTREE;
                    792:        else
                    793:                goto fail;
                    794:        if (forward == NULL)
                    795:                goto done;
                    796:        p = ++forward;
                    797:        if (strlen(p) == 0)
                    798:                goto done;
                    799:
                    800:        /* filter */
                    801:        if (p)
                    802:                lu->filter = p;
                    803: done:
                    804:        return (1);
                    805: fail:
                    806:        free(lu->buffer);
                    807:        lu->buffer = NULL;
                    808:        return (-1);
                    809: }
                    810:
                    811: int
                    812: aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
                    813:     int timelimit, struct aldap_page_control *page)
                    814: {
                    815:        struct aldap_url *lu;
                    816:
                    817:        if ((lu = calloc(1, sizeof(*lu))) == NULL)
                    818:                return (-1);
                    819:
                    820:        if (aldap_parse_url(url, lu))
                    821:                goto fail;
                    822:
                    823:        if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
                    824:            typesonly, sizelimit, timelimit, page) == -1)
                    825:                goto fail;
                    826:
                    827:        aldap_free_url(lu);
                    828:        return (ldap->msgid);
                    829: fail:
                    830:        aldap_free_url(lu);
                    831:        return (-1);
                    832: }
                    833:
                    834: /*
                    835:  * internal functions
                    836:  */
                    837:
1.6     ! martijn   838: struct aldap_stringset *
1.1       reyk      839: aldap_get_stringset(struct ber_element *elm)
                    840: {
                    841:        struct ber_element *a;
                    842:        int i;
1.6     ! martijn   843:        struct aldap_stringset *ret;
1.1       reyk      844:
                    845:        if (elm->be_type != BER_TYPE_OCTETSTRING)
                    846:                return NULL;
                    847:
1.6     ! martijn   848:        if ((ret = malloc(sizeof(*ret))) == NULL)
        !           849:                return NULL;
        !           850:        for (a = elm, ret->len = 0; a != NULL && a->be_type ==
        !           851:            BER_TYPE_OCTETSTRING; a = a->be_next, ret->len++)
1.1       reyk      852:                ;
1.6     ! martijn   853:        if (ret->len == 0) {
        !           854:                free(ret);
1.1       reyk      855:                return NULL;
1.6     ! martijn   856:        }
1.1       reyk      857:
1.6     ! martijn   858:        if ((ret->str = reallocarray(NULL, ret->len,
        !           859:            sizeof(*(ret->str)))) == NULL) {
        !           860:                free(ret);
1.1       reyk      861:                return NULL;
1.6     ! martijn   862:        }
1.1       reyk      863:
                    864:        for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
1.6     ! martijn   865:            a = a->be_next, i++)
        !           866:                (void) ber_get_ostring(a, &(ret->str[i]));
1.1       reyk      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);
1.4       rob      1221:                fprintf(stderr, "encoding (%u) type: ", root->be_encoding);
1.1       reyk     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:        }
1.4       rob      1236:        fprintf(stderr, "(%u) encoding %u ",
1.1       reyk     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:                }
1.2       reyk     1286:                fprintf(stderr, "string \"%.*s\"\n",  (int)len, buf);
1.1       reyk     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: }