[BACK]Return to ber.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ldap

Annotation of src/usr.bin/ldap/ber.c, Revision 1.18

1.18    ! rob         1: /*     $OpenBSD: ber.c,v 1.17 2018/07/31 19:38:09 rob Exp $ */
1.1       reyk        2:
                      3: /*
1.6       rob         4:  * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
1.1       reyk        5:  * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
                      6:  * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
                      7:  *
                      8:  * Permission to use, copy, modify, and distribute this software for any
                      9:  * purpose with or without fee is hereby granted, provided that the above
                     10:  * copyright notice and this permission notice appear in all copies.
                     11:  *
                     12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     19:  */
                     20:
                     21: #include <sys/types.h>
                     22:
                     23: #include <errno.h>
                     24: #include <limits.h>
                     25: #include <stdlib.h>
                     26: #include <err.h>       /* XXX for debug output */
                     27: #include <stdio.h>     /* XXX for debug output */
                     28: #include <string.h>
                     29: #include <unistd.h>
                     30: #include <stdarg.h>
                     31:
                     32: #include "ber.h"
                     33:
                     34: #define BER_TYPE_CONSTRUCTED   0x20    /* otherwise primitive */
                     35: #define BER_TYPE_SINGLE_MAX    30
                     36: #define BER_TAG_MASK           0x1f
                     37: #define BER_TAG_MORE           0x80    /* more subsequent octets */
                     38: #define BER_TAG_TYPE_MASK      0x7f
                     39: #define BER_CLASS_SHIFT                6
                     40:
                     41: static int     ber_dump_element(struct ber *ber, struct ber_element *root);
                     42: static void    ber_dump_header(struct ber *ber, struct ber_element *root);
                     43: static void    ber_putc(struct ber *ber, u_char c);
                     44: static void    ber_write(struct ber *ber, void *buf, size_t len);
1.15      claudio    45: static ssize_t get_id(struct ber *b, unsigned int *tag, int *class,
1.1       reyk       46:     int *cstruct);
                     47: static ssize_t get_len(struct ber *b, ssize_t *len);
                     48: static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm);
                     49: static ssize_t ber_getc(struct ber *b, u_char *c);
                     50: static ssize_t ber_read(struct ber *ber, void *buf, size_t len);
                     51:
                     52: #ifdef DEBUG
                     53: #define DPRINTF(...)   printf(__VA_ARGS__)
                     54: #else
                     55: #define DPRINTF(...)   do { } while (0)
                     56: #endif
                     57:
                     58: struct ber_element *
1.15      claudio    59: ber_get_element(unsigned int encoding)
1.1       reyk       60: {
                     61:        struct ber_element *elm;
                     62:
                     63:        if ((elm = calloc(1, sizeof(*elm))) == NULL)
                     64:                return NULL;
                     65:
                     66:        elm->be_encoding = encoding;
                     67:        ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
                     68:
                     69:        return elm;
                     70: }
                     71:
                     72: void
