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

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