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

1.3     ! claudio     1: /*     $Id: aldap.c,v 1.2 2018/06/21 08:27:35 reyk Exp $ */
        !             2: /*     $OpenBSD: aldap.c,v 1.2 2018/06/21 08:27:35 reyk 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 **);
                     42: char                           **aldap_get_stringset(struct ber_element *);
                     43: char                           *utoa(char *);
                     44: static int                      isu8cont(unsigned char);
                     45: char                           *parseval(char *, size_t);
                     46: int                            aldap_create_page_control(struct ber_element *,
                     47:                                    int, struct aldap_page_control *);
                     48: int                            aldap_send(struct aldap *,
                     49:                                    struct ber_element *);
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:        int error, wrote;
                    130:        void *ptr;
                    131:        char *data;
                    132:        size_t len, done;
                    133:
                    134:        len = ber_calc_len(root);
                    135:        error = ber_write_elements(&ldap->ber, root);
                    136:        ber_free_elements(root);
                    137:        if (error == -1)
                    138:                return -1;
                    139:
                    140:        ber_get_writebuf(&ldap->ber, &ptr);
                    141:        done = 0;
                    142:        data = ptr;
                    143:        while (len > 0) {
                    144:                if (ldap->tls != NULL) {
                    145:                        wrote = tls_write(ldap->tls, data + done, len);
                    146:                        if (wrote == TLS_WANT_POLLIN ||
                    147:                            wrote == TLS_WANT_POLLOUT)
                    148:                                continue;
                    149:                } else
                    150:                        wrote = write(ldap->fd, data + done, len);
                    151:
                    152:                if (wrote == -1)
                    153:                        return -1;
                    154:
                    155:                len -= wrote;
                    156:                done += wrote;
                    157:        }
                    158:
                    159:        return 0;
                    160: }
                    161:
                    162: int
                    163: aldap_req_starttls(struct aldap *ldap)
                    164: {
                    165:        struct ber_element *root = NULL, *ber;
                    166:
                    167:        if ((root = ber_add_sequence(NULL)) == NULL)
                    168:                goto fail;
                    169:
                    170:        ber = ber_printf_elements(root, "d{tst", ++ldap->msgid, BER_CLASS_APP,
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: {
                    314:        int len;
                    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:
                    525: char **
                    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
                    579: aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
                    580: {
                    581:        struct ber_element *b, *c;
                    582:        char *key;
                    583:        char **ret;
                    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
                    608: aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
                    609: {
                    610:        struct ber_element *a, *b;
                    611:        char *key;
                    612:        char **ret;
                    613:
                    614:        if (msg->body.search.iter == NULL)
                    615:                goto notfound;
                    616:
                    617:        LDAP_DEBUG("attr", msg->body.search.iter);
                    618:
                    619:        if (ber_get_eoc(msg->body.search.iter) == 0)
                    620:                goto notfound;
                    621:
                    622:        if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
                    623:            != 0)
                    624:                goto fail;
                    625:
                    626:        msg->body.search.iter = msg->body.search.iter->be_next;
                    627:
                    628:        if ((ret = aldap_get_stringset(a)) == NULL)
                    629:                goto fail;
                    630:
                    631:        (*outvalues) = ret;
                    632:        (*outkey) = utoa(key);
                    633:
                    634:        return (1);
                    635: fail:
                    636: notfound:
                    637:        (*outkey) = NULL;
                    638:        (*outvalues) = NULL;
                    639:        return (-1);
                    640: }
                    641:
                    642: int
                    643: aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues)
                    644: {
                    645:        struct ber_element *a, *b;
                    646:        char *descr = NULL;
                    647:        char **ret;
                    648:
                    649:        if (msg->body.search.attrs == NULL)
                    650:                goto fail;
                    651:
                    652:        LDAP_DEBUG("attr", msg->body.search.attrs);
                    653:
                    654:        for (a = msg->body.search.attrs;;) {
                    655:                if (a == NULL)
                    656:                        goto notfound;
                    657:                if (ber_get_eoc(a) == 0)
                    658:                        goto notfound;
                    659:                if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0)
                    660:                        goto fail;
                    661:                if (strcasecmp(descr, inkey) == 0)
                    662:                        goto attrfound;
                    663:                a = a->be_next;
                    664:        }
                    665:
                    666: attrfound:
                    667:        if ((ret = aldap_get_stringset(b)) == NULL)
                    668:                goto fail;
                    669:
                    670:        (*outvalues) = ret;
                    671:
                    672:        return (1);
                    673: fail:
                    674: notfound:
                    675:        (*outvalues) = NULL;
                    676:        return (-1);
                    677: }
                    678:
                    679: int
                    680: aldap_free_attr(char **values)
                    681: {
                    682:        int i;
                    683:
                    684:        if (values == NULL)
                    685:                return -1;
                    686:
                    687:        for (i = 0; values[i] != NULL; i++)
                    688:                free(values[i]);
                    689:
                    690:        free(values);
                    691:
                    692:        return (1);
                    693: }
                    694:
                    695: void
                    696: aldap_free_url(struct aldap_url *lu)
                    697: {
                    698:        free(lu->buffer);
                    699: }
                    700:
                    701: int
                    702: aldap_parse_url(const char *url, struct aldap_url *lu)
                    703: {
                    704:        char            *p, *forward, *forward2;
                    705:        const char      *errstr = NULL;
                    706:        int              i;
                    707:
                    708:        if ((lu->buffer = p = strdup(url)) == NULL)
                    709:                return (-1);
                    710:
                    711:        /* protocol */
                    712:        if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
                    713:                lu->protocol = LDAP;
                    714:                p += strlen(LDAP_URL);
                    715:        } else if (strncasecmp(LDAPS_URL, p, strlen(LDAPS_URL)) == 0) {
                    716:                lu->protocol = LDAPS;
                    717:                p += strlen(LDAPS_URL);
                    718:        } else if (strncasecmp(LDAPTLS_URL, p, strlen(LDAPTLS_URL)) == 0) {
                    719:                lu->protocol = LDAPTLS;
                    720:                p += strlen(LDAPTLS_URL);
                    721:        } else if (strncasecmp(LDAPI_URL, p, strlen(LDAPI_URL)) == 0) {
                    722:                lu->protocol = LDAPI;
                    723:                p += strlen(LDAPI_URL);
                    724:        } else
                    725:                lu->protocol = -1;
                    726:
                    727:        /* host and optional port */
                    728:        if ((forward = strchr(p, '/')) != NULL)
                    729:                *forward = '\0';
                    730:        /* find the optional port */
                    731:        if ((forward2 = strchr(p, ':')) != NULL) {
                    732:                *forward2 = '\0';
                    733:                /* if a port is given */
                    734:                if (*(forward2+1) != '\0') {
                    735: #define PORT_MAX UINT16_MAX
                    736:                        lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
                    737:                        if (errstr)
                    738:                                goto fail;
                    739:                }
                    740:        }
                    741:        /* fail if no host is given */
                    742:        if (strlen(p) == 0)
                    743:                goto fail;
                    744:        lu->host = p;
                    745:        if (forward == NULL)
                    746:                goto done;
                    747:        /* p is assigned either a pointer to a character or to '\0' */
                    748:        p = ++forward;
                    749:        if (strlen(p) == 0)
                    750:                goto done;
                    751:
                    752:        /* dn */
                    753:        if ((forward = strchr(p, '?')) != NULL)
                    754:                *forward = '\0';
                    755:        lu->dn = p;
                    756:        if (forward == NULL)
                    757:                goto done;
                    758:        /* p is assigned either a pointer to a character or to '\0' */
                    759:        p = ++forward;
                    760:        if (strlen(p) == 0)
                    761:                goto done;
                    762:
                    763:        /* attributes */
                    764:        if ((forward = strchr(p, '?')) != NULL)
                    765:                *forward = '\0';
                    766:        for (i = 0; i < MAXATTR; i++) {
                    767:                if ((forward2 = strchr(p, ',')) == NULL) {
                    768:                        if (strlen(p) == 0)
                    769:                                break;
                    770:                        lu->attributes[i] = p;
                    771:                        break;
                    772:                }
                    773:                *forward2 = '\0';
                    774:                lu->attributes[i] = p;
                    775:                p = ++forward2;
                    776:        }
                    777:        if (forward == NULL)
                    778:                goto done;
                    779:        /* p is assigned either a pointer to a character or to '\0' */
                    780:        p = ++forward;
                    781:        if (strlen(p) == 0)
                    782:                goto done;
                    783:
                    784:        /* scope */
                    785:        if ((forward = strchr(p, '?')) != NULL)
                    786:                *forward = '\0';
                    787:        if (strcmp(p, "base") == 0)
                    788:                lu->scope = LDAP_SCOPE_BASE;
                    789:        else if (strcmp(p, "one") == 0)
                    790:                lu->scope = LDAP_SCOPE_ONELEVEL;
                    791:        else if (strcmp(p, "sub") == 0)
                    792:                lu->scope = LDAP_SCOPE_SUBTREE;
                    793:        else
                    794:                goto fail;
                    795:        if (forward == NULL)
                    796:                goto done;
                    797:        p = ++forward;
                    798:        if (strlen(p) == 0)
                    799:                goto done;
                    800:
                    801:        /* filter */
                    802:        if (p)
                    803:                lu->filter = p;
                    804: done:
                    805:        return (1);
                    806: fail:
                    807:        free(lu->buffer);
                    808:        lu->buffer = NULL;
                    809:        return (-1);
                    810: }
                    811:
                    812: int
                    813: aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
                    814:     int timelimit, struct aldap_page_control *page)
                    815: {
                    816:        struct aldap_url *lu;
                    817:
                    818:        if ((lu = calloc(1, sizeof(*lu))) == NULL)
                    819:                return (-1);
                    820:
                    821:        if (aldap_parse_url(url, lu))
                    822:                goto fail;
                    823:
                    824:        if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
                    825:            typesonly, sizelimit, timelimit, page) == -1)
                    826:                goto fail;
                    827:
                    828:        aldap_free_url(lu);
                    829:        return (ldap->msgid);
                    830: fail:
                    831:        aldap_free_url(lu);
                    832:        return (-1);
                    833: }
                    834:
                    835: /*
                    836:  * internal functions
                    837:  */
                    838:
                    839: char **
                    840: aldap_get_stringset(struct ber_element *elm)
                    841: {
                    842:        struct ber_element *a;
                    843:        int i;
                    844:        char **ret;
                    845:        char *s;
                    846:
                    847:        if (elm->be_type != BER_TYPE_OCTETSTRING)
                    848:                return NULL;
                    849:
                    850:        for (a = elm, i = 1; i > 0 && a != NULL && a->be_type ==
                    851:            BER_TYPE_OCTETSTRING; a = a->be_next, i++)
                    852:                ;
                    853:        if (i == 1)
                    854:                return NULL;
                    855:
                    856:        if ((ret = calloc(i + 1, sizeof(char *))) == NULL)
                    857:                return NULL;
                    858:
                    859:        for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
                    860:            a = a->be_next, i++) {
                    861:
                    862:                ber_get_string(a, &s);
                    863:                ret[i] = utoa(s);
                    864:        }
                    865:        ret[i + 1] = NULL;
                    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);
                   1220:                fprintf(stderr, "encoding (%lu) type: ", root->be_encoding);
                   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:        }
                   1235:        fprintf(stderr, "(%lu) encoding %lu ",
                   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: }