1.15      claudio    73: ber_set_header(struct ber_element *elm, int class, unsigned int type)
1.1       reyk       74: {
                     75:        elm->be_class = class & BER_CLASS_MASK;
                     76:        if (type == BER_TYPE_DEFAULT)
                     77:                type = elm->be_encoding;
                     78:        elm->be_type = type;
                     79: }
                     80:
                     81: void
                     82: ber_link_elements(struct ber_element *prev, struct ber_element *elm)
                     83: {
                     84:        if (prev != NULL) {
                     85:                if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
                     86:                    prev->be_encoding == BER_TYPE_SET) &&
                     87:                    prev->be_sub == NULL)
                     88:                        prev->be_sub = elm;
                     89:                else
                     90:                        prev->be_next = elm;
                     91:        }
                     92: }
                     93:
                     94: struct ber_element *
                     95: ber_unlink_elements(struct ber_element *prev)
                     96: {
                     97:        struct ber_element *elm;
                     98:
                     99:        if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
                    100:            prev->be_encoding == BER_TYPE_SET) &&
                    101:            prev->be_sub != NULL) {
                    102:                elm = prev->be_sub;
                    103:                prev->be_sub = NULL;
                    104:        } else {
                    105:                elm = prev->be_next;
                    106:                prev->be_next = NULL;
                    107:        }
                    108:
                    109:        return (elm);
                    110: }
                    111:
                    112: void
                    113: ber_replace_elements(struct ber_element *prev, struct ber_element *new)
                    114: {
                    115:        struct ber_element *ber, *next;
                    116:
                    117:        ber = ber_unlink_elements(prev);
                    118:        next = ber_unlink_elements(ber);
                    119:        ber_link_elements(new, next);
                    120:        ber_link_elements(prev, new);
                    121:
                    122:        /* cleanup old element */
                    123:        ber_free_elements(ber);
                    124: }
                    125:
                    126: struct ber_element *
                    127: ber_add_sequence(struct ber_element *prev)
                    128: {
                    129:        struct ber_element *elm;
                    130:
                    131:        if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL)
                    132:                return NULL;
                    133:
                    134:        ber_link_elements(prev, elm);
                    135:
                    136:        return elm;
                    137: }
                    138:
                    139: struct ber_element *
                    140: ber_add_set(struct ber_element *prev)
                    141: {
                    142:        struct ber_element *elm;
                    143:
                    144:        if ((elm = ber_get_element(BER_TYPE_SET)) == NULL)
                    145:                return NULL;
                    146:
                    147:        ber_link_elements(prev, elm);
                    148:
                    149:        return elm;
                    150: }
                    151:
                    152: struct ber_element *
                    153: ber_add_enumerated(struct ber_element *prev, long long val)
                    154: {
                    155:        struct ber_element *elm;
                    156:        u_int i, len = 0;
                    157:        u_char cur, last = 0;
                    158:
                    159:        if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL)
                    160:                return NULL;
                    161:
                    162:        elm->be_numeric = val;
                    163:
                    164:        for (i = 0; i < sizeof(long long); i++) {
                    165:                cur = val & 0xff;
                    166:                if (cur != 0 && cur != 0xff)
                    167:                        len = i;
                    168:                if ((cur == 0 && last & 0x80) ||
                    169:                    (cur == 0xff && (last & 0x80) == 0))
                    170:                        len = i;
                    171:                val >>= 8;
                    172:                last = cur;
                    173:        }
                    174:        elm->be_len = len + 1;
                    175:
                    176:        ber_link_elements(prev, elm);
                    177:
                    178:        return elm;
                    179: }
                    180:
                    181: struct ber_element *
                    182: ber_add_integer(struct ber_element *prev, long long val)
                    183: {
                    184:        struct ber_element *elm;
                    185:        u_int i, len = 0;
                    186:        u_char cur, last = 0;
                    187:
                    188:        if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL)
                    189:                return NULL;
                    190:
                    191:        elm->be_numeric = val;
                    192:
                    193:        for (i = 0; i < sizeof(long long); i++) {
                    194:                cur = val & 0xff;
                    195:                if (cur != 0 && cur != 0xff)
                    196:                        len = i;
                    197:                if ((cur == 0 && last & 0x80) ||
                    198:                    (cur == 0xff && (last & 0x80) == 0))
                    199:                        len = i;
                    200:                val >>= 8;
                    201:                last = cur;
                    202:        }
                    203:        elm->be_len = len + 1;
                    204:
                    205:        ber_link_elements(prev, elm);
                    206:
                    207:        return elm;
                    208: }
                    209:
                    210: int
                    211: ber_get_integer(struct ber_element *elm, long long *n)
                    212: {
                    213:        if (elm->be_encoding != BER_TYPE_INTEGER)
                    214:                return -1;
                    215:
                    216:        *n = elm->be_numeric;
                    217:        return 0;
                    218: }
                    219:
                    220: int
                    221: ber_get_enumerated(struct ber_element *elm, long long *n)
                    222: {
                    223:        if (elm->be_encoding != BER_TYPE_ENUMERATED)
                    224:                return -1;
                    225:
                    226:        *n = elm->be_numeric;
                    227:        return 0;
                    228: }
                    229:
                    230: struct ber_element *
                    231: ber_add_boolean(struct ber_element *prev, int bool)
                    232: {
                    233:        struct ber_element *elm;
                    234:
                    235:        if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL)
                    236:                return NULL;
                    237:
                    238:        elm->be_numeric = bool ? 0xff : 0;
                    239:        elm->be_len = 1;
                    240:
                    241:        ber_link_elements(prev, elm);
                    242:
                    243:        return elm;
                    244: }
                    245:
                    246: int
                    247: ber_get_boolean(struct ber_element *elm, int *b)
                    248: {
                    249:        if (elm->be_encoding != BER_TYPE_BOOLEAN)
                    250:                return -1;
                    251:
                    252:        *b = !(elm->be_numeric == 0);
                    253:        return 0;
                    254: }
                    255:
                    256: struct ber_element *
                    257: ber_add_string(struct ber_element *prev, const char *string)
                    258: {
                    259:        return ber_add_nstring(prev, string, strlen(string));
                    260: }
                    261:
                    262: struct ber_element *
                    263: ber_add_nstring(struct ber_element *prev, const char *string0, size_t len)
                    264: {
                    265:        struct ber_element *elm;
                    266:        char *string;
                    267:
1.3       rob       268:        if ((string = calloc(1, len + 1)) == NULL)
1.1       reyk      269:                return NULL;
                    270:        if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
                    271:                free(string);
                    272:                return NULL;
                    273:        }
                    274:
                    275:        bcopy(string0, string, len);
                    276:        elm->be_val = string;
                    277:        elm->be_len = len;
                    278:        elm->be_free = 1;               /* free string on cleanup */
                    279:
                    280:        ber_link_elements(prev, elm);
                    281:
                    282:        return elm;
                    283: }
                    284:
                    285: int
                    286: ber_get_string(struct ber_element *elm, char **s)
                    287: {
                    288:        if (elm->be_encoding != BER_TYPE_OCTETSTRING)
                    289:                return -1;
                    290:
                    291:        *s = elm->be_val;
                    292:        return 0;
                    293: }
                    294:
                    295: int
                    296: ber_get_nstring(struct ber_element *elm, void **p, size_t *len)
                    297: {
                    298:        if (elm->be_encoding != BER_TYPE_OCTETSTRING)
                    299:                return -1;
                    300:
                    301:        *p = elm->be_val;
                    302:        *len = elm->be_len;
                    303:        return 0;
                    304: }
                    305:
                    306: struct ber_element *
                    307: ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
                    308: {
                    309:        struct ber_element *elm;
                    310:        void *v;
                    311:
                    312:        if ((v = calloc(1, len)) == NULL)
                    313:                return NULL;
                    314:        if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) {
                    315:                free(v);
                    316:                return NULL;
                    317:        }
                    318:
                    319:        bcopy(v0, v, len);
                    320:        elm->be_val = v;
                    321:        elm->be_len = len;
                    322:        elm->be_free = 1;               /* free string on cleanup */
                    323:
                    324:        ber_link_elements(prev, elm);
                    325:
                    326:        return elm;
                    327: }
                    328:
                    329: int
                    330: ber_get_bitstring(struct ber_element *elm, void **v, size_t *len)
                    331: {
                    332:        if (elm->be_encoding != BER_TYPE_BITSTRING)
                    333:                return -1;
                    334:
                    335:        *v = elm->be_val;
                    336:        *len = elm->be_len;
                    337:        return 0;
                    338: }
                    339:
                    340: struct ber_element *
                    341: ber_add_null(struct ber_element *prev)
                    342: {
                    343:        struct ber_element *elm;
                    344:
                    345:        if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL)
                    346:                return NULL;
                    347:
                    348:        ber_link_elements(prev, elm);
                    349:
                    350:        return elm;
                    351: }
                    352:
                    353: int
                    354: ber_get_null(struct ber_element *elm)
                    355: {
                    356:        if (elm->be_encoding != BER_TYPE_NULL)
                    357:                return -1;
                    358:
                    359:        return 0;
                    360: }
                    361:
                    362: struct ber_element *
                    363: ber_add_eoc(struct ber_element *prev)
                    364: {
                    365:        struct ber_element *elm;
                    366:
                    367:        if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL)
                    368:                return NULL;
                    369:
                    370:        ber_link_elements(prev, elm);
                    371:
                    372:        return elm;
                    373: }
                    374:
                    375: int
                    376: ber_get_eoc(struct ber_element *elm)
                    377: {
                    378:        if (elm->be_encoding != BER_TYPE_EOC)
                    379:                return -1;
                    380:
                    381:        return 0;
                    382: }
                    383:
                    384: size_t
                    385: ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
                    386: {
                    387:        u_int32_t        v;
                    388:        u_int            i, j = 0, k;
                    389:
                    390:        if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
                    391:            o->bo_id[0] > 2 || o->bo_id[1] > 40)
                    392:                return (0);
                    393:
                    394:        v = (o->bo_id[0] * 40) + o->bo_id[1];
                    395:        for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
                    396:                for (k = 28; k >= 7; k -= 7) {
                    397:                        if (v >= (u_int)(1 << k)) {
                    398:                                if (len)
                    399:                                        buf[j] = v >> k | BER_TAG_MORE;
                    400:                                j++;
                    401:                        }
                    402:                }
                    403:                if (len)
                    404:                        buf[j] = v & BER_TAG_TYPE_MASK;
                    405:                j++;
                    406:        }
                    407:
                    408:        return (j);
                    409: }
                    410:
                    411: int
                    412: ber_string2oid(const char *oidstr, struct ber_oid *o)
                    413: {
                    414:        char                    *sp, *p, str[BUFSIZ];
                    415:        const char              *errstr;
                    416:
                    417:        if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
                    418:                return (-1);
                    419:        memset(o, 0, sizeof(*o));
                    420:
                    421:        /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
                    422:        for (p = sp = str; p != NULL; sp = p) {
                    423:                if ((p = strpbrk(p, "._-")) != NULL)
                    424:                        *p++ = '\0';
                    425:                o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
                    426:                if (errstr || o->bo_n > BER_MAX_OID_LEN)
                    427:                        return (-1);
                    428:        }
                    429:
                    430:        return (0);
                    431: }
                    432:
