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