GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/snmpd/ber.c Lines: 11 566 1.9 %
Date: 2017-11-07 Branches: 7 494 1.4 %

Line Branch Exec Source
1
/*	$OpenBSD: ber.c,v 1.31 2016/03/05 03:31:36 deraadt Exp $ */
2
3
/*
4
 * Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
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
272
	if ((string = calloc(1, len + 1)) == NULL)
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
24
	char			*sp, *p, str[BUFSIZ];
419
12
	const char		*errstr;
420
421
12
	if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
422
		return (-1);
423
12
	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
200
	for (p = sp = str; p != NULL; sp = p) {
427
88
		if ((p = strpbrk(p, "._-")) != NULL)
428
76
			*p++ = '\0';
429
88
		o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
430

176
		if (errstr || o->bo_n > BER_MAX_OID_LEN)
431
			return (-1);
432
	}
433
434
12
	return (0);
435
12
}
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, l;
635
	void			**ptr;
636
	size_t			*len, ret = 0, n = strlen(fmt);
637
	char			**s;
638
	off_t			*pos;
639
	struct ber_oid		*o;
640
	struct ber_element	*parent[_MAX_SEQ], **e;
641
642
	memset(parent, 0, 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 'd':
661
			d = va_arg(ap, int *);
662
			if (ber_get_integer(ber, &l) == -1)
663
				goto fail;
664
			*d = l;
665
			ret++;
666
			break;
667
		case 'e':
668
			e = va_arg(ap, struct ber_element **);
669
			*e = ber;
670
			ret++;
671
			continue;
672
		case 'E':
673
			i = va_arg(ap, long long *);
674
			if (ber_get_enumerated(ber, i) == -1)
675
				goto fail;
676
			ret++;
677
			break;
678
		case 'i':
679
			i = va_arg(ap, long long *);
680
			if (ber_get_integer(ber, i) == -1)
681
				goto fail;
682
			ret++;
683
			break;
684
		case 'o':
685
			o = va_arg(ap, struct ber_oid *);
686
			if (ber_get_oid(ber, o) == -1)
687
				goto fail;
688
			ret++;
689
			break;
690
		case 'S':
691
			ret++;
692
			break;
693
		case 's':
694
			s = va_arg(ap, char **);
695
			if (ber_get_string(ber, s) == -1)
696
				goto fail;
697
			ret++;
698
			break;
699
		case 't':
700
			d = va_arg(ap, int *);
701
			t = va_arg(ap, unsigned long *);
702
			*d = ber->be_class;
703
			*t = ber->be_type;
704
			ret++;
705
			continue;
706
		case 'x':
707
			ptr = va_arg(ap, void **);
708
			len = va_arg(ap, size_t *);
709
			if (ber_get_nstring(ber, ptr, len) == -1)
710
				goto fail;
711
			ret++;
712
			break;
713
		case '0':
714
			if (ber->be_encoding != BER_TYPE_NULL)
715
				goto fail;
716
			ret++;
717
			break;
718
		case '.':
719
			if (ber->be_encoding != BER_TYPE_EOC)
720
				goto fail;
721
			ret++;
722
			break;
723
		case 'p':
724
			pos = va_arg(ap, off_t *);
725
			*pos = ber_getpos(ber);
726
			ret++;
727
			continue;
728
		case '{':
729
		case '(':
730
			if (ber->be_encoding != BER_TYPE_SEQUENCE &&
731
			    ber->be_encoding != BER_TYPE_SET)
732
				goto fail;
733
			if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
734
				goto fail;
735
			parent[++level] = ber;
736
			ber = ber->be_sub;
737
			ret++;
738
			continue;
739
		case '}':
740
		case ')':
741
			if (parent[level] == NULL)
742
				goto fail;
743
			ber = parent[level--];
744
			ret++;
745
			break;
746
		default:
747
			goto fail;
748
		}
749
750
		if (ber->be_next == NULL)
751
			continue;
752
		ber = ber->be_next;
753
	}
754
	va_end(ap);
755
	return (ret == n ? 0 : -1);
756
757
 fail:
758
	va_end(ap);
759
	return (-1);
760
761
}
762
763
/*
764
 * write ber elements to the socket
765
 *
766
 * params:
767
 *	ber	holds the socket
768
 *	root	fully populated element tree
769
 *
770
 * returns:
771
 *      >=0     number of bytes written
772
 *	-1	on failure and sets errno
773
 */
