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

1.8.2.1 ! tb          1: /*     $OpenBSD: aldap.c,v 1.8 2019/09/10 14:35:32 martijn Exp $ */
1.1       reyk        2:
                      3: /*
                      4:  * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
                      5:  * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: #include <arpa/inet.h>
                     21: #include <ctype.h>
                     22: #include <errno.h>
                     23: #include <inttypes.h>
                     24: #include <string.h>
                     25: #include <stdlib.h>
                     26: #include <unistd.h>
                     27:
                     28: #include <event.h>
                     29:
                     30: #include "aldap.h"
                     31:
                     32: #if 0
                     33: #define DEBUG
                     34: #endif
                     35: #define VERSION 3
                     36:
                     37: static struct ber_element      *ldap_parse_search_filter(struct ber_element *,
                     38:                                    char *);
                     39: static struct ber_element      *ldap_do_parse_search_filter(
                     40:                                    struct ber_element *, char **);
1.6       martijn    41: struct aldap_stringset         *aldap_get_stringset(struct ber_element *);
1.1       reyk       42: char                           *utoa(char *);
                     43: static int                      isu8cont(unsigned char);
                     44: char                           *parseval(char *, size_t);
                     45: int                            aldap_create_page_control(struct ber_element *,
                     46:                                    int, struct aldap_page_control *);
                     47: int                            aldap_send(struct aldap *,
                     48:                                    struct ber_element *);
1.3       claudio    49: unsigned int                   aldap_application(struct ber_element *);
1.1       reyk       50:
                     51: #ifdef DEBUG
                     52: void                    ldap_debug_elements(struct ber_element *);
                     53: #endif
                     54:
                     55: #ifdef DEBUG
                     56: #define DPRINTF(x...)  printf(x)
                     57: #define LDAP_DEBUG(x, y)       do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0)
                     58: #else
                     59: #define DPRINTF(x...)  do { } while (0)
                     60: #define LDAP_DEBUG(x, y)       do { } while (0)
                     61: #endif
                     62:
1.3       claudio    63: unsigned int
1.1       reyk       64: aldap_application(struct ber_element *elm)
                     65: {
                     66:        return BER_TYPE_OCTETSTRING;
                     67: }
                     68:
                     69: int
                     70: aldap_close(struct aldap *al)
                     71: {
                     72:        if (al->tls != NULL) {
                     73:                tls_close(al->tls);
                     74:                tls_free(al->tls);
                     75:        }
                     76:        close(al->fd);
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        166:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      167:                goto fail;
                    168:
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        198:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      199:                goto fail;
                    200:
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        227:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      228:                goto fail;
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        258:        if ((root = ober_add_sequence(NULL)) == NULL)
1.1       reyk      259:                goto fail;
                    260:
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        319:        ber = ober_add_sequence(NULL);
1.1       reyk      320:
                    321:        if (page == NULL) {
1.8.2.1 ! tb        322:                if (ober_printf_elements(ber, "ds", 50, "") == NULL)
1.1       reyk      323:                        goto fail;
                    324:        } else {
1.8.2.1 ! 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.8.2.1 ! tb        330:        if ((len = ober_write_elements(&c, ber)) < 1)
1.1       reyk      331:                goto fail;
1.8.2.1 ! 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.8.2.1 ! tb        336:        ober_free_elements(ber);
        !           337:        ober_free(&c);
1.1       reyk      338:        return len;
                    339: fail:
                    340:        if (ber != NULL)
1.8.2.1 ! 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.8.2.1 ! tb        380:                        ober_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf),
1.1       reyk      381:                            EVBUFFER_LENGTH(ldap->buf));
                    382:                        errno = 0;
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! tb        469:                        ober_free_elements(elm);
        !           470:                ober_free(&b);
1.1       reyk      471:                return NULL;
                    472:        }
                    473:
1.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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.8.2.1 ! 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: {
                    583:        struct ber_element *b, *c;
                    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.8.2.1 ! tb        590:        if (ober_scanf_elements(msg->body.search.attrs, "{s(e)}e",
1.1       reyk      591:            &key, &b, &c) != 0)
                    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: {
                    613:        struct ber_element *a, *b;
                    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.8.2.1 ! tb        622:        if (ober_get_eoc(msg->body.search.iter) == 0)
1.1       reyk      623:                goto notfound;
                    624:
1.8.2.1 ! tb        625:        if (ober_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
1.1       reyk      626:            != 0)
                    627:                goto fail;
                    628:
                    629:        msg->body.search.iter = msg->body.search.iter->be_next;
                    630:
                    631:        if ((ret = aldap_get_stringset(a)) == NULL)
                    632:                goto fail;
                    633:
                    634:        (*outvalues) = ret;
                    635:        (*outkey) = utoa(key);
                    636:
                    637:        return (1);
                    638: fail:
                    639: notfound:
                    640:        (*outkey) = NULL;
                    641:        (*outvalues) = NULL;
                    642:        return (-1);
                    643: }
                    644:
                    645: int
1.6       martijn   646: aldap_match_attr(struct aldap_message *msg, char *inkey,
                    647:     struct aldap_stringset **outvalues)
1.1       reyk      648: {
                    649:        struct ber_element *a, *b;
                    650:        char *descr = NULL;
1.6       martijn   651:        struct aldap_stringset *ret;
1.1       reyk      652:
                    653:        if (msg->body.search.attrs == NULL)
                    654:                goto fail;
                    655:
                    656:        LDAP_DEBUG("attr", msg->body.search.attrs);
                    657:
                    658:        for (a = msg->body.search.attrs;;) {
                    659:                if (a == NULL)
                    660:                        goto notfound;
1.8.2.1 ! tb        661:                if (ober_get_eoc(a) == 0)
1.1       reyk      662:                        goto notfound;
1.8.2.1 ! tb        663:                if (ober_scanf_elements(a, "{s(e", &descr, &b) != 0)
1.1       reyk      664:                        goto fail;
                    665:                if (strcasecmp(descr, inkey) == 0)
                    666:                        goto attrfound;
                    667:                a = a->be_next;
                    668:        }
                    669:
                    670: attrfound:
                    671:        if ((ret = aldap_get_stringset(b)) == NULL)
                    672:                goto fail;
                    673:
                    674:        (*outvalues) = ret;
                    675:
                    676:        return (1);
                    677: fail:
                    678: notfound:
                    679:        (*outvalues) = NULL;
                    680:        return (-1);
                    681: }
                    682:
                    683: int
1.6       martijn   684: aldap_free_attr(struct aldap_stringset *values)
1.1       reyk      685: {
                    686:        if (values == NULL)
                    687:                return -1;
                    688:
1.6       martijn   689:        free(values->str);
1.1       reyk      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:
1.6       martijn   839: struct aldap_stringset *
1.1       reyk      840: aldap_get_stringset(struct ber_element *elm)
                    841: {
                    842:        struct ber_element *a;
                    843:        int i;
1.6       martijn   844:        struct aldap_stringset *ret;
1.1       reyk      845:
                    846:        if (elm->be_type != BER_TYPE_OCTETSTRING)
                    847:                return NULL;
                    848:
1.6       martijn   849:        if ((ret = malloc(sizeof(*ret))) == NULL)
                    850:                return NULL;
                    851:        for (a = elm, ret->len = 0; a != NULL && a->be_type ==
                    852:            BER_TYPE_OCTETSTRING; a = a->be_next, ret->len++)
1.1       reyk      853:                ;
1.6       martijn   854:        if (ret->len == 0) {
                    855:                free(ret);
1.1       reyk      856:                return NULL;
1.6       martijn   857:        }
1.1       reyk      858:
1.6       martijn   859:        if ((ret->str = reallocarray(NULL, ret->len,
                    860:            sizeof(*(ret->str)))) == NULL) {
                    861:                free(ret);
1.1       reyk      862:                return NULL;
1.6       martijn   863:        }
1.1       reyk      864:
                    865:        for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
1.6       martijn   866:            a = a->be_next, i++)
1.8.2.1 ! tb        867:                (void) ober_get_ostring(a, &(ret->str[i]));
1.1       reyk      868:
                    869:        return ret;
                    870: }
                    871:
                    872: /*
                    873:  * Base case for ldap_do_parse_search_filter
                    874:  *
                    875:  * returns:
                    876:  *     struct ber_element *, ber_element tree
                    877:  *     NULL, parse failed
                    878:  */
                    879: static struct ber_element *
                    880: ldap_parse_search_filter(struct ber_element *ber, char *filter)
                    881: {
                    882:        struct ber_element *elm;
                    883:        char *cp;
                    884:
                    885:        cp = filter;
                    886:
                    887:        if (cp == NULL || *cp == '\0') {
                    888:                errno = EINVAL;
                    889:                return (NULL);
                    890:        }
                    891:
                    892:        if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
                    893:                return (NULL);
                    894:
                    895:        if (*cp != '\0') {
1.8.2.1 ! tb        896:                ober_free_elements(elm);
        !           897:                ober_link_elements(ber, NULL);
1.1       reyk      898:                errno = EINVAL;
                    899:                return (NULL);
                    900:        }
                    901:
                    902:        return (elm);
                    903: }
                    904:
                    905: /*
                    906:  * Translate RFC4515 search filter string into ber_element tree
                    907:  *
                    908:  * returns:
                    909:  *     struct ber_element *, ber_element tree
                    910:  *     NULL, parse failed
                    911:  *
                    912:  * notes:
                    913:  *     when cp is passed to a recursive invocation, it is updated
                    914:  *         to point one character beyond the filter that was passed
                    915:  *         i.e., cp jumps to "(filter)" upon return
                    916:  *                                    ^
                    917:  *     goto's used to discriminate error-handling based on error type
                    918:  *     doesn't handle extended filters (yet)
                    919:  *
                    920:  */
                    921: static struct ber_element *
                    922: ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
                    923: {
                    924:        struct ber_element *elm, *root = NULL;
                    925:        char *attr_desc, *attr_val, *parsed_val, *cp;
                    926:        size_t len;
                    927:        unsigned long type;
                    928:
                    929:        root = NULL;
                    930:
                    931:        /* cpp should pass in pointer to opening parenthesis of "(filter)" */
                    932:        cp = *cpp;
                    933:        if (*cp != '(')
                    934:                goto syntaxfail;
                    935:
                    936:        switch (*++cp) {
                    937:        case '&':               /* AND */
                    938:        case '|':               /* OR */
                    939:                if (*cp == '&')
                    940:                        type = LDAP_FILT_AND;
                    941:                else
                    942:                        type = LDAP_FILT_OR;
                    943:
1.8.2.1 ! tb        944:                if ((elm = ober_add_set(prev)) == NULL)
1.1       reyk      945:                        goto callfail;
                    946:                root = elm;
1.8.2.1 ! tb        947:                ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1       reyk      948:
                    949:                if (*++cp != '(')               /* opening `(` of filter */
                    950:                        goto syntaxfail;
                    951:
                    952:                while (*cp == '(') {
                    953:                        if ((elm =
                    954:                            ldap_do_parse_search_filter(elm, &cp)) == NULL)
                    955:                                goto bad;
                    956:                }
                    957:
                    958:                if (*cp != ')')                 /* trailing `)` of filter */
                    959:                        goto syntaxfail;
                    960:                break;
                    961:
                    962:        case '!':               /* NOT */
1.8.2.1 ! tb        963:                if ((root = ober_add_sequence(prev)) == NULL)
1.1       reyk      964:                        goto callfail;
1.8.2.1 ! tb        965:                ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
1.1       reyk      966:
                    967:                cp++;                           /* now points to sub-filter */
                    968:                if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
                    969:                        goto bad;
                    970:
                    971:                if (*cp != ')')                 /* trailing `)` of filter */
                    972:                        goto syntaxfail;
                    973:                break;
                    974:
                    975:        default:        /* SIMPLE || PRESENCE */
                    976:                attr_desc = cp;
                    977:
                    978:                len = strcspn(cp, "()<>~=");
                    979:                cp += len;
                    980:                switch (*cp) {
                    981:                case '~':
                    982:                        type = LDAP_FILT_APPR;
                    983:                        cp++;
                    984:                        break;
                    985:                case '<':
                    986:                        type = LDAP_FILT_LE;
                    987:                        cp++;
                    988:                        break;
                    989:                case '>':
                    990:                        type = LDAP_FILT_GE;
                    991:                        cp++;
                    992:                        break;
                    993:                case '=':
                    994:                        type = LDAP_FILT_EQ;    /* assume EQ until disproven */
                    995:                        break;
                    996:                case '(':
                    997:                case ')':
                    998:                default:
                    999:                        goto syntaxfail;
                   1000:                }
                   1001:                attr_val = ++cp;
                   1002:
                   1003:                /* presence filter */
                   1004:                if (strncmp(attr_val, "*)", 2) == 0) {
                   1005:                        cp++;                   /* point to trailing `)` */
                   1006:                        if ((root =
1.8.2.1 ! tb       1007:                            ober_add_nstring(prev, attr_desc, len)) == NULL)
1.1       reyk     1008:                                goto bad;
                   1009:
1.8.2.1 ! tb       1010:                        ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
1.1       reyk     1011:                        break;
                   1012:                }
                   1013:
1.8.2.1 ! tb       1014:                if ((root = ober_add_sequence(prev)) == NULL)
1.1       reyk     1015:                        goto callfail;
1.8.2.1 ! tb       1016:                ober_set_header(root, BER_CLASS_CONTEXT, type);
1.1       reyk     1017:
1.8.2.1 ! tb       1018:                if ((elm = ober_add_nstring(root, attr_desc, len)) == NULL)
1.1       reyk     1019:                        goto callfail;
                   1020:
                   1021:                len = strcspn(attr_val, "*)");
                   1022:                if (len == 0 && *cp != '*')
                   1023:                        goto syntaxfail;
                   1024:                cp += len;
                   1025:                if (*cp == '\0')
                   1026:                        goto syntaxfail;
                   1027:
                   1028:                if (*cp == '*') {       /* substring filter */
                   1029:                        int initial;
                   1030:
                   1031:                        cp = attr_val;
                   1032:
1.8.2.1 ! tb       1033:                        ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
1.1       reyk     1034:
1.8.2.1 ! tb       1035:                        if ((elm = ober_add_sequence(elm)) == NULL)
1.1       reyk     1036:                                goto callfail;
                   1037:
                   1038:                        for (initial = 1;; cp++, initial = 0) {
                   1039:                                attr_val = cp;
                   1040:
                   1041:                                len = strcspn(attr_val, "*)");
                   1042:                                if (len == 0) {
                   1043:                                        if (*cp == ')')
                   1044:                                                break;
                   1045:                                        else
                   1046:                                                continue;
                   1047:                                }
                   1048:                                cp += len;
                   1049:                                if (*cp == '\0')
                   1050:                                        goto syntaxfail;
                   1051:
                   1052:                                if (initial)
                   1053:                                        type = LDAP_FILT_SUBS_INIT;
                   1054:                                else if (*cp == ')')
                   1055:                                        type = LDAP_FILT_SUBS_FIN;
                   1056:                                else
                   1057:                                        type = LDAP_FILT_SUBS_ANY;
                   1058:
                   1059:                                if ((parsed_val = parseval(attr_val, len)) ==
                   1060:                                    NULL)
                   1061:                                        goto callfail;
1.8.2.1 ! tb       1062:                                elm = ober_add_nstring(elm, parsed_val,
1.1       reyk     1063:                                    strlen(parsed_val));
                   1064:                                free(parsed_val);
                   1065:                                if (elm == NULL)
                   1066:                                        goto callfail;
1.8.2.1 ! tb       1067:                                ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1       reyk     1068:                                if (type == LDAP_FILT_SUBS_FIN)
                   1069:                                        break;
                   1070:                        }
                   1071:                        break;
                   1072:                }
                   1073:
                   1074:                if ((parsed_val = parseval(attr_val, len)) == NULL)
                   1075:                        goto callfail;
1.8.2.1 ! tb       1076:                elm = ober_add_nstring(elm, parsed_val, strlen(parsed_val));
1.1       reyk     1077:                free(parsed_val);
                   1078:                if (elm == NULL)
                   1079:                        goto callfail;
                   1080:                break;
                   1081:        }
                   1082:
                   1083:        cp++;           /* now points one char beyond the trailing `)` */
                   1084:
                   1085:        *cpp = cp;
                   1086:        return (root);
                   1087:
                   1088: syntaxfail:            /* XXX -- error reporting */
                   1089: callfail:
                   1090: bad:
                   1091:        if (root != NULL)
1.8.2.1 ! tb       1092:                ober_free_elements(root);
        !          1093:        ober_link_elements(prev, NULL);
1.1       reyk     1094:        return (NULL);
                   1095: }
                   1096:
                   1097: #ifdef DEBUG
                   1098: /*
                   1099:  * Display a list of ber elements.
                   1100:  *
                   1101:  */
                   1102: void
                   1103: ldap_debug_elements(struct ber_element *root)
                   1104: {
                   1105:        static int       indent = 0;
                   1106:        long long        v;
                   1107:        int              d;
                   1108:        char            *buf;
                   1109:        size_t           len;
                   1110:        u_int            i;
                   1111:        int              constructed;
                   1112:        struct ber_oid   o;
                   1113:
                   1114:        /* calculate lengths */
1.8.2.1 ! tb       1115:        ober_calc_len(root);
1.1       reyk     1116:
                   1117:        switch (root->be_encoding) {
                   1118:        case BER_TYPE_SEQUENCE:
                   1119:        case BER_TYPE_SET:
                   1120:                constructed = root->be_encoding;
                   1121:                break;
                   1122:        default:
                   1123:                constructed = 0;
                   1124:                break;
                   1125:        }
                   1126:
                   1127:        fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
                   1128:        switch (root->be_class) {
                   1129:        case BER_CLASS_UNIVERSAL:
                   1130:                fprintf(stderr, "class: universal(%u) type: ", root->be_class);
                   1131:                switch (root->be_type) {
                   1132:                case BER_TYPE_EOC:
                   1133:                        fprintf(stderr, "end-of-content");
                   1134:                        break;
                   1135:                case BER_TYPE_BOOLEAN:
                   1136:                        fprintf(stderr, "boolean");
                   1137:                        break;
                   1138:                case BER_TYPE_INTEGER:
                   1139:                        fprintf(stderr, "integer");
                   1140:                        break;
                   1141:                case BER_TYPE_BITSTRING:
                   1142:                        fprintf(stderr, "bit-string");
                   1143:                        break;
                   1144:                case BER_TYPE_OCTETSTRING:
                   1145:                        fprintf(stderr, "octet-string");
                   1146:                        break;
                   1147:                case BER_TYPE_NULL:
                   1148:                        fprintf(stderr, "null");
                   1149:                        break;
                   1150:                case BER_TYPE_OBJECT:
                   1151:                        fprintf(stderr, "object");
                   1152:                        break;
                   1153:                case BER_TYPE_ENUMERATED:
                   1154:                        fprintf(stderr, "enumerated");
                   1155:                        break;
                   1156:                case BER_TYPE_SEQUENCE:
                   1157:                        fprintf(stderr, "sequence");
                   1158:                        break;
                   1159:                case BER_TYPE_SET:
                   1160:                        fprintf(stderr, "set");
                   1161:                        break;
                   1162:                }
                   1163:                break;
                   1164:        case BER_CLASS_APPLICATION:
                   1165:                fprintf(stderr, "class: application(%u) type: ",
                   1166:                    root->be_class);
                   1167:                switch (root->be_type) {
                   1168:                case LDAP_REQ_BIND:
                   1169:                        fprintf(stderr, "bind");
                   1170:                        break;
                   1171:                case LDAP_RES_BIND:
                   1172:                        fprintf(stderr, "bind");
                   1173:                        break;
                   1174:                case LDAP_REQ_UNBIND_30:
                   1175:                        break;
                   1176:                case LDAP_REQ_SEARCH:
                   1177:                        fprintf(stderr, "search");
                   1178:                        break;
                   1179:                case LDAP_RES_SEARCH_ENTRY:
                   1180:                        fprintf(stderr, "search_entry");
                   1181:                        break;
                   1182:                case LDAP_RES_SEARCH_RESULT:
                   1183:                        fprintf(stderr, "search_result");
                   1184:                        break;
                   1185:                case LDAP_REQ_MODIFY:
                   1186:                        fprintf(stderr, "modify");
                   1187:                        break;
                   1188:                case LDAP_RES_MODIFY:
                   1189:                        fprintf(stderr, "modify");
                   1190:                        break;
                   1191:                case LDAP_REQ_ADD:
                   1192:                        fprintf(stderr, "add");
                   1193:                        break;
                   1194:                case LDAP_RES_ADD:
                   1195:                        fprintf(stderr, "add");
                   1196:                        break;
                   1197:                case LDAP_REQ_DELETE_30:
                   1198:                        fprintf(stderr, "delete");
                   1199:                        break;
                   1200:                case LDAP_RES_DELETE:
                   1201:                        fprintf(stderr, "delete");
                   1202:                        break;
                   1203:                case LDAP_REQ_MODRDN:
                   1204:                        fprintf(stderr, "modrdn");
                   1205:                        break;
                   1206:                case LDAP_RES_MODRDN:
                   1207:                        fprintf(stderr, "modrdn");
                   1208:                        break;
                   1209:                case LDAP_REQ_COMPARE:
                   1210:                        fprintf(stderr, "compare");
                   1211:                        break;
                   1212:                case LDAP_RES_COMPARE:
                   1213:                        fprintf(stderr, "compare");
                   1214:                        break;
                   1215:                case LDAP_REQ_ABANDON_30:
                   1216:                        fprintf(stderr, "abandon");
                   1217:                        break;
                   1218:                }
                   1219:                break;
                   1220:        case BER_CLASS_PRIVATE:
                   1221:                fprintf(stderr, "class: private(%u) type: ", root->be_class);
1.4       rob      1222:                fprintf(stderr, "encoding (%u) type: ", root->be_encoding);
1.1       reyk     1223:                break;
                   1224:        case BER_CLASS_CONTEXT:
                   1225:                /* XXX: this is not correct */
                   1226:                fprintf(stderr, "class: context(%u) type: ", root->be_class);
                   1227:                switch(root->be_type) {
                   1228:                case LDAP_AUTH_SIMPLE:
                   1229:                        fprintf(stderr, "auth simple");
                   1230:                        break;
                   1231:                }
                   1232:                break;
                   1233:        default:
                   1234:                fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
                   1235:                break;
                   1236:        }
1.4       rob      1237:        fprintf(stderr, "(%u) encoding %u ",
1.1       reyk     1238:            root->be_type, root->be_encoding);
                   1239:
                   1240:        if (constructed)
                   1241:                root->be_encoding = constructed;
                   1242:
                   1243:        switch (root->be_encoding) {
                   1244:        case BER_TYPE_BOOLEAN:
1.8.2.1 ! tb       1245:                if (ober_get_boolean(root, &d) == -1) {
1.1       reyk     1246:                        fprintf(stderr, "<INVALID>\n");
                   1247:                        break;
                   1248:                }
                   1249:                fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
                   1250:                break;
                   1251:        case BER_TYPE_INTEGER:
1.8.2.1 ! tb       1252:                if (ober_get_integer(root, &v) == -1) {
1.1       reyk     1253:                        fprintf(stderr, "<INVALID>\n");
                   1254:                        break;
                   1255:                }
                   1256:                fprintf(stderr, "value %lld\n", v);
                   1257:                break;
                   1258:        case BER_TYPE_ENUMERATED:
1.8.2.1 ! tb       1259:                if (ober_get_enumerated(root, &v) == -1) {
1.1       reyk     1260:                        fprintf(stderr, "<INVALID>\n");
                   1261:                        break;
                   1262:                }
                   1263:                fprintf(stderr, "value %lld\n", v);
                   1264:                break;
                   1265:        case BER_TYPE_BITSTRING:
1.8.2.1 ! tb       1266:                if (ober_get_bitstring(root, (void *)&buf, &len) == -1) {
1.1       reyk     1267:                        fprintf(stderr, "<INVALID>\n");
                   1268:                        break;
                   1269:                }
                   1270:                fprintf(stderr, "hexdump ");
                   1271:                for (i = 0; i < len; i++)
                   1272:                        fprintf(stderr, "%02x", buf[i]);
                   1273:                fprintf(stderr, "\n");
                   1274:                break;
                   1275:        case BER_TYPE_OBJECT:
1.8.2.1 ! tb       1276:                if (ober_get_oid(root, &o) == -1) {
1.1       reyk     1277:                        fprintf(stderr, "<INVALID>\n");
                   1278:                        break;
                   1279:                }
                   1280:                fprintf(stderr, "\n");
                   1281:                break;
                   1282:        case BER_TYPE_OCTETSTRING:
1.8.2.1 ! tb       1283:                if (ober_get_nstring(root, (void *)&buf, &len) == -1) {
1.1       reyk     1284:                        fprintf(stderr, "<INVALID>\n");
                   1285:                        break;
                   1286:                }
1.2       reyk     1287:                fprintf(stderr, "string \"%.*s\"\n",  (int)len, buf);
1.1       reyk     1288:                break;
                   1289:        case BER_TYPE_NULL:     /* no payload */
                   1290:        case BER_TYPE_EOC:
                   1291:        case BER_TYPE_SEQUENCE:
                   1292:        case BER_TYPE_SET:
                   1293:        default:
                   1294:                fprintf(stderr, "\n");
                   1295:                break;
                   1296:        }
                   1297:
                   1298:        if (constructed && root->be_sub) {
                   1299:                indent += 2;
                   1300:                ldap_debug_elements(root->be_sub);
                   1301:                indent -= 2;
                   1302:        }
                   1303:        if (root->be_next)
                   1304:                ldap_debug_elements(root->be_next);
                   1305: }
                   1306: #endif
                   1307:
                   1308: /*
                   1309:  * Strip UTF-8 down to ASCII without validation.
                   1310:  * notes:
                   1311:  *     non-ASCII characters are displayed as '?'
                   1312:  *     the argument u should be a NULL terminated sequence of UTF-8 bytes.
                   1313:  */
                   1314: char *
                   1315: utoa(char *u)
                   1316: {
                   1317:        int      len, i, j;
                   1318:        char    *str;
                   1319:
                   1320:        /* calculate the length to allocate */
                   1321:        for (len = 0, i = 0; u[i] != '\0'; i++)
                   1322:                if (!isu8cont(u[i]))
                   1323:                        len++;
                   1324:
                   1325:        if ((str = calloc(len + 1, sizeof(char))) == NULL)
                   1326:                return NULL;
                   1327:
                   1328:        /* copy the ASCII characters to the newly allocated string */
                   1329:        for (i = 0, j = 0; u[i] != '\0'; i++)
                   1330:                if (!isu8cont(u[i]))
                   1331:                        str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?';
                   1332:
                   1333:        return str;
                   1334: }
                   1335:
                   1336: static int
                   1337: isu8cont(unsigned char c)
                   1338: {
                   1339:        return (c & (0x80 | 0x40)) == 0x80;
                   1340: }
                   1341:
                   1342: /*
                   1343:  * Parse a LDAP value
                   1344:  * notes:
                   1345:  *     the argument p should be a NUL-terminated sequence of ASCII bytes
                   1346:  */
                   1347: char *
                   1348: parseval(char *p, size_t len)
                   1349: {
                   1350:        char     hex[3];
                   1351:        char    *buffer;
                   1352:        size_t   i, j;
                   1353:
                   1354:        if ((buffer = calloc(1, len + 1)) == NULL)
                   1355:                return NULL;
                   1356:
                   1357:        for (i = j = 0; j < len; i++) {
                   1358:                if (p[j] == '\\') {
                   1359:                        strlcpy(hex, p + j + 1, sizeof(hex));
                   1360:                        buffer[i] = (char)strtoumax(hex, NULL, 16);
                   1361:                        j += 3;
                   1362:                } else {
                   1363:                        buffer[i] = p[j];
                   1364:                        j++;
                   1365:                }
                   1366:        }
                   1367:
                   1368:        return buffer;
                   1369: }
                   1370:
                   1371: int
                   1372: aldap_get_errno(struct aldap *a, const char **estr)
                   1373: {
                   1374:        switch (a->err) {
                   1375:        case ALDAP_ERR_SUCCESS:
                   1376:                *estr = "success";
                   1377:                break;
                   1378:        case ALDAP_ERR_PARSER_ERROR:
                   1379:                *estr = "parser failed";
                   1380:                break;
                   1381:        case ALDAP_ERR_INVALID_FILTER:
                   1382:                *estr = "invalid filter";
                   1383:                break;
                   1384:        case ALDAP_ERR_OPERATION_FAILED:
                   1385:                *estr = "operation failed";
                   1386:                break;
                   1387:        case ALDAP_ERR_TLS_ERROR:
                   1388:                *estr = tls_error(a->tls);
                   1389:                break;
                   1390:        default:
                   1391:                *estr = "unknown";
                   1392:                break;
                   1393:        }
                   1394:        return (a->err);
                   1395: }