1.17      rob       433: int
                    434: ber_oid_cmp(struct ber_oid *a, struct ber_oid *b)
                    435: {
                    436:        size_t   i;
                    437:        for (i = 0; i < BER_MAX_OID_LEN; i++) {
                    438:                if (a->bo_id[i] != 0) {
                    439:                        if (a->bo_id[i] == b->bo_id[i])
                    440:                                continue;
                    441:                        else if (a->bo_id[i] < b->bo_id[i]) {
                    442:                                /* b is a successor of a */
                    443:                                return (1);
                    444:                        } else {
                    445:                                /* b is a predecessor of a */
                    446:                                return (-1);
                    447:                        }
                    448:                } else if (b->bo_id[i] != 0) {
                    449:                        /* b is larger, but a child of a */
                    450:                        return (2);
                    451:                } else
                    452:                        break;
                    453:        }
                    454:
                    455:        /* b and a are identical */
                    456:        return (0);
                    457: }
                    458:
1.1       reyk      459: struct ber_element *
                    460: ber_add_oid(struct ber_element *prev, struct ber_oid *o)
                    461: {
                    462:        struct ber_element      *elm;
                    463:        u_int8_t                *buf;
                    464:        size_t                   len;
                    465:
                    466:        if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
                    467:                return (NULL);
                    468:
                    469:        if ((len = ber_oid2ber(o, NULL, 0)) == 0)
                    470:                goto fail;
                    471:
                    472:        if ((buf = calloc(1, len)) == NULL)
                    473:                goto fail;
                    474:
                    475:        elm->be_val = buf;
                    476:        elm->be_len = len;
                    477:        elm->be_free = 1;
                    478:
                    479:        if (ber_oid2ber(o, buf, len) != len)
                    480:                goto fail;
                    481:
                    482:        ber_link_elements(prev, elm);
                    483:
                    484:        return (elm);
                    485:
                    486:  fail:
                    487:        ber_free_elements(elm);
                    488:        return (NULL);
                    489: }
                    490:
                    491: struct ber_element *
                    492: ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
                    493: {
                    494:        struct ber_oid           no;
                    495:
                    496:        if (n > BER_MAX_OID_LEN)
                    497:                return (NULL);
                    498:        no.bo_n = n;
                    499:        bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
                    500:
                    501:        return (ber_add_oid(prev, &no));
                    502: }
                    503:
                    504: struct ber_element *
                    505: ber_add_oidstring(struct ber_element *prev, const char *oidstr)
                    506: {
                    507:        struct ber_oid           o;
                    508:
                    509:        if (ber_string2oid(oidstr, &o) == -1)
                    510:                return (NULL);
                    511:
                    512:        return (ber_add_oid(prev, &o));
                    513: }
                    514:
                    515: int
                    516: ber_get_oid(struct ber_element *elm, struct ber_oid *o)
                    517: {
                    518:        u_int8_t        *buf;
                    519:        size_t           len, i = 0, j = 0;
                    520:
                    521:        if (elm->be_encoding != BER_TYPE_OBJECT)
                    522:                return (-1);
                    523:
                    524:        buf = elm->be_val;
                    525:        len = elm->be_len;
                    526:
                    527:        if (!buf[i])
                    528:                return (-1);
                    529:
                    530:        memset(o, 0, sizeof(*o));
                    531:        o->bo_id[j++] = buf[i] / 40;
                    532:        o->bo_id[j++] = buf[i++] % 40;
                    533:        for (; i < len && j < BER_MAX_OID_LEN; i++) {
                    534:                o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
                    535:                if (buf[i] & 0x80)
                    536:                        continue;
                    537:                j++;
                    538:        }
                    539:        o->bo_n = j;
                    540:
                    541:        return (0);
                    542: }
                    543:
                    544: struct ber_element *
                    545: ber_printf_elements(struct ber_element *ber, char *fmt, ...)
                    546: {
                    547:        va_list                  ap;
                    548:        int                      d, class;
                    549:        size_t                   len;
1.15      claudio   550:        unsigned int             type;
1.1       reyk      551:        long long                i;
                    552:        char                    *s;
                    553:        void                    *p;
                    554:        struct ber_oid          *o;
                    555:        struct ber_element      *sub = ber, *e;
                    556:
                    557:        va_start(ap, fmt);
                    558:        while (*fmt) {
                    559:                switch (*fmt++) {
                    560:                case 'B':
                    561:                        p = va_arg(ap, void *);
                    562:                        len = va_arg(ap, size_t);
                    563:                        if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
                    564:                                goto fail;
                    565:                        break;
                    566:                case 'b':
                    567:                        d = va_arg(ap, int);
                    568:                        if ((ber = ber_add_boolean(ber, d)) == NULL)
                    569:                                goto fail;
                    570:                        break;
                    571:                case 'd':
                    572:                        d = va_arg(ap, int);
                    573:                        if ((ber = ber_add_integer(ber, d)) == NULL)
                    574:                                goto fail;
                    575:                        break;
                    576:                case 'e':
                    577:                        e = va_arg(ap, struct ber_element *);
                    578:                        ber_link_elements(ber, e);
                    579:                        break;
                    580:                case 'E':
                    581:                        i = va_arg(ap, long long);
                    582:                        if ((ber = ber_add_enumerated(ber, i)) == NULL)
                    583:                                goto fail;
                    584:                        break;
                    585:                case 'i':
                    586:                        i = va_arg(ap, long long);
                    587:                        if ((ber = ber_add_integer(ber, i)) == NULL)
                    588:                                goto fail;
                    589:                        break;
                    590:                case 'O':
                    591:                        o = va_arg(ap, struct ber_oid *);
                    592:                        if ((ber = ber_add_oid(ber, o)) == NULL)
                    593:                                goto fail;
                    594:                        break;
                    595:                case 'o':
                    596:                        s = va_arg(ap, char *);
                    597:                        if ((ber = ber_add_oidstring(ber, s)) == NULL)
                    598:                                goto fail;
                    599:                        break;
                    600:                case 's':
                    601:                        s = va_arg(ap, char *);
                    602:                        if ((ber = ber_add_string(ber, s)) == NULL)
                    603:                                goto fail;
                    604:                        break;
                    605:                case 't':
                    606:                        class = va_arg(ap, int);
1.15      claudio   607:                        type = va_arg(ap, unsigned int);
1.1       reyk      608:                        ber_set_header(ber, class, type);
                    609:                        break;
                    610:                case 'x':
                    611:                        s = va_arg(ap, char *);
                    612:                        len = va_arg(ap, size_t);
                    613:                        if ((ber = ber_add_nstring(ber, s, len)) == NULL)
                    614:                                goto fail;
                    615:                        break;
                    616:                case '0':
                    617:                        if ((ber = ber_add_null(ber)) == NULL)
                    618:                                goto fail;
                    619:                        break;
                    620:                case '{':
                    621:                        if ((ber = sub = ber_add_sequence(ber)) == NULL)
                    622:                                goto fail;
                    623:                        break;
                    624:                case '(':
                    625:                        if ((ber = sub = ber_add_set(ber)) == NULL)
                    626:                                goto fail;
                    627:                        break;
                    628:                case '}':
                    629:                case ')':
                    630:                        ber = sub;
                    631:                        break;
                    632:                case '.':
                    633:                        if ((e = ber_add_eoc(ber)) == NULL)
                    634:                                goto fail;
                    635:                        ber = e;
                    636:                        break;
                    637:                default:
                    638:                        break;
                    639:                }
                    640:        }
                    641:        va_end(ap);
                    642:
                    643:        return (ber);
                    644:  fail:
                    645:        ber_free_elements(ber);
                    646:        return (NULL);
                    647: }
                    648:
                    649: int
                    650: ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
                    651: {
                    652: #define _MAX_SEQ                128
                    653:        va_list                  ap;
                    654:        int                     *d, level = -1;
1.15      claudio   655:        unsigned int            *t;
1.8       rob       656:        long long               *i, l;
1.1       reyk      657:        void                    **ptr;
                    658:        size_t                  *len, ret = 0, n = strlen(fmt);
                    659:        char                    **s;
1.8       rob       660:        off_t                   *pos;
1.1       reyk      661:        struct ber_oid          *o;
                    662:        struct ber_element      *parent[_MAX_SEQ], **e;
                    663:
                    664:        memset(parent, 0, sizeof(struct ber_element *) * _MAX_SEQ);
                    665:
                    666:        va_start(ap, fmt);
                    667:        while (*fmt) {
                    668:                switch (*fmt++) {
                    669:                case 'B':
                    670:                        ptr = va_arg(ap, void **);
                    671:                        len = va_arg(ap, size_t *);
                    672:                        if (ber_get_bitstring(ber, ptr, len) == -1)
                    673:                                goto fail;
                    674:                        ret++;
                    675:                        break;
                    676:                case 'b':
                    677:                        d = va_arg(ap, int *);
                    678:                        if (ber_get_boolean(ber, d) == -1)
                    679:                                goto fail;
                    680:                        ret++;
                    681:                        break;
1.8       rob       682:                case 'd':
                    683:                        d = va_arg(ap, int *);
                    684:                        if (ber_get_integer(ber, &l) == -1)
                    685:                                goto fail;
                    686:                        *d = l;
                    687:                        ret++;
                    688:                        break;
1.1       reyk      689:                case 'e':
                    690:                        e = va_arg(ap, struct ber_element **);
                    691:                        *e = ber;
                    692:                        ret++;
                    693:                        continue;
                    694:                case 'E':
                    695:                        i = va_arg(ap, long long *);
                    696:                        if (ber_get_enumerated(ber, i) == -1)
                    697:                                goto fail;
                    698:                        ret++;
                    699:                        break;
                    700:                case 'i':
                    701:                        i = va_arg(ap, long long *);
                    702:                        if (ber_get_integer(ber, i) == -1)
                    703:                                goto fail;
                    704:                        ret++;
                    705:                        break;
                    706:                case 'o':
                    707:                        o = va_arg(ap, struct ber_oid *);
                    708:                        if (ber_get_oid(ber, o) == -1)
                    709:                                goto fail;
                    710:                        ret++;
                    711:                        break;
                    712:                case 'S':
                    713:                        ret++;
                    714:                        break;
                    715:                case 's':
                    716:                        s = va_arg(ap, char **);
                    717:                        if (ber_get_string(ber, s) == -1)
                    718:                                goto fail;
                    719:                        ret++;
                    720:                        break;
                    721:                case 't':
                    722:                        d = va_arg(ap, int *);
1.15      claudio   723:                        t = va_arg(ap, unsigned int *);
1.1       reyk      724:                        *d = ber->be_class;
                    725:                        *t = ber->be_type;
                    726:                        ret++;
                    727:                        continue;
                    728:                case 'x':
                    729:                        ptr = va_arg(ap, void **);
                    730:                        len = va_arg(ap, size_t *);
                    731:                        if (ber_get_nstring(ber, ptr, len) == -1)
                    732:                                goto fail;
                    733:                        ret++;
                    734:                        break;
                    735:                case '0':
                    736:                        if (ber->be_encoding != BER_TYPE_NULL)
                    737:                                goto fail;
                    738:                        ret++;
                    739:                        break;
                    740:                case '.':
                    741:                        if (ber->be_encoding != BER_TYPE_EOC)
                    742:                                goto fail;
                    743:                        ret++;
                    744:                        break;
1.8       rob       745:                case 'p':
                    746:                        pos = va_arg(ap, off_t *);
                    747:                        *pos = ber_getpos(ber);
                    748:                        ret++;
                    749:                        continue;
1.1       reyk      750:                case '{':
                    751:                case '(':
                    752:                        if (ber->be_encoding != BER_TYPE_SEQUENCE &&
                    753:                            ber->be_encoding != BER_TYPE_SET)
                    754:                                goto fail;
                    755:                        if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
                    756:                                goto fail;
                    757:                        parent[++level] = ber;
                    758:                        ber = ber->be_sub;
                    759:                        ret++;
                    760:                        continue;
                    761:                case '}':
                    762:                case ')':
                    763:                        if (parent[level] == NULL)
                    764:                                goto fail;
                    765:                        ber = parent[level--];
                    766:                        ret++;
1.5       rob       767:                        break;
1.1       reyk      768:                default:
                    769:                        goto fail;
                    770:                }
                    771:
                    772:                if (ber->be_next == NULL)
                    773:                        continue;
                    774:                ber = ber->be_next;
                    775:        }
                    776:        va_end(ap);
                    777:        return (ret == n ? 0 : -1);
                    778:
                    779:  fail:
                    780:        va_end(ap);
                    781:        return (-1);
                    782:
                    783: }
                    784:
1.17      rob       785: ssize_t
                    786: ber_get_writebuf(struct ber *b, void **buf)
                    787: {
                    788:        if (b->br_wbuf == NULL)
                    789:                return -1;
                    790:        *buf = b->br_wbuf;
                    791:        return (b->br_wend - b->br_wbuf);
                    792: }
                    793:
1.1       reyk      794: /*
1.14      rob       795:  * write ber elements to the write buffer
1.1       reyk      796:  *
                    797:  * params:
1.14      rob       798:  *     ber     holds the destination write buffer byte stream
1.1       reyk      799:  *     root    fully populated element tree
                    800:  *
                    801:  * returns:
1.10      rob       802:  *     >=0     number of bytes written
1.1       reyk      803:  *     -1      on failure and sets errno
                    804:  */
                    805: int
                    806: ber_write_elements(struct ber *ber, struct ber_element *root)
                    807: {
                    808:        size_t len;
                    809:
                    810:        /* calculate length because only the definite form is required */
                    811:        len = ber_calc_len(root);
                    812:        DPRINTF("write ber element of %zd bytes length\n", len);
                    813:
                    814:        if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
                    815:                free(ber->br_wbuf);
                    816:                ber->br_wbuf = NULL;
                    817:        }
                    818:        if (ber->br_wbuf == NULL) {
                    819:                if ((ber->br_wbuf = malloc(len)) == NULL)
                    820:                        return -1;
                    821:                ber->br_wend = ber->br_wbuf + len;
                    822:        }
                    823:
                    824:        /* reset write pointer */
                    825:        ber->br_wptr = ber->br_wbuf;
                    826:
                    827:        if (ber_dump_element(ber, root) == -1)
                    828:                return -1;
                    829:
                    830:        return (len);
                    831: }
                    832:
1.17      rob       833: void
                    834: ber_set_readbuf(struct ber *b, void *buf, size_t len)
                    835: {
                    836:        b->br_rbuf = b->br_rptr = buf;
                    837:        b->br_rend = (u_int8_t *)buf + len;
                    838: }
                    839:
1.1       reyk      840: /*
1.14      rob       841:  * read ber elements from the read buffer
1.1       reyk      842:  *
                    843:  * params:
1.14      rob       844:  *     ber     holds a fully populated read buffer byte stream
1.1       reyk      845:  *     root    if NULL, build up an element tree from what we receive on
                    846:  *             the wire. If not null, use the specified encoding for the
                    847:  *             elements received.
                    848:  *
                    849:  * returns:
                    850:  *     !=NULL, elements read and store in the ber_element tree
                    851:  *     NULL, type mismatch or read error
                    852:  */
                    853: struct ber_element *
                    854: ber_read_elements(struct ber *ber, struct ber_element *elm)
                    855: {
                    856:        struct ber_element *root = elm;
                    857:
                    858:        if (root == NULL) {
                    859:                if ((root = ber_get_element(0)) == NULL)
                    860:                        return NULL;
                    861:        }
                    862:
                    863:        DPRINTF("read ber elements, root %p\n", root);
                    864:
                    865:        if (ber_read_element(ber, root) == -1) {
                    866:                /* Cleanup if root was allocated by us */
                    867:                if (elm == NULL)
                    868:                        ber_free_elements(root);
                    869:                return NULL;
                    870:        }
                    871:
                    872:        return root;
                    873: }
                    874:
1.8       rob       875: off_t
                    876: ber_getpos(struct ber_element *elm)
                    877: {
                    878:        return elm->be_offs;
                    879: }
                    880:
1.1       reyk      881: void
1.5       rob       882: ber_free_element(struct ber_element *root)
                    883: {
                    884:        if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
                    885:            root->be_encoding == BER_TYPE_SET))
                    886:                ber_free_elements(root->be_sub);
                    887:        if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
                    888:            root->be_encoding == BER_TYPE_BITSTRING ||
                    889:            root->be_encoding == BER_TYPE_OBJECT))
                    890:                free(root->be_val);
                    891:        free(root);
                    892: }
                    893:
                    894: void
1.1       reyk      895: ber_free_elements(struct ber_element *root)
                    896: {
                    897:        if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
                    898:            root->be_encoding == BER_TYPE_SET))
                    899:                ber_free_elements(root->be_sub);
                    900:        if (root->be_next)
                    901:                ber_free_elements(root->be_next);
                    902:        if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
                    903:            root->be_encoding == BER_TYPE_BITSTRING ||
                    904:            root->be_encoding == BER_TYPE_OBJECT))
                    905:                free(root->be_val);
                    906:        free(root);
                    907: }
                    908:
                    909: size_t
                    910: ber_calc_len(struct ber_element *root)
                    911: {
1.15      claudio   912:        unsigned int t;
1.1       reyk      913:        size_t s;
                    914:        size_t size = 2;        /* minimum 1 byte head and 1 byte size */
                    915:
                    916:        /* calculate the real length of a sequence or set */
                    917:        if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
                    918:            root->be_encoding == BER_TYPE_SET))
                    919:                root->be_len = ber_calc_len(root->be_sub);
                    920:
                    921:        /* fix header length for extended types */
                    922:        if (root->be_type > BER_TYPE_SINGLE_MAX)
                    923:                for (t = root->be_type; t > 0; t >>= 7)
                    924:                        size++;
                    925:        if (root->be_len >= BER_TAG_MORE)
                    926:                for (s = root->be_len; s > 0; s >>= 8)
                    927:                        size++;
                    928:
                    929:        /* calculate the length of the following elements */
                    930:        if (root->be_next)
                    931:                size += ber_calc_len(root->be_next);
                    932:
                    933:        /* This is an empty element, do not use a minimal size */
1.2       rob       934:        if (root->be_class == BER_CLASS_UNIVERSAL &&
                    935:            root->be_type == BER_TYPE_EOC && root->be_len == 0)
1.1       reyk      936:                return (0);
                    937:
                    938:        return (root->be_len + size);
                    939: }
                    940:
1.17      rob       941: void
                    942: ber_set_application(struct ber *b, unsigned int (*cb)(struct ber_element *))
                    943: {
                    944:        b->br_application = cb;
                    945: }
                    946:
                    947: void
                    948: ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
                    949:     void *arg)
                    950: {
                    951:        elm->be_cb = cb;
                    952:        elm->be_cbarg = arg;
                    953: }
                    954:
                    955: void
                    956: ber_free(struct ber *b)
                    957: {
                    958:        free(b->br_wbuf);
                    959: }
                    960:
1.1       reyk      961: /*
                    962:  * internal functions
                    963:  */
                    964:
                    965: static int
                    966: ber_dump_element(struct ber *ber, struct ber_element *root)
                    967: {
                    968:        unsigned long long l;
                    969:        int i;
                    970:        uint8_t u;
                    971:
                    972:        ber_dump_header(ber, root);
1.8       rob       973:        if (root->be_cb)
                    974:                root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
1.1       reyk      975:
                    976:        switch (root->be_encoding) {
                    977:        case BER_TYPE_BOOLEAN:
                    978:        case BER_TYPE_INTEGER:
                    979:        case BER_TYPE_ENUMERATED:
                    980:                l = (unsigned long long)root->be_numeric;
                    981:                for (i = root->be_len; i > 0; i--) {
                    982:                        u = (l >> ((i - 1) * 8)) & 0xff;
                    983:                        ber_putc(ber, u);
                    984:                }
                    985:                break;
                    986:        case BER_TYPE_BITSTRING:
                    987:                return -1;
                    988:        case BER_TYPE_OCTETSTRING:
                    989:        case BER_TYPE_OBJECT:
                    990:                ber_write(ber, root->be_val, root->be_len);
                    991:                break;
                    992:        case BER_TYPE_NULL:     /* no payload */
                    993:        case BER_TYPE_EOC:
                    994:                break;
                    995:        case BER_TYPE_SEQUENCE:
                    996:        case BER_TYPE_SET:
                    997:                if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
                    998:                        return -1;
                    999:                break;
                   1000:        }
                   1001:
                   1002:        if (root->be_next == NULL)
                   1003:                return 0;
                   1004:        return ber_dump_element(ber, root->be_next);
                   1005: }
                   1006:
                   1007: static void
                   1008: ber_dump_header(struct ber *ber, struct ber_element *root)
                   1009: {
1.15      claudio  1010:        u_char  id = 0, t, buf[5];
                   1011:        unsigned int type;
1.1       reyk     1012:        size_t size;
                   1013:
                   1014:        /* class universal, type encoding depending on type value */
                   1015:        /* length encoding */
                   1016:        if (root->be_type <= BER_TYPE_SINGLE_MAX) {
                   1017:                id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
                   1018:                if (root->be_encoding == BER_TYPE_SEQUENCE ||
                   1019:                    root->be_encoding == BER_TYPE_SET)
                   1020:                        id |= BER_TYPE_CONSTRUCTED;
                   1021:
                   1022:                ber_putc(ber, id);
                   1023:        } else {
                   1024:                id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
                   1025:                if (root->be_encoding == BER_TYPE_SEQUENCE ||
                   1026:                    root->be_encoding == BER_TYPE_SET)
                   1027:                        id |= BER_TYPE_CONSTRUCTED;
                   1028:
                   1029:                ber_putc(ber, id);
                   1030:
                   1031:                for (t = 0, type = root->be_type; type > 0; type >>= 7)
                   1032:                        buf[t++] = type & ~BER_TAG_MORE;
                   1033:
                   1034:                while (t-- > 0) {
                   1035:                        if (t > 0)
                   1036:                                buf[t] |= BER_TAG_MORE;
                   1037:                        ber_putc(ber, buf[t]);
                   1038:                }
                   1039:        }
                   1040:
                   1041:        if (root->be_len < BER_TAG_MORE) {
                   1042:                /* short form */
                   1043:                ber_putc(ber, root->be_len);
                   1044:        } else {
                   1045:                for (t = 0, size = root->be_len; size > 0; size >>= 8)
                   1046:                        buf[t++] = size & 0xff;
                   1047:
                   1048:                ber_putc(ber, t | BER_TAG_MORE);
                   1049:
                   1050:                while (t > 0)
                   1051:                        ber_putc(ber, buf[--t]);
                   1052:        }
                   1053: }
                   1054:
                   1055: static void
                   1056: ber_putc(struct ber *ber, u_char c)
                   1057: {
                   1058:        if (ber->br_wptr + 1 <= ber->br_wend)
                   1059:                *ber->br_wptr = c;
                   1060:        ber->br_wptr++;
                   1061: }
                   1062:
                   1063: static void
                   1064: ber_write(struct ber *ber, void *buf, size_t len)
                   1065: {
                   1066:        if (ber->br_wptr + len <= ber->br_wend)
                   1067:                bcopy(buf, ber->br_wptr, len);
                   1068:        ber->br_wptr += len;
                   1069: }
                   1070:
                   1071: /*
                   1072:  * extract a BER encoded tag. There are two types, a short and long form.
                   1073:  */
                   1074: static ssize_t