774
int
775
ber_write_elements(struct ber *ber, struct ber_element *root)
776
{
777
	size_t len;
778
779
	/* calculate length because only the definite form is required */
780
	len = ber_calc_len(root);
781
	DPRINTF("write ber element of %zd bytes length\n", len);
782
783
	if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
784
		free(ber->br_wbuf);
785
		ber->br_wbuf = NULL;
786
	}
787
	if (ber->br_wbuf == NULL) {
788
		if ((ber->br_wbuf = malloc(len)) == NULL)
789
			return -1;
790
		ber->br_wend = ber->br_wbuf + len;
791
	}
792
793
	/* reset write pointer */
794
	ber->br_wptr = ber->br_wbuf;
795
796
	if (ber_dump_element(ber, root) == -1)
797
		return -1;
798
799
	/* XXX this should be moved to a different function */
800
	if (ber->fd != -1)
801
		return write(ber->fd, ber->br_wbuf, len);
802
803
	return (len);
804
}
805
806
/*
807
 * read ber elements from the socket
808
 *
809
 * params:
810
 *	ber	holds the socket and lot more
811
 *	root	if NULL, build up an element tree from what we receive on
812
 *		the wire. If not null, use the specified encoding for the
813
 *		elements received.
814
 *
815
 * returns:
816
 *	!=NULL, elements read and store in the ber_element tree
817
 *	NULL, type mismatch or read error
818
 */
819
struct ber_element *
820
ber_read_elements(struct ber *ber, struct ber_element *elm)
821
{
822
	struct ber_element *root = elm;
823
824
	if (root == NULL) {
825
		if ((root = ber_get_element(0)) == NULL)
826
			return NULL;
827
	}
828
829
	DPRINTF("read ber elements, root %p\n", root);
830
831
	if (ber_read_element(ber, root) == -1) {
832
		/* Cleanup if root was allocated by us */
833
		if (elm == NULL)
834
			ber_free_elements(root);
835
		return NULL;
836
	}
837
838
	return root;
839
}
840
841
off_t
842
ber_getpos(struct ber_element *elm)
843
{
844
	return elm->be_offs;
845
}
846
847
void
848
ber_free_elements(struct ber_element *root)
849
{
850
	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
851
	    root->be_encoding == BER_TYPE_SET))
852
		ber_free_elements(root->be_sub);
853
	if (root->be_next)
854
		ber_free_elements(root->be_next);
855
	if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
856
	    root->be_encoding == BER_TYPE_BITSTRING ||
857
	    root->be_encoding == BER_TYPE_OBJECT))
858
		free(root->be_val);
859
	free(root);
860
}
861
862
size_t
863
ber_calc_len(struct ber_element *root)
864
{
865
	unsigned long t;
866
	size_t s;
867
	size_t size = 2;	/* minimum 1 byte head and 1 byte size */
868
869
	/* calculate the real length of a sequence or set */
870
	if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
871
	    root->be_encoding == BER_TYPE_SET))
872
		root->be_len = ber_calc_len(root->be_sub);
873
874
	/* fix header length for extended types */
875
	if (root->be_type > BER_TYPE_SINGLE_MAX)
876
		for (t = root->be_type; t > 0; t >>= 7)
877
			size++;
878
	if (root->be_len >= BER_TAG_MORE)
879
		for (s = root->be_len; s > 0; s >>= 8)
880
			size++;
881
882
	/* calculate the length of the following elements */
883
	if (root->be_next)
884
		size += ber_calc_len(root->be_next);
885
886
	/* This is an empty element, do not use a minimal size */
887
	if (root->be_class != BER_CLASS_CONTEXT &&
888
	    root->be_type == BER_TYPE_EOC && root->be_len == 0)
889
		return (0);
890
891
	return (root->be_len + size);
892
}
893
894
/*
895
 * internal functions
896
 */
