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

1.10    ! martijn     1: /*     $OpenBSD: aldap.c,v 1.9 2019/10/24 12:39:26 tb 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);
1.9       tb         77:        ober_free(&al->ber);
1.1       reyk       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;
1.9       tb         93:        ober_set_application(&a->ber, aldap_application);
1.1       reyk       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:
1.9       tb        133:        len = ober_calc_len(root);
                    134:        error = ober_write_elements(&ldap->ber, root);
                    135:        ober_free_elements(root);
1.1       reyk      136:        if (error == -1)
                    137:                return -1;
                    138:
1.9       tb        139:        ober_get_writebuf(&ldap->ber, &ptr);
1.1       reyk      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:
1.9       tb        166:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      167:                goto fail;
                    168:
1.9       tb        169:        ber = ober_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)
1.9       tb        182:                ober_free_elements(root);
1.1       reyk      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:
1.9       tb        198:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      199:                goto fail;
                    200:
1.9       tb        201:        elm = ober_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)
1.9       tb        216:                ober_free_elements(root);
1.1       reyk      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:
1.9       tb        227:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      228:                goto fail;
1.9       tb        229:        elm = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1.1       reyk      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)
1.9       tb        243:                ober_free_elements(root);
1.1       reyk      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:
1.9       tb        258:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      259:                goto fail;
                    260:
1.9       tb        261:        ber = ober_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;
1.9       tb        269:        ber = ober_printf_elements(ber, "sEEddb", basedn, (long long)scope,
1.1       reyk      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:
1.9       tb        282:        if ((ber = ober_add_sequence(ber)) == NULL)
1.1       reyk      283:                goto fail;
                    284:        if (attrs != NULL)
                    285:                for (i = 0; attrs[i] != NULL; i++) {
1.9       tb        286:                        if ((ber = ober_add_string(ber, attrs[i])) == NULL)
1.1       reyk      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)
1.9       tb        304:                ober_free_elements(root);
1.1       reyk      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:
1.9       tb        319:        ber = ober_add_sequence(NULL);
1.1       reyk      320:
                    321:        if (page == NULL) {
1.9       tb        322:                if (ober_printf_elements(ber, "ds", 50, "") == NULL)
1.1       reyk      323:                        goto fail;
                    324:        } else {
1.9       tb        325:                if (ober_printf_elements(ber, "dx", 50, page->cookie,
1.1       reyk      326:                            page->cookie_len) == NULL)
                    327:                        goto fail;
                    328:        }
                    329:
1.9       tb        330:        if ((len = ober_write_elements(&c, ber)) < 1)
1.1       reyk      331:                goto fail;
1.9       tb        332:        if (ober_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
1.1       reyk      333:                                c.br_wbuf, (size_t)len) == NULL)
                    334:                goto fail;
                    335:
1.9       tb        336:        ober_free_elements(ber);
                    337:        ober_free(&c);
1.1       reyk      338:        return len;
                    339: fail:
                    340:        if (ber != NULL)
1.9       tb        341:                ober_free_elements(ber);
                    342:        ober_free(&c);
1.1       reyk      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) {
1.9       tb        380:                        ober_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf),
1.1       reyk      381:                            EVBUFFER_LENGTH(ldap->buf));
                    382:                        errno = 0;
1.9       tb        383:                        m->msg = ober_read_elements(&ldap->ber, NULL);
1.1       reyk      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:
1.9       tb        396:        if (ober_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
1.1       reyk      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:
1.9       tb        410:                if (ober_scanf_elements(m->protocol_op, "{EeSe",
1.8       martijn   411:                    &m->body.res.rescode, &m->dn, &m->body.res.diagmsg) != 0)
1.1       reyk      412:                        goto parsefail;
1.8       martijn   413:                if (m->body.res.rescode == LDAP_REFERRAL) {
                    414:                        a = m->body.res.diagmsg->be_next;
1.9       tb        415:                        if (ober_scanf_elements(a, "{e", &m->references) != 0)
1.1       reyk      416:                                goto parsefail;
1.8       martijn   417:                }
1.1       reyk      418:                if (m->msg->be_sub) {
                    419:                        for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
1.9       tb        420:                                ober_scanf_elements(ep, "t", &class, &type);
1.1       reyk      421:                                if (class == 2 && type == 0)
                    422:                                        m->page = aldap_parse_page_control(ep->be_sub->be_sub,
                    423:                                            ep->be_sub->be_sub->be_len);
                    424:                        }
                    425:                } else
                    426:                        m->page = NULL;
                    427:                break;
                    428:        case LDAP_RES_SEARCH_ENTRY:
1.9       tb        429:                if (ober_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
1.1       reyk      430:                    &m->body.search.attrs) != 0)
                    431:                        goto parsefail;
                    432:                break;
                    433:        case LDAP_RES_SEARCH_REFERENCE:
1.9       tb        434:                if (ober_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
1.1       reyk      435:                        goto parsefail;
                    436:                break;
                    437:        case LDAP_RES_EXTENDED:
1.9       tb        438:                if (ober_scanf_elements(m->protocol_op, "{E",
1.1       reyk      439:                    &m->body.res.rescode) != 0) {
                    440:                        goto parsefail;
                    441:                }
                    442:                break;
                    443:        }
                    444:
                    445:        return m;
                    446: parsefail:
                    447:        evbuffer_drain(ldap->buf, EVBUFFER_LENGTH(ldap->buf));
                    448:        ldap->err = ALDAP_ERR_PARSER_ERROR;
                    449:        aldap_freemsg(m);
                    450:        return NULL;
                    451: }
                    452:
                    453: struct aldap_page_control *
                    454: aldap_parse_page_control(struct ber_element *control, size_t len)
                    455: {
                    456:        char *oid, *s;
                    457:        char *encoded;
                    458:        struct ber b;
                    459:        struct ber_element *elm;
                    460:        struct aldap_page_control *page;
                    461:
                    462:        b.br_wbuf = NULL;
1.9       tb        463:        ober_scanf_elements(control, "ss", &oid, &encoded);
                    464:        ober_set_readbuf(&b, encoded, control->be_next->be_len);
                    465:        elm = ober_read_elements(&b, NULL);
1.1       reyk      466:
                    467:        if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
                    468:                if (elm != NULL)
1.9       tb        469:                        ober_free_elements(elm);
                    470:                ober_free(&b);
1.1       reyk      471:                return NULL;
                    472:        }
                    473:
1.9       tb        474:        ober_scanf_elements(elm->be_sub, "is", &page->size, &s);
1.1       reyk      475:        page->cookie_len = elm->be_sub->be_next->be_len;
                    476:
                    477:        if ((page->cookie = malloc(page->cookie_len)) == NULL) {
                    478:                if (elm != NULL)
1.9       tb        479:                        ober_free_elements(elm);
                    480:                ober_free(&b);
1.1       reyk      481:                free(page);
                    482:                return NULL;
                    483:        }
                    484:        memcpy(page->cookie, s, page->cookie_len);
                    485:
1.9       tb        486:        ober_free_elements(elm);
                    487:        ober_free(&b);
1.1       reyk      488:        return page;
                    489: }
                    490:
                    491: void
                    492: aldap_freepage(struct aldap_page_control *page)
                    493: {
                    494:        free(page->cookie);
                    495:        free(page);
                    496: }
                    497:
                    498: void
                    499: aldap_freemsg(struct aldap_message *msg)
                    500: {
                    501:        if (msg->msg)
1.9       tb        502:                ober_free_elements(msg->msg);
1.1       reyk      503:        free(msg);
                    504: }
                    505:
                    506: int
                    507: aldap_get_resultcode(struct aldap_message *msg)
                    508: {
                    509:        return msg->body.res.rescode;
                    510: }
                    511:
                    512: char *
                    513: aldap_get_dn(struct aldap_message *msg)
                    514: {
                    515:        char *dn;
                    516:
                    517:        if (msg->dn == NULL)
                    518:                return NULL;
                    519:
1.9       tb        520:        if (ober_get_string(msg->dn, &dn) == -1)
1.1       reyk      521:                return NULL;
                    522:
                    523:        return utoa(dn);
                    524: }
                    525:
1.6       martijn   526: struct aldap_stringset *
1.1       reyk      527: aldap_get_references(struct aldap_message *msg)
                    528: {
                    529:        if (msg->references == NULL)
                    530:                return NULL;
                    531:        return aldap_get_stringset(msg->references);
                    532: }
                    533:
                    534: void
                    535: aldap_free_references(char **values)
                    536: {
                    537:        int i;
                    538:
                    539:        if (values == NULL)
                    540:                return;
                    541:
                    542:        for (i = 0; values[i] != NULL; i++)
                    543:                free(values[i]);
                    544:
                    545:        free(values);
                    546: }
                    547:
                    548: char *
                    549: aldap_get_diagmsg(struct aldap_message *msg)
                    550: {
                    551:        char *s;
                    552:
                    553:        if (msg->body.res.diagmsg == NULL)
                    554:                return NULL;
                    555:
1.9       tb        556:        if (ober_get_string(msg->body.res.diagmsg, &s) == -1)
1.1       reyk      557:                return NULL;
                    558:
                    559:        return utoa(s);
                    560: }
                    561:
                    562: int
                    563: aldap_count_attrs(struct aldap_message *msg)
                    564: {
                    565:        int i;
                    566:        struct ber_element *a;
                    567:
                    568:        if (msg->body.search.attrs == NULL)
                    569:                return (-1);
                    570:
                    571:        for (i = 0, a = msg->body.search.attrs;
1.9       tb        572:            a != NULL && ober_get_eoc(a) != 0;
1.1       reyk      573:            i++, a = a->be_next)
                    574:                ;
                    575:
                    576:        return i;
                    577: }
                    578:
                    579: int
1.6       martijn   580: aldap_first_attr(struct aldap_message *msg, char **outkey,
                    581:     struct aldap_stringset **outvalues)
1.1       reyk      582: {
1.10    ! martijn   583:        struct ber_element *b;
1.1       reyk      584:        char *key;
1.6       martijn   585:        struct aldap_stringset *ret;
1.1       reyk      586:
                    587:        if (msg->body.search.attrs == NULL)
                    588:                goto fail;
                    589:
1.10    ! martijn   590:        if (ober_scanf_elements(msg->body.search.attrs, "{s(e)}",
        !           591:            &key, &b) != 0)
1.1       reyk      592:                goto fail;
                    593:
                    594:        msg->body.search.iter = msg->body.search.attrs->be_next;
                    595:
                    596:        if ((ret = aldap_get_stringset(b)) == NULL)
                    597:                goto fail;
                    598:
                    599:        (*outvalues) = ret;
                    600:        (*outkey) = utoa(key);
                    601:
                    602:        return (1);
                    603: fail:
                    604:        (*outkey) = NULL;
                    605:        (*outvalues) = NULL;
                    606:        return (-1);
                    607: }
                    608:
                    609: int
1.6       martijn   610: aldap_next_attr(struct aldap_message *msg, char **outkey,
                    611:     struct aldap_stringset **outvalues)
1.1       reyk      612: {
1.10    ! martijn   613:        struct ber_element *a;
1.1       reyk      614:        char *key;
1.6       martijn   615:        struct aldap_stringset *ret;
1.1       reyk      616:
                    617:        if (msg->body.search.iter == NULL)
                    618:                goto notfound;
                    619:
                    620:        LDAP_DEBUG("attr", msg->body.search.iter);
                    621:
1.9       tb        622:        if (ober_get_eoc(msg->body.search.iter) == 0)
1.1       reyk      623:                goto notfound;
                    624:
1.10    ! martijn   625:        if (ober_scanf_elements(msg->body.search.iter, "{s(e)}", &key, &a) != 0)
1.1       reyk      626:                goto fail;
                    627:
                    628:        msg->body.search.iter = msg->body.search.iter->be_next;
                    629:
                    630:        if ((ret = aldap_get_stringset(a)) == NULL)
                    631:                goto fail;
                    632:
                    633:        (*outvalues) = ret;
                    634:        (*outkey) = utoa(key);
                    635:
                    636:        return (1);
                    637: fail:
                    638: notfound:
                    639:        (*outkey) = NULL;
                    640:        (*outvalues) = NULL;
                    641:        return (-1);
                    642: }
                    643:
                    644: int
1.6       martijn   645: aldap_match_attr(struct aldap_message *msg, char *inkey,
                    646:     struct aldap_stringset **outvalues)
1.1       reyk      647: {
                    648:        struct ber_element *a, *b;
                    649:        char *descr = NULL;
1.6       martijn   650:        struct aldap_stringset *ret;
1.1       reyk      651:
                    652:        if (msg->body.search.attrs == NULL)
                    653:                goto fail;
                    654:
                    655:        LDAP_DEBUG("attr", msg->body.search.attrs);
                    656:
                    657:        for (a = msg->body.search.attrs;;) {
                    658:                if (a == NULL)
                    659:                        goto notfound;
1.9       tb        660:                if (ober_get_eoc(a) == 0)
1.1       reyk      661:                        goto notfound;
1.9       tb        662:                if (ober_scanf_elements(a, "{s(e", &descr, &b) != 0)
1.1       reyk      663:                        goto fail;
                    664:                if (strcasecmp(descr, inkey) == 0)
                    665:                        goto attrfound;
                    666:                a = a->be_next;
                    667:        }
                    668:
                    669: attrfound:
                    670:        if ((ret = aldap_get_stringset(b)) == NULL)
                    671:                goto fail;
                    672:
                    673:        (*outvalues) = ret;
                    674:
                    675:        return (1);
                    676: fail:
                    677: notfound:
                    678:        (*outvalues) = NULL;
                    679:        return (-1);
                    680: }
                    681:
                    682: int
1.6       martijn   683: aldap_free_attr(struct aldap_stringset *values)
1.1       reyk      684: {
                    685:        if (values == NULL)
                    686:                return -1;
                    687:
1.6       martijn   688:        free(values->str);
1.1       reyk      689:        free(values);
                    690:
                    691:        return (1);
                    692: }
                    693:
                    694: void
                    695: aldap_free_url(struct aldap_url *lu)
                    696: {
                    697:        free(lu->buffer);
                    698: }
                    699:
                    700: int
                    701: aldap_parse_url(const char *url, struct aldap_url *lu)
                    702: {
                    703:        char            *p, *forward, *forward2;
                    704:        const char      *errstr = NULL;
                    705:        int              i;
                    706:
                    707:        if ((lu->buffer = p = strdup(url)) == NULL)
                    708:                return (-1);
                    709:
                    710:        /* protocol */
                    711:        if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
                    712:                lu->protocol = LDAP;
                    713:                p += strlen(LDAP_URL);
                    714:        } else if (strncasecmp(LDAPS_URL, p, strlen(LDAPS_URL)) == 0) {
                    715:                lu->protocol = LDAPS;
                    716:                p += strlen(LDAPS_URL);
                    717:        } else if (strncasecmp(LDAPTLS_URL, p, strlen(LDAPTLS_URL)) == 0) {
                    718:                lu->protocol = LDAPTLS;
                    719:                p += strlen(LDAPTLS_URL);
                    720:        } else if (strncasecmp(LDAPI_URL, p, strlen(LDAPI_URL)) == 0) {
                    721:                lu->protocol = LDAPI;
                    722:                p += strlen(LDAPI_URL);
                    723:        } else
                    724:                lu->protocol = -1;
                    725:
                    726:        /* host and optional port */
                    727:        if ((forward = strchr(p, '/')) != NULL)
                    728:                *forward = '\0';
                    729:        /* find the optional port */
                    730:        if ((forward2 = strchr(p, ':')) != NULL) {
                    731:                *forward2 = '\0';
                    732:                /* if a port is given */
                    733:                if (*(forward2+1) != '\0') {
                    734: #define PORT_MAX UINT16_MAX
                    735:                        lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
                    736:                        if (errstr)
                    737:                                goto fail;
                    738:                }
                    739:        }
                    740:        /* fail if no host is given */
                    741:        if (strlen(p) == 0)
                    742:                goto fail;
                    743:        lu->host = p;
                    744:        if (forward == NULL)
                    745:                goto done;
                    746:        /* p is assigned either a pointer to a character or to '\0' */
                    747:        p = ++forward;
                    748:        if (strlen(p) == 0)
                    749:                goto done;
                    750:
                    751:        /* dn */
                    752:        if ((forward = strchr(p, '?')) != NULL)
                    753:                *forward = '\0';
                    754:        lu->dn = p;
                    755:        if (forward == NULL)
                    756:                goto done;
                    757:        /* p is assigned either a pointer to a character or to '\0' */
                    758:        p = ++forward;
                    759:        if (strlen(p) == 0)
                    760:                goto done;
                    761:
                    762:        /* attributes */
                    763:        if ((forward = strchr(p, '?')) != NULL)
                    764:                *forward = '\0';
                    765:        for (i = 0; i < MAXATTR; i++) {
                    766:                if ((forward2 = strchr(p, ',')) == NULL) {
                    767:                        if (strlen(p) == 0)
                    768:                                break;
                    769:                        lu->attributes[i] = p;
                    770:                        break;
                    771:                }
                    772:                *forward2 = '\0';
                    773:                lu->attributes[i] = p;
                    774:                p = ++forward2;
                    775:        }
                    776:        if (forward == NULL)
                    777:                goto done;
                    778:        /* p is assigned either a pointer to a character or to '\0' */
                    779:        p = ++forward;
                    780:        if (strlen(p) == 0)
                    781:                goto done;
                    782:
                    783:        /* scope */
                    784:        if ((forward = strchr(p, '?')) != NULL)
                    785:                *forward = '\0';
                    786:        if (strcmp(p, "base") == 0)
                    787:                lu->scope = LDAP_SCOPE_BASE;
                    788:        else if (strcmp(p, "one") == 0)
                    789:                lu->scope = LDAP_SCOPE_ONELEVEL;
                    790:        else if (strcmp(p, "sub") == 0)
                    791:                lu->scope = LDAP_SCOPE_SUBTREE;
                    792:        else
                    793:                goto fail;
                    794:        if (forward == NULL)
                    795:                goto done;
                    796:        p = ++forward;
                    797:        if (strlen(p) == 0)
                    798:                goto done;
                    799:
                    800:        /* filter */
                    801:        if (p)
                    802:                lu->filter = p;
                    803: done:
                    804:        return (1);
                    805: fail:
                    806:        free(lu->buffer);
                    807:        lu->buffer = NULL;
                    808:        return (-1);
                    809: }
                    810:
                    811: int
                    812: aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
                    813:     int timelimit, struct aldap_page_control *page)
                    814: {
                    815:        struct aldap_url *lu;
                    816:
                    817:        if ((lu = calloc(1, sizeof(*lu))) == NULL)
                    818:                return (-1);
                    819:
                    820:        if (aldap_parse_url(url, lu))
                    821:                goto fail;
                    822:
                    823:        if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
                    824:            typesonly, sizelimit, timelimit, page) == -1)
                    825:                goto fail;
                    826:
                    827:        aldap_free_url(lu);
                    828:        return (ldap->msgid);
                    829: fail:
                    830:        aldap_free_url(lu);
                    831:        return (-1);
                    832: }
                    833:
                    834: /*
                    835:  * internal functions
                    836:  */
                    837:
1.6       martijn   838: struct aldap_stringset *
1.1       reyk      839: aldap_get_stringset(struct ber_element *elm)
                    840: {
                    841:        struct ber_element *a;
                    842:        int i;
1.6       martijn   843:        struct aldap_stringset *ret;
1.1       reyk      844:
                    845:        if (elm->be_type != BER_TYPE_OCTETSTRING)
                    846:                return NULL;
                    847:
1.6       martijn   848:        if ((ret = malloc(sizeof(*ret))) == NULL)
                    849:                return NULL;
                    850:        for (a = elm, ret->len = 0; a != NULL && a->be_type ==
                    851:            BER_TYPE_OCTETSTRING; a = a->be_next, ret->len++)
1.1       reyk      852:                ;
1.6       martijn   853:        if (ret->len == 0) {
                    854:                free(ret);
1.1       reyk      855:                return NULL;
1.6       martijn   856:        }
1.1       reyk      857:
1.6       martijn   858:        if ((ret->str = reallocarray(NULL, ret->len,
                    859:            sizeof(*(ret->str)))) == NULL) {
                    860:                free(ret);
1.1       reyk      861:                return NULL;
1.6       martijn   862:        }
1.1       reyk      863:
                    864:        for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
1.6       martijn   865:            a = a->be_next, i++)
1.9       tb        866:                (void) ober_get_ostring(a, &(ret->str[i]));
1.1       reyk      867:
                    868:        return ret;
                    869: }
                    870:
                    871: /*
                    872:  * Base case for ldap_do_parse_search_filter
                    873:  *
                    874:  * returns:
                    875:  *     struct ber_element *, ber_element tree
                    876:  *     NULL, parse failed
                    877:  */
                    878: static struct ber_element *
                    879: ldap_parse_search_filter(struct ber_element *ber, char *filter)
                    880: {
                    881:        struct ber_element *elm;
                    882:        char *cp;
                    883:
                    884:        cp = filter;
                    885:
                    886:        if (cp == NULL || *cp == '\0') {
                    887:                errno = EINVAL;
                    888:                return (NULL);
                    889:        }
                    890:
                    891:        if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
                    892:                return (NULL);
                    893:
                    894:        if (*cp != '\0') {
1.9       tb        895:                ober_free_elements(elm);
                    896:                ober_link_elements(ber, NULL);
1.1       reyk      897:                errno = EINVAL;
                    898:                return (NULL);
                    899:        }
                    900:
                    901:        return (elm);
                    902: }
                    903:
                    904: /*
                    905:  * Translate RFC4515 search filter string into ber_element tree
                    906:  *
                    907:  * returns:
                    908:  *     struct ber_element *, ber_element tree
                    909:  *     NULL, parse failed
                    910:  *
                    911:  * notes:
                    912:  *     when cp is passed to a recursive invocation, it is updated
                    913:  *         to point one character beyond the filter that was passed
                    914:  *         i.e., cp jumps to "(filter)" upon return
                    915:  *                                    ^
                    916:  *     goto's used to discriminate error-handling based on error type
                    917:  *     doesn't handle extended filters (yet)
                    918:  *
                    919:  */
                    920: static struct ber_element *
                    921: ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
                    922: {
                    923:        struct ber_element *elm, *root = NULL;
                    924:        char *attr_desc, *attr_val, *parsed_val, *cp;
                    925:        size_t len;
                    926:        unsigned long type;
                    927:
                    928:        root = NULL;
                    929:
                    930:        /* cpp should pass in pointer to opening parenthesis of "(filter)" */
                    931:        cp = *cpp;
                    932:        if (*cp != '(')
                    933:                goto syntaxfail;
                    934:
                    935:        switch (*++cp) {
                    936:        case '&':               /* AND */
                    937:        case '|':               /* OR */
                    938:                if (*cp == '&')
                    939:                        type = LDAP_FILT_AND;
                    940:                else
                    941:                        type = LDAP_FILT_OR;
                    942:
1.9       tb        943:                if ((elm = ober_add_set(prev)) == NULL)
1.1       reyk      944:                        goto callfail;
                    945:                root = elm;
1.9       tb        946:                ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1       reyk      947:
                    948:                if (*++cp != '(')               /* opening `(` of filter */
                    949:                        goto syntaxfail;
                    950:
                    951:                while (*cp == '(') {
                    952:                        if ((elm =
                    953:                            ldap_do_parse_search_filter(elm, &cp)) == NULL)
                    954:                                goto bad;
                    955:                }
                    956:
                    957:                if (*cp != ')')                 /* trailing `)` of filter */
                    958:                        goto syntaxfail;
                    959:                break;
                    960:
                    961:        case '!':               /* NOT */
1.9       tb        962:                if ((root = ober_add_sequence(prev)) == NULL)
1.1       reyk      963:                        goto callfail;
1.9       tb        964:                ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
1.1       reyk      965:
                    966:                cp++;                           /* now points to sub-filter */
                    967:                if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
                    968:                        goto bad;
                    969:
                    970:                if (*cp != ')')                 /* trailing `)` of filter */
                    971:                        goto syntaxfail;
                    972:                break;
                    973:
                    974:        default:        /* SIMPLE || PRESENCE */
                    975:                attr_desc = cp;
                    976:
                    977:                len = strcspn(cp, "()<>~=");
                    978:                cp += len;
                    979:                switch (*cp) {
                    980:                case '~':
                    981:                        type = LDAP_FILT_APPR;
                    982:                        cp++;
                    983:                        break;
                    984:                case '<':
                    985:                        type = LDAP_FILT_LE;
                    986:                        cp++;
                    987:                        break;
                    988:                case '>':
                    989:                        type = LDAP_FILT_GE;
                    990:                        cp++;
                    991:                        break;
                    992:                case '=':
                    993:                        type = LDAP_FILT_EQ;    /* assume EQ until disproven */
                    994:                        break;
                    995:                case '(':
                    996:                case ')':
                    997:                default:
                    998:                        goto syntaxfail;
                    999:                }
                   1000:                attr_val = ++cp;
                   1001:
                   1002:                /* presence filter */
                   1003:                if (strncmp(attr_val, "*)", 2) == 0) {
                   1004:                        cp++;                   /* point to trailing `)` */
                   1005:                        if ((root =
1.9       tb       1006:                            ober_add_nstring(prev, attr_desc, len)) == NULL)
1.1       reyk     1007:                                goto bad;
                   1008:
1.9       tb       1009:                        ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
1.1       reyk     1010:                        break;
                   1011:                }
                   1012:
1.9       tb       1013:                if ((root = ober_add_sequence(prev)) == NULL)
1.1       reyk     1014:                        goto callfail;
1.9       tb       1015:                ober_set_header(root, BER_CLASS_CONTEXT, type);
1.1       reyk     1016:
1.9       tb       1017:                if ((elm = ober_add_nstring(root, attr_desc, len)) == NULL)
1.1       reyk     1018:                        goto callfail;
                   1019:
                   1020:                len = strcspn(attr_val, "*)");
                   1021:                if (len == 0 && *cp != '*')
                   1022:                        goto syntaxfail;
                   1023:                cp += len;
                   1024:                if (*cp == '\0')
                   1025:                        goto syntaxfail;
                   1026:
                   1027:                if (*cp == '*') {       /* substring filter */
                   1028:                        int initial;
                   1029:
                   1030:                        cp = attr_val;
                   1031:
1.9       tb       1032:                        ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
1.1       reyk     1033:
1.9       tb       1034:                        if ((elm = ober_add_sequence(elm)) == NULL)
1.1       reyk     1035:                                goto callfail;
                   1036:
                   1037:                        for (initial = 1;; cp++, initial = 0) {
                   1038:                                attr_val = cp;
                   1039:
                   1040:                                len = strcspn(attr_val, "*)");
                   1041:                                if (len == 0) {
                   1042:                                        if (*cp == ')')
                   1043:                                                break;
                   1044:                                        else
                   1045:                                                continue;
                   1046:                                }
                   1047:                                cp += len;
                   1048:                                if (*cp == '\0')
                   1049:                                        goto syntaxfail;
                   1050:
                   1051:                                if (initial)
                   1052:                                        type = LDAP_FILT_SUBS_INIT;
                   1053:                                else if (*cp == ')')
                   1054:                                        type = LDAP_FILT_SUBS_FIN;
                   1055:                                else
                   1056:                                        type = LDAP_FILT_SUBS_ANY;
                   1057:
                   1058:                                if ((parsed_val = parseval(attr_val, len)) ==
                   1059:                                    NULL)
                   1060:                                        goto callfail;
1.9       tb       1061:                                elm = ober_add_nstring(elm, parsed_val,
1.1       reyk     1062:                                    strlen(parsed_val));
                   1063:                                free(parsed_val);
                   1064:                                if (elm == NULL)
                   1065:                                        goto callfail;
1.9       tb       1066:                                ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1       reyk     1067:                                if (type == LDAP_FILT_SUBS_FIN)
                   1068:                                        break;
                   1069:                        }
                   1070:                        break;
                   1071:                }
                   1072:
                   1073:                if ((parsed_val = parseval(attr_val, len)) == NULL)
                   1074:                        goto callfail;
1.9       tb       1075:                elm = ober_add_nstring(elm, parsed_val, strlen(parsed_val));
1.1       reyk     1076:                free(parsed_val);
                   1077:                if (elm == NULL)
                   1078:                        goto callfail;
                   1079:                break;
                   1080:        }
                   1081:
                   1082:        cp++;           /* now points one char beyond the trailing `)` */
                   1083:
                   1084:        *cpp = cp;
                   1085:        return (root);
                   1086:
                   1087: syntaxfail:            /* XXX -- error reporting */
                   1088: callfail:
                   1089: bad:
                   1090:        if (root != NULL)
1.9       tb       1091:                ober_free_elements(root);
                   1092:        ober_link_elements(prev, NULL);
1.1       reyk     1093:        return (NULL);
                   1094: }
                   1095:
                   1096: #ifdef DEBUG
                   1097: /*
                   1098:  * Display a list of ber elements.
                   1099:  *
                   1100:  */
                   1101: void
                   1102: ldap_debug_elements(struct ber_element *root)
                   1103: {
                   1104:        static int       indent = 0;
                   1105:        long long        v;
                   1106:        int              d;
                   1107:        char            *buf;
                   1108:        size_t           len;
                   1109:        u_int            i;
                   1110:        int              constructed;
                   1111:        struct ber_oid   o;
                   1112:
                   1113:        /* calculate lengths */
1.9       tb       1114:        ober_calc_len(root);
1.1       reyk     1115:
                   1116:        switch (root->be_encoding) {
                   1117:        case BER_TYPE_SEQUENCE:
                   1118:        case BER_TYPE_SET:
                   1119:                constructed = root->be_encoding;
                   1120:                break;
                   1121:        default:
                   1122:                constructed = 0;
                   1123:                break;
                   1124:        }
                   1125:
                   1126:        fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
                   1127:        switch (root->be_class) {
                   1128:        case BER_CLASS_UNIVERSAL:
                   1129:                fprintf(stderr, "class: universal(%u) type: ", root->be_class);
                   1130:                switch (root->be_type) {
                   1131:                case BER_TYPE_EOC:
                   1132:                        fprintf(stderr, "end-of-content");
                   1133:                        break;
                   1134:                case BER_TYPE_BOOLEAN:
                   1135:                        fprintf(stderr, "boolean");
                   1136:                        break;
                   1137:                case BER_TYPE_INTEGER:
                   1138:                        fprintf(stderr, "integer");
                   1139:                        break;
                   1140:                case BER_TYPE_BITSTRING:
                   1141:                        fprintf(stderr, "bit-string");
                   1142:                        break;
                   1143:                case BER_TYPE_OCTETSTRING:
                   1144:                        fprintf(stderr, "octet-string");
                   1145:                        break;
                   1146:                case BER_TYPE_NULL:
                   1147:                        fprintf(stderr, "null");
                   1148:                        break;
                   1149:                case BER_TYPE_OBJECT:
                   1150:                        fprintf(stderr, "object");
                   1151:                        break;
                   1152:                case BER_TYPE_ENUMERATED:
                   1153:                        fprintf(stderr, "enumerated");
                   1154:                        break;
                   1155:                case BER_TYPE_SEQUENCE:
                   1156:                        fprintf(stderr, "sequence");
                   1157:                        break;
                   1158:                case BER_TYPE_SET:
                   1159:                        fprintf(stderr, "set");
                   1160:                        break;
                   1161:                }
                   1162:                break;
                   1163:        case BER_CLASS_APPLICATION:
                   1164:                fprintf(stderr, "class: application(%u) type: ",
                   1165:                    root->be_class);
                   1166:                switch (root->be_type) {
                   1167:                case LDAP_REQ_BIND:
                   1168:                        fprintf(stderr, "bind");
                   1169:                        break;
                   1170:                case LDAP_RES_BIND:
                   1171:                        fprintf(stderr, "bind");
                   1172:                        break;
                   1173:                case LDAP_REQ_UNBIND_30:
                   1174:                        break;
                   1175:                case LDAP_REQ_SEARCH:
                   1176:                        fprintf(stderr, "search");
                   1177:                        break;
                   1178:                case LDAP_RES_SEARCH_ENTRY:
                   1179:                        fprintf(stderr, "search_entry");
                   1180:                        break;
                   1181:                case LDAP_RES_SEARCH_RESULT:
                   1182:                        fprintf(stderr, "search_result");
                   1183:                        break;
                   1184:                case LDAP_REQ_MODIFY:
                   1185:                        fprintf(stderr, "modify");
                   1186:                        break;
                   1187:                case LDAP_RES_MODIFY:
                   1188:                        fprintf(stderr, "modify");
                   1189:                        break;
                   1190:                case LDAP_REQ_ADD:
                   1191:                        fprintf(stderr, "add");
                   1192:                        break;
                   1193:                case LDAP_RES_ADD:
                   1194:                        fprintf(stderr, "add");
                   1195:                        break;
                   1196:                case LDAP_REQ_DELETE_30:
                   1197:                        fprintf(stderr, "delete");
                   1198:                        break;
                   1199:                case LDAP_RES_DELETE:
                   1200:                        fprintf(stderr, "delete");
                   1201:                        break;
                   1202:                case LDAP_REQ_MODRDN:
                   1203:                        fprintf(stderr, "modrdn");
                   1204:                        break;
                   1205:                case LDAP_RES_MODRDN:
                   1206:                        fprintf(stderr, "modrdn");
                   1207:                        break;
                   1208:                case LDAP_REQ_COMPARE:
                   1209:                        fprintf(stderr, "compare");
                   1210:                        break;
                   1211:                case LDAP_RES_COMPARE:
                   1212:                        fprintf(stderr, "compare");
                   1213:                        break;
                   1214:                case LDAP_REQ_ABANDON_30:
                   1215:                        fprintf(stderr, "abandon");
                   1216:                        break;
                   1217:                }
                   1218:                break;
                   1219:        case BER_CLASS_PRIVATE:
                   1220:                fprintf(stderr, "class: private(%u) type: ", root->be_class);
1.4       rob      1221:                fprintf(stderr, "encoding (%u) type: ", root->be_encoding);
1.1       reyk     1222:                break;
                   1223:        case BER_CLASS_CONTEXT:
                   1224:                /* XXX: this is not correct */
                   1225:                fprintf(stderr, "class: context(%u) type: ", root->be_class);
                   1226:                switch(root->be_type) {
                   1227:                case LDAP_AUTH_SIMPLE:
                   1228:                        fprintf(stderr, "auth simple");
                   1229:                        break;
                   1230:                }
                   1231:                break;
                   1232:        default:
                   1233:                fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
                   1234:                break;
                   1235:        }
1.4       rob      1236:        fprintf(stderr, "(%u) encoding %u ",
1.1       reyk     1237:            root->be_type, root->be_encoding);
                   1238:
                   1239:        if (constructed)
                   1240:                root->be_encoding = constructed;
                   1241:
                   1242:        switch (root->be_encoding) {
                   1243:        case BER_TYPE_BOOLEAN:
1.9       tb       1244:                if (ober_get_boolean(root, &d) == -1) {
1.1       reyk     1245:                        fprintf(stderr, "<INVALID>\n");
                   1246:                        break;
                   1247:                }
                   1248:                fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
                   1249:                break;
                   1250:        case BER_TYPE_INTEGER:
1.9       tb       1251:                if (ober_get_integer(root, &v) == -1) {
1.1       reyk     1252:                        fprintf(stderr, "<INVALID>\n");
                   1253:                        break;
                   1254:                }
                   1255:                fprintf(stderr, "value %lld\n", v);
                   1256:                break;
                   1257:        case BER_TYPE_ENUMERATED:
1.9       tb       1258:                if (ober_get_enumerated(root, &v) == -1) {
1.1       reyk     1259:                        fprintf(stderr, "<INVALID>\n");
                   1260:                        break;
                   1261:                }
                   1262:                fprintf(stderr, "value %lld\n", v);
                   1263:                break;
                   1264:        case BER_TYPE_BITSTRING:
1.9       tb       1265:                if (ober_get_bitstring(root, (void *)&buf, &len) == -1) {
1.1       reyk     1266:                        fprintf(stderr, "<INVALID>\n");
                   1267:                        break;
                   1268:                }
                   1269:                fprintf(stderr, "hexdump ");
                   1270:                for (i = 0; i < len; i++)
                   1271:                        fprintf(stderr, "%02x", buf[i]);
                   1272:                fprintf(stderr, "\n");
                   1273:                break;
                   1274:        case BER_TYPE_OBJECT:
1.9       tb       1275:                if (ober_get_oid(root, &o) == -1) {
1.1       reyk     1276:                        fprintf(stderr, "<INVALID>\n");
                   1277:                        break;
                   1278:                }
                   1279:                fprintf(stderr, "\n");
                   1280:                break;
                   1281:        case BER_TYPE_OCTETSTRING:
1.9       tb       1282:                if (ober_get_nstring(root, (void *)&buf, &len) == -1) {
1.1       reyk     1283:                        fprintf(stderr, "<INVALID>\n");
                   1284:                        break;
                   1285:                }
1.2       reyk     1286:                fprintf(stderr, "string \"%.*s\"\n",  (int)len, buf);
1.1       reyk     1287:                break;
                   1288:        case BER_TYPE_NULL:     /* no payload */
                   1289:        case BER_TYPE_EOC:
                   1290:        case BER_TYPE_SEQUENCE:
                   1291:        case BER_TYPE_SET:
                   1292:        default:
                   1293:                fprintf(stderr, "\n");
                   1294:                break;
                   1295:        }
                   1296:
                   1297:        if (constructed && root->be_sub) {
                   1298:                indent += 2;
                   1299:                ldap_debug_elements(root->be_sub);
                   1300:                indent -= 2;
                   1301:        }
                   1302:        if (root->be_next)
                   1303:                ldap_debug_elements(root->be_next);
                   1304: }
                   1305: #endif
                   1306:
                   1307: /*
                   1308:  * Strip UTF-8 down to ASCII without validation.
                   1309:  * notes:
                   1310:  *     non-ASCII characters are displayed as '?'
                   1311:  *     the argument u should be a NULL terminated sequence of UTF-8 bytes.
                   1312:  */
                   1313: char *
                   1314: utoa(char *u)
                   1315: {
                   1316:        int      len, i, j;
                   1317:        char    *str;
                   1318:
                   1319:        /* calculate the length to allocate */
                   1320:        for (len = 0, i = 0; u[i] != '\0'; i++)
                   1321:                if (!isu8cont(u[i]))
                   1322:                        len++;
                   1323:
                   1324:        if ((str = calloc(len + 1, sizeof(char))) == NULL)
                   1325:                return NULL;
                   1326:
                   1327:        /* copy the ASCII characters to the newly allocated string */
                   1328:        for (i = 0, j = 0; u[i] != '\0'; i++)
                   1329:                if (!isu8cont(u[i]))
                   1330:                        str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?';
                   1331:
                   1332:        return str;
                   1333: }
                   1334:
                   1335: static int
                   1336: isu8cont(unsigned char c)
                   1337: {
                   1338:        return (c & (0x80 | 0x40)) == 0x80;
                   1339: }
                   1340:
                   1341: /*
                   1342:  * Parse a LDAP value
                   1343:  * notes:
                   1344:  *     the argument p should be a NUL-terminated sequence of ASCII bytes
                   1345:  */
                   1346: char *
                   1347: parseval(char *p, size_t len)
                   1348: {
                   1349:        char     hex[3];
                   1350:        char    *buffer;
                   1351:        size_t   i, j;
                   1352:
                   1353:        if ((buffer = calloc(1, len + 1)) == NULL)
                   1354:                return NULL;
                   1355:
                   1356:        for (i = j = 0; j < len; i++) {
                   1357:                if (p[j] == '\\') {
                   1358:                        strlcpy(hex, p + j + 1, sizeof(hex));
                   1359:                        buffer[i] = (char)strtoumax(hex, NULL, 16);
                   1360:                        j += 3;
                   1361:                } else {
                   1362:                        buffer[i] = p[j];
                   1363:                        j++;
                   1364:                }
                   1365:        }
                   1366:
                   1367:        return buffer;
                   1368: }
                   1369:
                   1370: int
                   1371: aldap_get_errno(struct aldap *a, const char **estr)
                   1372: {
                   1373:        switch (a->err) {
                   1374:        case ALDAP_ERR_SUCCESS:
                   1375:                *estr = "success";
                   1376:                break;
                   1377:        case ALDAP_ERR_PARSER_ERROR:
                   1378:                *estr = "parser failed";
                   1379:                break;
                   1380:        case ALDAP_ERR_INVALID_FILTER:
                   1381:                *estr = "invalid filter";
                   1382:                break;
                   1383:        case ALDAP_ERR_OPERATION_FAILED:
                   1384:                *estr = "operation failed";
                   1385:                break;
                   1386:        case ALDAP_ERR_TLS_ERROR:
                   1387:                *estr = tls_error(a->tls);
                   1388:                break;
                   1389:        default:
                   1390:                *estr = "unknown";
                   1391:                break;
                   1392:        }
                   1393:        return (a->err);
                   1394: }