1.15      claudio  1075: get_id(struct ber *b, unsigned int *tag, int *class, int *cstruct)
1.1       reyk     1076: {
                   1077:        u_char u;
                   1078:        size_t i = 0;
1.15      claudio  1079:        unsigned int t = 0;
1.1       reyk     1080:
                   1081:        if (ber_getc(b, &u) == -1)
                   1082:                return -1;
                   1083:
                   1084:        *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
                   1085:        *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
                   1086:
                   1087:        if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
                   1088:                *tag = u & BER_TAG_MASK;
                   1089:                return 1;
                   1090:        }
                   1091:
                   1092:        do {
                   1093:                if (ber_getc(b, &u) == -1)
                   1094:                        return -1;
                   1095:                t = (t << 7) | (u & ~BER_TAG_MORE);
                   1096:                i++;
1.15      claudio  1097:                if (i > sizeof(unsigned int)) {
1.13      rob      1098:                        errno = ERANGE;
                   1099:                        return -1;
                   1100:                }
1.1       reyk     1101:        } while (u & BER_TAG_MORE);
                   1102:
                   1103:        *tag = t;
                   1104:        return i + 1;
                   1105: }
                   1106:
                   1107: /*
                   1108:  * extract length of a ber object -- if length is unknown an error is returned.
                   1109:  */
                   1110: static ssize_t
                   1111: get_len(struct ber *b, ssize_t *len)
                   1112: {
                   1113:        u_char  u, n;
                   1114:        ssize_t s, r;
                   1115:
                   1116:        if (ber_getc(b, &u) == -1)
                   1117:                return -1;
                   1118:        if ((u & BER_TAG_MORE) == 0) {
                   1119:                /* short form */
                   1120:                *len = u;
                   1121:                return 1;
                   1122:        }
                   1123:
1.5       rob      1124:        if (u == 0x80) {
                   1125:                /* Indefinite length not supported. */
                   1126:                errno = EINVAL;
                   1127:                return -1;
                   1128:        }
                   1129:
1.1       reyk     1130:        n = u & ~BER_TAG_MORE;
                   1131:        if (sizeof(ssize_t) < n) {
                   1132:                errno = ERANGE;
                   1133:                return -1;
                   1134:        }
                   1135:        r = n + 1;
                   1136:
                   1137:        for (s = 0; n > 0; n--) {
                   1138:                if (ber_getc(b, &u) == -1)
                   1139:                        return -1;
                   1140:                s = (s << 8) | u;
                   1141:        }
                   1142:
                   1143:        if (s < 0) {
                   1144:                /* overflow */
                   1145:                errno = ERANGE;
                   1146:                return -1;
                   1147:        }
                   1148:
                   1149:        *len = s;
                   1150:        return r;
                   1151: }
                   1152:
                   1153: static ssize_t
                   1154: ber_read_element(struct ber *ber, struct ber_element *elm)
                   1155: {
                   1156:        long long val = 0;
                   1157:        struct ber_element *next;
1.15      claudio  1158:        unsigned int type;
1.18    ! rob      1159:        int i, class, cstruct, elements = 0;
1.1       reyk     1160:        ssize_t len, r, totlen = 0;
                   1161:        u_char c;
                   1162:
                   1163:        if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
                   1164:                return -1;
1.16      rob      1165:        DPRINTF("ber read got class %d type %u, %s\n",
1.7       rob      1166:            class, type, cstruct ? "constructed" : "primitive");
1.1       reyk     1167:        totlen += r;
                   1168:        if ((r = get_len(ber, &len)) == -1)
                   1169:                return -1;
                   1170:        DPRINTF("ber read element size %zd\n", len);
                   1171:        totlen += r + len;
                   1172:
1.4       rob      1173:        /* If the total size of the element is larger than the buffer
                   1174:         * don't bother to continue. */
1.1       reyk     1175:        if (len > ber->br_rend - ber->br_rptr) {
                   1176:                errno = ECANCELED;
                   1177:                return -1;
                   1178:        }
                   1179:
                   1180:        elm->be_type = type;
                   1181:        elm->be_len = len;
1.8       rob      1182:        elm->be_offs = ber->br_offs;    /* element position within stream */
1.1       reyk     1183:        elm->be_class = class;
                   1184:
                   1185:        if (elm->be_encoding == 0) {
                   1186:                /* try to figure out the encoding via class, type and cstruct */
                   1187:                if (cstruct)
                   1188:                        elm->be_encoding = BER_TYPE_SEQUENCE;
                   1189:                else if (class == BER_CLASS_UNIVERSAL)
                   1190:                        elm->be_encoding = type;
                   1191:                else if (ber->br_application != NULL) {
                   1192:                        /*
                   1193:                         * Ask the application to map the encoding to a
                   1194:                         * universal type. For example, a SMI IpAddress
                   1195:                         * type is defined as 4 byte OCTET STRING.
                   1196:                         */
                   1197:                        elm->be_encoding = (*ber->br_application)(elm);
                   1198:                } else
                   1199:                        /* last resort option */
                   1200:                        elm->be_encoding = BER_TYPE_NULL;
                   1201:        }
                   1202:
                   1203:        switch (elm->be_encoding) {
                   1204:        case BER_TYPE_EOC:      /* End-Of-Content */
                   1205:                break;
                   1206:        case BER_TYPE_BOOLEAN:
                   1207:        case BER_TYPE_INTEGER:
                   1208:        case BER_TYPE_ENUMERATED:
                   1209:                if (len > (ssize_t)sizeof(long long))
                   1210:                        return -1;
                   1211:                for (i = 0; i < len; i++) {
                   1212:                        if (ber_getc(ber, &c) != 1)
                   1213:                                return -1;
                   1214:                        val <<= 8;
                   1215:                        val |= c;
                   1216:                }
                   1217:
                   1218:                /* sign extend if MSB is set */
                   1219:                if (val >> ((i - 1) * 8) & 0x80)
                   1220:                        val |= ULLONG_MAX << (i * 8);
                   1221:                elm->be_numeric = val;
                   1222:                break;
                   1223:        case BER_TYPE_BITSTRING:
                   1224:                elm->be_val = malloc(len);
                   1225:                if (elm->be_val == NULL)
                   1226:                        return -1;
                   1227:                elm->be_free = 1;
                   1228:                elm->be_len = len;
                   1229:                ber_read(ber, elm->be_val, len);
                   1230:                break;
                   1231:        case BER_TYPE_OCTETSTRING:
                   1232:        case BER_TYPE_OBJECT:
                   1233:                elm->be_val = malloc(len + 1);
                   1234:                if (elm->be_val == NULL)
                   1235:                        return -1;
                   1236:                elm->be_free = 1;
                   1237:                elm->be_len = len;
                   1238:                ber_read(ber, elm->be_val, len);
                   1239:                ((u_char *)elm->be_val)[len] = '\0';
                   1240:                break;
                   1241:        case BER_TYPE_NULL:     /* no payload */
                   1242:                if (len != 0)
                   1243:                        return -1;
                   1244:                break;
                   1245:        case BER_TYPE_SEQUENCE:
                   1246:        case BER_TYPE_SET:
                   1247:                if (elm->be_sub == NULL) {
                   1248:                        if ((elm->be_sub = ber_get_element(0)) == NULL)
                   1249:                                return -1;
                   1250:                }
                   1251:                next = elm->be_sub;
                   1252:                while (len > 0) {
1.18    ! rob      1253:                        /*
        !          1254:                         * Prevent stack overflow from excessive recursion
        !          1255:                         * depth in ber_free_elements().
        !          1256:                         */
        !          1257:                        if (elements >= BER_MAX_SEQ_ELEMENTS) {
        !          1258:                                errno = ERANGE;
        !          1259:                                return -1;
        !          1260:                        }
1.1       reyk     1261:                        r = ber_read_element(ber, next);
                   1262:                        if (r == -1)
                   1263:                                return -1;
1.18    ! rob      1264:                        elements++;
1.1       reyk     1265:                        len -= r;
                   1266:                        if (len > 0 && next->be_next == NULL) {
                   1267:                                if ((next->be_next = ber_get_element(0)) ==
                   1268:                                    NULL)
                   1269:                                        return -1;
                   1270:                        }
                   1271:                        next = next->be_next;
                   1272:                }
                   1273:                break;
                   1274:        }
                   1275:        return totlen;
                   1276: }
                   1277:
                   1278: static ssize_t
                   1279: ber_getc(struct ber *b, u_char *c)
                   1280: {
1.12      jca      1281:        return ber_read(b, c, 1);
1.1       reyk     1282: }
                   1283:
                   1284: static ssize_t
                   1285: ber_read(struct ber *ber, void *buf, size_t len)
                   1286: {
1.12      jca      1287:        size_t  sz;
                   1288:
                   1289:        if (ber->br_rbuf == NULL)
                   1290:                return -1;
1.1       reyk     1291:
1.12      jca      1292:        sz = ber->br_rend - ber->br_rptr;
                   1293:        if (len > sz) {
                   1294:                errno = ECANCELED;
                   1295:                return -1;      /* parser wants more data than available */
1.1       reyk     1296:        }
1.12      jca      1297:
                   1298:        bcopy(ber->br_rptr, buf, len);
                   1299:        ber->br_rptr += len;
                   1300:        ber->br_offs += len;
                   1301:
                   1302:        return len;
1.1       reyk     1303: }