897
898
static int
899
ber_dump_element(struct ber *ber, struct ber_element *root)
900
{
901
	unsigned long long l;
902
	int i;
903
	uint8_t u;
904
905
	ber_dump_header(ber, root);
906
	if (root->be_cb)
907
		root->be_cb(root->be_cbarg, ber->br_wptr - ber->br_wbuf);
908
909
	switch (root->be_encoding) {
910
	case BER_TYPE_BOOLEAN:
911
	case BER_TYPE_INTEGER:
912
	case BER_TYPE_ENUMERATED:
913
		l = (unsigned long long)root->be_numeric;
914
		for (i = root->be_len; i > 0; i--) {
915
			u = (l >> ((i - 1) * 8)) & 0xff;
916
			ber_putc(ber, u);
917
		}
918
		break;
919
	case BER_TYPE_BITSTRING:
920
		return -1;
921
	case BER_TYPE_OCTETSTRING:
922
	case BER_TYPE_OBJECT:
923
		ber_write(ber, root->be_val, root->be_len);
924
		break;
925
	case BER_TYPE_NULL:	/* no payload */
926
	case BER_TYPE_EOC:
927
		break;
928
	case BER_TYPE_SEQUENCE:
929
	case BER_TYPE_SET:
930
		if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
931
			return -1;
932
		break;
933
	}
934
935
	if (root->be_next == NULL)
936
		return 0;
937
	return ber_dump_element(ber, root->be_next);
938
}
939
940
static void
941
ber_dump_header(struct ber *ber, struct ber_element *root)
942
{
943
	u_char	id = 0, t, buf[8];
944
	unsigned long type;
945
	size_t size;
946
947
	/* class universal, type encoding depending on type value */
948
	/* length encoding */
949
	if (root->be_type <= BER_TYPE_SINGLE_MAX) {
950
		id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
951
		if (root->be_encoding == BER_TYPE_SEQUENCE ||
952
		    root->be_encoding == BER_TYPE_SET)
953
			id |= BER_TYPE_CONSTRUCTED;
954
955
		ber_putc(ber, id);
956
	} else {
957
		id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
958
		if (root->be_encoding == BER_TYPE_SEQUENCE ||
959
		    root->be_encoding == BER_TYPE_SET)
960
			id |= BER_TYPE_CONSTRUCTED;
961
962
		ber_putc(ber, id);
963
964
		for (t = 0, type = root->be_type; type > 0; type >>= 7)
965
			buf[t++] = type & ~BER_TAG_MORE;
966
967
		while (t-- > 0) {
968
			if (t > 0)
969
				buf[t] |= BER_TAG_MORE;
970
			ber_putc(ber, buf[t]);
971
		}
972
	}
973
974
	if (root->be_len < BER_TAG_MORE) {
975
		/* short form */
976
		ber_putc(ber, root->be_len);
977
	} else {
978
		for (t = 0, size = root->be_len; size > 0; size >>= 8)
979
			buf[t++] = size & 0xff;
980
981
		ber_putc(ber, t | BER_TAG_MORE);
982
983
		while (t > 0)
984
			ber_putc(ber, buf[--t]);
985
	}
986
}
987
988
static void
989
ber_putc(struct ber *ber, u_char c)
990
{
991
	if (ber->br_wptr + 1 <= ber->br_wend)
992
		*ber->br_wptr = c;
993
	ber->br_wptr++;
994
}
995
996
static void
997
ber_write(struct ber *ber, void *buf, size_t len)
998
{
999
	if (ber->br_wptr + len <= ber->br_wend)
1000
		bcopy(buf, ber->br_wptr, len);
1001
	ber->br_wptr += len;
1002
}
1003
1004
/*
1005
 * extract a BER encoded tag. There are two types, a short and long form.
1006
 */
1007
static ssize_t
1008
get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
1009
{
1010
	u_char u;
1011
	size_t i = 0;
1012
	unsigned long t = 0;
1013
1014
	if (ber_getc(b, &u) == -1)
1015
		return -1;
1016
1017
	*class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
1018
	*cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
1019
1020
	if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
1021
		*tag = u & BER_TAG_MASK;
1022
		return 1;
1023
	}
1024
1025
	do {
1026
		if (ber_getc(b, &u) == -1)
1027
			return -1;
1028
		t = (t << 7) | (u & ~BER_TAG_MORE);
1029
		i++;
1030
	} while (u & BER_TAG_MORE);
1031
1032
	if (i > sizeof(unsigned long)) {
1033
		errno = ERANGE;
1034
		return -1;
1035
	}
1036
1037
	*tag = t;
1038
	return i + 1;
1039
}
1040
1041
/*
1042
 * extract length of a ber object -- if length is unknown an error is returned.
1043
 */
