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

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