1044
static ssize_t
1045
get_len(struct ber *b, ssize_t *len)
1046
{
1047
	u_char	u, n;
1048
	ssize_t	s, r;
1049
1050
	if (ber_getc(b, &u) == -1)
1051
		return -1;
1052
	if ((u & BER_TAG_MORE) == 0) {
1053
		/* short form */
1054
		*len = u;
1055
		return 1;
1056
	}
1057
1058
	if (u == 0x80) {
1059
		/* Indefinite length not supported. */
1060
		errno = EINVAL;
1061
		return -1;
1062
	}
1063
1064
	n = u & ~BER_TAG_MORE;
1065
	if (sizeof(ssize_t) < n) {
1066
		errno = ERANGE;
1067
		return -1;
1068
	}
1069
	r = n + 1;
1070
1071
	for (s = 0; n > 0; n--) {
1072
		if (ber_getc(b, &u) == -1)
1073
			return -1;
1074
		s = (s << 8) | u;
1075
	}
1076
1077
	if (s < 0) {
1078
		/* overflow */
1079
		errno = ERANGE;
1080
		return -1;
1081
	}
1082
1083
	*len = s;
1084
	return r;
1085
}
1086
1087
static ssize_t
1088
ber_read_element(struct ber *ber, struct ber_element *elm)
1089
{
1090
	long long val = 0;
1091
	struct ber_element *next;
1092
	unsigned long type;
1093
	int i, class, cstruct;
1094
	ssize_t len, r, totlen = 0;
1095
	u_char c;
1096
1097
	if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
1098
		return -1;
1099
	DPRINTF("ber read got class %d type %lu, %s\n",
1100
	    class, type, cstruct ? "constructive" : "primitive");
1101
	totlen += r;
1102
	if ((r = get_len(ber, &len)) == -1)
1103
		return -1;
1104
	DPRINTF("ber read element size %zd\n", len);
1105
	totlen += r + len;
1106
1107
	/* If using an external buffer and the total size of the element
1108
	 * is larger then the external buffer don't bother to continue. */
1109
	if (ber->fd == -1 && len > ber->br_rend - ber->br_rptr) {
1110
		errno = ECANCELED;
1111
		return -1;
1112
	}
1113
1114
	elm->be_type = type;
1115
	elm->be_len = len;
1116
	elm->be_offs = ber->br_offs;	/* element position within stream */
1117
	elm->be_class = class;
1118
1119
	if (elm->be_encoding == 0) {
1120
		/* try to figure out the encoding via class, type and cstruct */
1121
		if (cstruct)
1122
			elm->be_encoding = BER_TYPE_SEQUENCE;
1123
		else if (class == BER_CLASS_UNIVERSAL)
1124
			elm->be_encoding = type;
1125
		else if (ber->br_application != NULL) {
1126
			/*
1127
			 * Ask the application to map the encoding to a
1128
			 * universal type. For example, a SMI IpAddress
1129
			 * type is defined as 4 byte OCTET STRING.
1130
			 */
1131
			elm->be_encoding = (*ber->br_application)(elm);
1132
		} else
1133
			/* last resort option */
1134
			elm->be_encoding = BER_TYPE_NULL;
1135
	}
1136
1137
	switch (elm->be_encoding) {
1138
	case BER_TYPE_EOC:	/* End-Of-Content */
1139
		break;
1140
	case BER_TYPE_BOOLEAN:
1141
	case BER_TYPE_INTEGER:
1142
	case BER_TYPE_ENUMERATED:
1143
		if (len > (ssize_t)sizeof(long long))
1144
			return -1;
1145
		for (i = 0; i < len; i++) {
1146
			if (ber_getc(ber, &c) != 1)
1147
				return -1;
1148
			val <<= 8;
1149
			val |= c;
1150
		}
1151
1152
		/* sign extend if MSB is set */
1153
		if (val >> ((i - 1) * 8) & 0x80)
1154
			val |= ULLONG_MAX << (i * 8);
1155
		elm->be_numeric = val;
1156
		break;
1157
	case BER_TYPE_BITSTRING:
1158
		elm->be_val = malloc(len);
1159
		if (elm->be_val == NULL)
1160
			return -1;
1161
		elm->be_free = 1;
1162
		elm->be_len = len;
1163
		ber_read(ber, elm->be_val, len);
1164
		break;
1165
	case BER_TYPE_OCTETSTRING:
1166
	case BER_TYPE_OBJECT:
1167
		elm->be_val = malloc(len + 1);
1168
		if (elm->be_val == NULL)
1169
			return -1;
1170
		elm->be_free = 1;
1171
		elm->be_len = len;
1172
		ber_read(ber, elm->be_val, len);
1173
		((u_char *)elm->be_val)[len] = '\0';
1174
		break;
1175
	case BER_TYPE_NULL:	/* no payload */
1176
		if (len != 0)
1177
			return -1;
1178
		break;
1179
	case BER_TYPE_SEQUENCE:
1180
	case BER_TYPE_SET:
1181
		if (elm->be_sub == NULL) {
1182
			if ((elm->be_sub = ber_get_element(0)) == NULL)
1183
				return -1;
1184
		}
1185
		next = elm->be_sub;
1186
		while (len > 0) {
1187
			r = ber_read_element(ber, next);
1188
			if (r == -1)
1189
				return -1;
1190
			len -= r;
1191
			if (len > 0 && next->be_next == NULL) {
1192
				if ((next->be_next = ber_get_element(0)) ==
1193
				    NULL)
1194
					return -1;
1195
			}
1196
			next = next->be_next;
1197
		}
1198
		break;
1199
	}
1200
	return totlen;
1201
}
1202
1203
static ssize_t
1204
ber_readbuf(struct ber *b, void *buf, size_t nbytes)
1205
{
1206
	size_t	 sz;
1207
	size_t	 len;
1208
1209
	if (b->br_rbuf == NULL)
1210
		return -1;
1211
1212
	sz = b->br_rend - b->br_rptr;
1213
	len = MINIMUM(nbytes, sz);
1214
	if (len == 0) {
1215
		errno = ECANCELED;
1216
		return (-1);	/* end of buffer and parser wants more data */
1217
	}
1218
1219
	bcopy(b->br_rptr, buf, len);
1220
	b->br_rptr += len;
1221
1222
	return (len);
1223
}
1224
1225
void
1226
ber_set_readbuf(struct ber *b, void *buf, size_t len)
1227
{
1228
	b->br_rbuf = b->br_rptr = buf;
1229
	b->br_rend = (u_int8_t *)buf + len;
1230
}
1231
1232
ssize_t
1233
ber_get_writebuf(struct ber *b, void **buf)
1234
{
1235
	if (b->br_wbuf == NULL)
1236
		return -1;
1237
	*buf = b->br_wbuf;
1238
	return (b->br_wend - b->br_wbuf);
1239
}
1240
1241
void
1242
ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
1243
{
1244
	b->br_application = cb;
1245
}
1246
1247
void
1248
ber_set_writecallback(struct ber_element *elm, void (*cb)(void *, size_t),
1249
    void *arg)
1250
{
1251
	elm->be_cb = cb;
1252
	elm->be_cbarg = arg;
1253
}
1254
1255
1256
void
1257
ber_free(struct ber *b)
1258
{
1259
	free(b->br_wbuf);
1260
}
1261
1262
static ssize_t
1263
ber_getc(struct ber *b, u_char *c)
1264
{
1265
	return ber_read(b, c, 1);
1266
}
1267
1268
static ssize_t
1269
ber_read(struct ber *ber, void *buf, size_t len)
1270
{
1271
	u_char *b = buf;
1272
	ssize_t	r, remain = len;
1273
1274
	/*
1275
	 * XXX calling read here is wrong in many ways. The most obvious one
1276
	 * being that we will block till data arrives.
1277
	 * But for now it is _good enough_ *gulp*
1278
	 */
1279
1280
	while (remain > 0) {
1281
		if (ber->fd == -1)
1282
			r = ber_readbuf(ber, b, remain);
1283
		else
1284
			r = read(ber->fd, b, remain);
1285
		if (r == -1) {
1286
			if (errno == EINTR || errno == EAGAIN)
1287
				continue;
1288
			return -1;
1289
		}
1290
		if (r == 0)
1291
			return (b - (u_char *)buf);
1292
		b += r;
1293
		remain -= r;
1294
	}
1295
	r = b - (u_char *)buf;
1296
	ber->br_offs += r;
1297
	return r;
1298
}
1299
1300
int
1301
ber_oid_cmp(struct ber_oid *a, struct ber_oid *b)
1302
{
1303
	size_t	 i;
1304
	for (i = 0; i < BER_MAX_OID_LEN; i++) {
1305
		if (a->bo_id[i] != 0) {
1306
			if (a->bo_id[i] == b->bo_id[i])
1307
				continue;
1308
			else if (a->bo_id[i] < b->bo_id[i]) {
1309
				/* b is a successor of a */
1310
				return (1);
1311
			} else {
1312
				/* b is a predecessor of a */
1313
				return (-1);
1314
			}
1315
		} else if (b->bo_id[i] != 0) {
1316
			/* b is larger, but a child of a */
1317
			return (2);
1318
		} else
1319
			break;
1320
	}
1321
1322
	/* b and a are identical */
1323
	return (0);
1324
}