xref: /openbsd-src/regress/lib/libutil/ber/ber_test.c (revision 696b58997f75587bd78112ed0b6cdec94a718911)
1*696b5899Stb /* $OpenBSD: ber_test.c,v 1.20 2019/10/24 12:39:26 tb Exp $
26a0724fcSrob */
36a0724fcSrob /*
46a0724fcSrob  * Copyright (c) Rob Pierce <rob@openbsd.org>
56a0724fcSrob  *
66a0724fcSrob  * Permission to use, copy, modify, and distribute this software for any
76a0724fcSrob  * purpose with or without fee is hereby granted, provided that the above
86a0724fcSrob  * copyright notice and this permission notice appear in all copies.
96a0724fcSrob  *
106a0724fcSrob  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
116a0724fcSrob  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
126a0724fcSrob  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
136a0724fcSrob  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
146a0724fcSrob  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
156a0724fcSrob  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
166a0724fcSrob  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
176a0724fcSrob  */
186a0724fcSrob 
196a0724fcSrob #include <sys/types.h>
206a0724fcSrob 
216a0724fcSrob #include <ber.h>
226a0724fcSrob #include <errno.h>
236a0724fcSrob #include <stdio.h>
246a0724fcSrob #include <string.h>
256a0724fcSrob 
266a0724fcSrob #define SUCCEED	0
276a0724fcSrob #define FAIL	1
286a0724fcSrob 
296a0724fcSrob struct test_vector {
3036a71bf8Srob 	int		 fail;		/* 1 means test is expected to fail */
3136a71bf8Srob 	int		 memcheck;	/* 1 when short forms used */
326a0724fcSrob 	char		 title[128];
336a0724fcSrob 	size_t		 length;
346a0724fcSrob 	unsigned char	 input[1024];
356a0724fcSrob };
366a0724fcSrob 
376a0724fcSrob struct test_vector test_vectors[] = {
386a0724fcSrob 	{
396a0724fcSrob 		SUCCEED,
4036a71bf8Srob 		1,
416a0724fcSrob 		"boolean",
426a0724fcSrob 		3,
436a0724fcSrob 		{
446a0724fcSrob 			0x01, 0x01, 0xff
456a0724fcSrob 		},
466a0724fcSrob 	},
476a0724fcSrob 	{
4890377c34Srob 		FAIL,
4990377c34Srob 		0,
5090377c34Srob 		"boolean (constructed - expected failure)",
5190377c34Srob 		3,
5290377c34Srob 		{
5390377c34Srob 			0x21, 0x01, 0xff
5490377c34Srob 		},
5590377c34Srob 	},
5690377c34Srob 	{
5790377c34Srob 		FAIL,
5890377c34Srob 		0,
5990377c34Srob 		"boolean (more than 1 content octet - expected failure)",
6090377c34Srob 		4,
6190377c34Srob 		{
6290377c34Srob 			0x01, 0x02, 0x00, 0xff
6390377c34Srob 		},
6490377c34Srob 	},
6590377c34Srob 	{
666a0724fcSrob 		SUCCEED,
6736a71bf8Srob 		1,
68ce5d4185Srob 		"enum",
69ce5d4185Srob 		3,
70ce5d4185Srob 		{
71ce5d4185Srob 			0x0a, 0x01, 0x00
72ce5d4185Srob 		},
73ce5d4185Srob 	},
74ce5d4185Srob 	{
75ce5d4185Srob 		FAIL,
76ce5d4185Srob 		0,
77ce5d4185Srob 		"enum (constructed - expected failure)",
78ce5d4185Srob 		3,
79ce5d4185Srob 		{
80ce5d4185Srob 			0x2a, 0x01, 0x00
81ce5d4185Srob 		},
82ce5d4185Srob 	},
83ce5d4185Srob 	{
84ba9a685bSrob 		FAIL,
85ba9a685bSrob 		0,
86ba9a685bSrob 		"enum minimal contents octets (expected failure)",
87ba9a685bSrob 		4,
88ba9a685bSrob 		{
89ba9a685bSrob 			0x0a, 0x02, 0x00, 0x01
90ba9a685bSrob 		},
91ba9a685bSrob 	},
92ba9a685bSrob 	{
93ce5d4185Srob 		SUCCEED,
94ce5d4185Srob 		1,
956a0724fcSrob 		"integer (zero)",
966a0724fcSrob 		3,
976a0724fcSrob 		{
986a0724fcSrob 			0x02, 0x01, 0x00
996a0724fcSrob 		},
1006a0724fcSrob 	},
1016a0724fcSrob 	{
102ce5d4185Srob 		FAIL,
103ce5d4185Srob 		0,
104ce5d4185Srob 		"integer (constructed - expected failure)",
105ce5d4185Srob 		3,
106ce5d4185Srob 		{
107ce5d4185Srob 			0x22, 0x01, 0x01
108ce5d4185Srob 		},
109ce5d4185Srob 	},
110ce5d4185Srob 	{
1116a0724fcSrob 		SUCCEED,
11236a71bf8Srob 		1,
1136a0724fcSrob 		"positive integer",
1146a0724fcSrob 		3,
1156a0724fcSrob 		{
1166a0724fcSrob 			0x02, 0x01, 0x63
1176a0724fcSrob 		},
1186a0724fcSrob 	},
1196a0724fcSrob 	{
1206a0724fcSrob 		SUCCEED,
12136a71bf8Srob 		1,
1226a0724fcSrob 		"large positive integer",
1236a0724fcSrob 		5,
1246a0724fcSrob 		{
1256a0724fcSrob 			0x02, 0x03, 0x01, 0x00, 0x00
1266a0724fcSrob 		},
1276a0724fcSrob 	},
1286a0724fcSrob 	{
1296a0724fcSrob 		SUCCEED,
13036a71bf8Srob 		1,
1316a0724fcSrob 		"negative integer",
1326a0724fcSrob 		4,
1336a0724fcSrob 		{
1346a0724fcSrob 			0x02, 0x02, 0xff, 0x7f
1356a0724fcSrob 		},
1366a0724fcSrob 	},
1376a0724fcSrob 	{
1385175af87Srob 		FAIL,
1395175af87Srob 		0,
140ba9a685bSrob 		"integer minimal contents octets (expected failure)",
1415175af87Srob 		4,
1425175af87Srob 		{
1435175af87Srob 			0x02, 0x02, 0x00, 0x01
1445175af87Srob 		},
1455175af87Srob 	},
1465175af87Srob 	{
1476a0724fcSrob 		SUCCEED,
14836a71bf8Srob 		1,
1496a0724fcSrob 		"bit string",
1506a0724fcSrob 		6,
1516a0724fcSrob 		{
1526a0724fcSrob 			0x03, 0x04, 0xde, 0xad, 0xbe, 0xef
1536a0724fcSrob 		},
1546a0724fcSrob 	},
1556a0724fcSrob 	{
1566a0724fcSrob 		SUCCEED,
15736a71bf8Srob 		1,
1586a0724fcSrob 		"octet string",
1596a0724fcSrob 		10,
1606a0724fcSrob 		{
1616a0724fcSrob 			0x04, 0x08, 0x01, 0x23, 0x45,
1626a0724fcSrob 			0x67, 0x89, 0xab, 0xcd, 0xef
1636a0724fcSrob 		},
1646a0724fcSrob 	},
1656a0724fcSrob 	{
1666a0724fcSrob 		SUCCEED,
16736a71bf8Srob 		1,
1686a0724fcSrob 		"null",
1696a0724fcSrob 		2,
1706a0724fcSrob 		{
1716a0724fcSrob 			0x05, 0x00
1726a0724fcSrob 		},
1736a0724fcSrob 	},
1746a0724fcSrob 	{
175ce5d4185Srob 		FAIL,
176ce5d4185Srob 		0,
177ce5d4185Srob 		"null (constructed - expected failure)",
178ce5d4185Srob 		2,
179ce5d4185Srob 		{
180ce5d4185Srob 			0x25, 0x00
181ce5d4185Srob 		},
182ce5d4185Srob 	},
183ce5d4185Srob 	{
1846a0724fcSrob 		SUCCEED,
18536a71bf8Srob 		1,
1866a0724fcSrob 		"object identifier",
1876a0724fcSrob 		8,
1886a0724fcSrob 		{
1896a0724fcSrob 			0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d
1906a0724fcSrob 		}
1916a0724fcSrob 	},
1926a0724fcSrob 	{
1936a0724fcSrob 		SUCCEED,
19436a71bf8Srob 		1,
1956a0724fcSrob 		"sequence",	/* ldap */
1966a0724fcSrob 		14,
1976a0724fcSrob 		{
198cc5c2ffaSrob 			0x30, 0x0c, 0x02, 0x01, 0x01, 0x60, 0x07, 0x02,
199cc5c2ffaSrob 			0x01, 0x03, 0x04, 0x00, 0x80, 0x00
200cc5c2ffaSrob 		}
201cc5c2ffaSrob 	},
202cc5c2ffaSrob 	{
203cc5c2ffaSrob 		SUCCEED,
204cc5c2ffaSrob 		1,
205cc5c2ffaSrob 		"ldap bind",
206cc5c2ffaSrob 		30,
207cc5c2ffaSrob 		{
208cc5c2ffaSrob 			0x30, 0x1c, 0x02, 0x01, 0x01, 0x60, 0x17, 0x02,
209cc5c2ffaSrob 			0x01, 0x03, 0x04, 0x08, 0x63, 0x6e, 0x3d, 0x61,
210cc5c2ffaSrob 			0x64, 0x6d, 0x69, 0x6e, 0x80, 0x08, 0x70, 0x61,
211cc5c2ffaSrob 			0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
212cc5c2ffaSrob 		}
213cc5c2ffaSrob 	},
214cc5c2ffaSrob 	{
215cc5c2ffaSrob 		SUCCEED,
216cc5c2ffaSrob 		1,
217cc5c2ffaSrob 		"ldap search",
218cc5c2ffaSrob 		37,
219cc5c2ffaSrob 		{
220cc5c2ffaSrob 			0x30, 0x23, 0x02, 0x01, 0x01, 0x60, 0x1e, 0x04,
221cc5c2ffaSrob  			0x09, 0x6f, 0x75, 0x3d, 0x70, 0x65, 0x6f, 0x70,
222cc5c2ffaSrob 			0x6c, 0x65, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x00,
223cc5c2ffaSrob 			0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01,
224cc5c2ffaSrob 			0x00, 0x04, 0x02, 0x63, 0x6e
2256a0724fcSrob 		}
2266a0724fcSrob 	},
2276a0724fcSrob 	{
2286a0724fcSrob 		SUCCEED,
22936a71bf8Srob 		1,
2304947a39fSrob 		"snmpd encode",
2314947a39fSrob 		15,
2324947a39fSrob 		{
2334947a39fSrob 			0x30, 0x0d, 0x02, 0x01, 0x01, 0x02, 0x02, 0x20,
2344947a39fSrob 			0x00, 0x04, 0x01, 0x01, 0x02, 0x01, 0x03
2354947a39fSrob 		}
2364947a39fSrob 	},
2374947a39fSrob 	{
2384947a39fSrob 		SUCCEED,
2394947a39fSrob 		1,
2406a0724fcSrob 		"set with integer and boolean",
2416a0724fcSrob 		8,
2426a0724fcSrob 		{
2436a0724fcSrob 			0x31, 0x06, 0x02, 0x01, 0x04, 0x01, 0x01, 0xff
2446a0724fcSrob 		}
2456a0724fcSrob 	},
2466a0724fcSrob 	{
2476a0724fcSrob 		FAIL,
24836a71bf8Srob 		0,
24936a71bf8Srob 		"indefinite encoding (expected failure)",
2506a0724fcSrob 		4,
2516a0724fcSrob 		{
2526a0724fcSrob 			0x30, 0x80, 0x00, 0x00
2536a0724fcSrob 		}
2546a0724fcSrob 	},
2556a0724fcSrob 	{
25690377c34Srob 		FAIL,
25736a71bf8Srob 		0,
25890377c34Srob 		"reserved for future use (expected failure)",
25990377c34Srob 		4,
2606a0724fcSrob 		{
26190377c34Srob 			0x30, 0xff, 0x01, 0x01
26290377c34Srob 		}
2636a0724fcSrob 	},
2646a0724fcSrob 	{
2656a0724fcSrob 		FAIL,
26636a71bf8Srob 		0,
26790377c34Srob 		"long form tagging prohibited (expected failure)",
26890377c34Srob 		5,
2696a0724fcSrob 		{
27090377c34Srob 			0x1f, 0x80, 0x02, 0x01, 0x01
2716a0724fcSrob 		},
2726a0724fcSrob 	},
2736a0724fcSrob 	{
27436a71bf8Srob 		SUCCEED,
27536a71bf8Srob 		0,
2767ffe596eSrob 		"max long form length octets (i.e. 4 bytes)",
2777ffe596eSrob 		7,
27836a71bf8Srob 		{
2797ffe596eSrob 			0x02, 0x84, 0x00, 0x00, 0x00, 0x01, 0x01
28036a71bf8Srob 		},
28136a71bf8Srob 	},
28236a71bf8Srob 	{
2836a0724fcSrob 		FAIL,
28436a71bf8Srob 		0,
28536a71bf8Srob 		"overflow long form length octets (expected failure)",
2867ffe596eSrob 		8,
28736a71bf8Srob 		{
2887ffe596eSrob 			0x02, 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01
28936a71bf8Srob 		},
29036a71bf8Srob 	},
29136a71bf8Srob 	{
29236a71bf8Srob 		FAIL,
29336a71bf8Srob 		0,
29468cc6c26Srob 		"incorrect length - not enough data (expected failure)",
29568cc6c26Srob 		3,
2966a0724fcSrob 		{
29768cc6c26Srob 			0x02, 0x02, 0x01
2986a0724fcSrob 		}
2996a0724fcSrob 	}
3006a0724fcSrob };
3016a0724fcSrob 
3026a0724fcSrob static void
hexdump(const unsigned char * buf,size_t len)3036a0724fcSrob hexdump(const unsigned char *buf, size_t len)
3046a0724fcSrob {
3056a0724fcSrob 	size_t	i;
3066a0724fcSrob 
3076a0724fcSrob 	for (i = 1; i < len; i++)
3086a0724fcSrob 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "": "\n");
3096a0724fcSrob 
3106a0724fcSrob 	fprintf(stderr, " 0x%02hhx", buf[i - 1]);
3116a0724fcSrob 	fprintf(stderr, "\n");
3126a0724fcSrob }
3136a0724fcSrob 
314cc5c2ffaSrob unsigned int
ldap_application(struct ber_element * elm)315cc5c2ffaSrob ldap_application(struct ber_element *elm)
316cc5c2ffaSrob {
317cc5c2ffaSrob 	return BER_TYPE_OCTETSTRING;
318cc5c2ffaSrob }
319cc5c2ffaSrob 
3206a0724fcSrob static int
test(int i)3216a0724fcSrob test(int i)
3226a0724fcSrob {
3236a0724fcSrob 	int			 pos, b;
3246a0724fcSrob 	char			*string;
3256a0724fcSrob 	void			*p = NULL;
3266a0724fcSrob 	ssize_t			 len = 0;
3276a0724fcSrob 	struct ber_element	*elm = NULL, *ptr = NULL;
3286a0724fcSrob 	struct ber		 ber;
3296a0724fcSrob 	long long		 val;
3306a0724fcSrob 	void			*bstring = NULL;
3316a0724fcSrob 	struct ber_oid		 oid;
3326a0724fcSrob 	struct ber_octetstring	 ostring;
3336a0724fcSrob 
3346a0724fcSrob 	bzero(&ber, sizeof(ber));
335*696b5899Stb 	ober_set_readbuf(&ber, test_vectors[i].input, test_vectors[i].length);
336*696b5899Stb 	ober_set_application(&ber, ldap_application);
3376a0724fcSrob 
338*696b5899Stb 	elm = ober_read_elements(&ber, elm);
33950795871Srob 	if (elm == NULL && test_vectors[i].fail &&
34050795871Srob 	    (errno == EINVAL || errno == ERANGE || errno == ECANCELED))
3416a0724fcSrob 		return 0;
3426a0724fcSrob 	else if (elm != NULL && test_vectors[i].fail) {
343*696b5899Stb 		printf("expected failure of ober_read_elements did not occur\n");
3446a0724fcSrob 		return 1;
3456a0724fcSrob 	} else if (elm == NULL) {
346*696b5899Stb 		printf("unexpectedly failed ober_read_elements\n");
3476a0724fcSrob 		return 1;
3486a0724fcSrob 	}
3496a0724fcSrob 
3506a0724fcSrob 	/*
3516a0724fcSrob 	 * short form tagged elements start at the 3rd octet (i.e. position 2).
3526a0724fcSrob 	 */
35336a71bf8Srob 	if (test_vectors[i].memcheck) {
354*696b5899Stb 		pos = ober_getpos(elm);
3556a0724fcSrob 		if (pos != 2) {
3566a0724fcSrob 			printf("unexpected element position within "
35717b9f730Srob 			    "byte stream\n");
3586a0724fcSrob 			return 1;
3596a0724fcSrob 		}
3606a0724fcSrob 	}
3616a0724fcSrob 
3626a0724fcSrob 	switch (elm->be_encoding) {
3636a0724fcSrob 	case BER_TYPE_EOC:
364*696b5899Stb 		if (ober_get_eoc(elm) == -1) {
3656a0724fcSrob 			printf("failed (eoc) encoding check\n");
3666a0724fcSrob 			return 1;
3676a0724fcSrob 		}
368*696b5899Stb 		if (ober_scanf_elements(elm, ".", &val) == -1) {
369*696b5899Stb 			printf("failed (eoc) ober_scanf_elements\n");
3706a0724fcSrob 			return 1;
3716a0724fcSrob 		}
3726a0724fcSrob 		break;
3736a0724fcSrob 	case BER_TYPE_BOOLEAN:
374*696b5899Stb 		if (ober_get_boolean(elm, &b) == -1) {
3756a0724fcSrob 			printf("failed (boolean) encoding check\n");
3766a0724fcSrob 			return 1;
3776a0724fcSrob 		}
378*696b5899Stb 		if (ober_scanf_elements(elm, "b", &b) == -1) {
379*696b5899Stb 			printf("failed (boolean) ober_scanf_elements\n");
3806a0724fcSrob 			return 1;
3816a0724fcSrob 		}
3826a0724fcSrob 		break;
3836a0724fcSrob 	case BER_TYPE_INTEGER:
384*696b5899Stb 		if (ober_get_integer(elm, &val) == -1) {
3856a0724fcSrob 			printf("failed (int) encoding check\n");
3866a0724fcSrob 			return 1;
3876a0724fcSrob 		}
388*696b5899Stb 		if (ober_scanf_elements(elm, "i", &val) == -1) {
389*696b5899Stb 			printf("failed (int) ober_scanf_elements (i)\n");
3906a0724fcSrob 			return 1;
3916a0724fcSrob 		}
392*696b5899Stb 		if (ober_scanf_elements(elm, "d", &val) == -1) {
393*696b5899Stb 			printf("failed (int) ober_scanf_elements (d)\n");
3946a0724fcSrob 			return 1;
3956a0724fcSrob 		}
3966a0724fcSrob 		break;
397ce5d4185Srob 	case BER_TYPE_ENUMERATED:
398*696b5899Stb 		if (ober_get_enumerated(elm, &val) == -1) {
399ce5d4185Srob 			printf("failed (enum) encoding check\n");
400ce5d4185Srob 			return 1;
401ce5d4185Srob 		}
402*696b5899Stb 		if (ober_scanf_elements(elm, "E", &val) == -1) {
403*696b5899Stb 			printf("failed (enum) ober_scanf_elements (E)\n");
404ce5d4185Srob 			return 1;
405ce5d4185Srob 		}
406ce5d4185Srob 		break;
4076a0724fcSrob 	case BER_TYPE_BITSTRING:
408*696b5899Stb 		if (ober_get_bitstring(elm, &bstring, &len) == -1) {
4096a0724fcSrob 			printf("failed (bit string) encoding check\n");
4106a0724fcSrob 			return 1;
4116a0724fcSrob 		}
4126a0724fcSrob 		break;
4136a0724fcSrob 	case BER_TYPE_OCTETSTRING:
414*696b5899Stb 		if (ober_get_ostring(elm, &ostring) == -1) {
4156a0724fcSrob 			printf("failed (octet string) encoding check\n");
4166a0724fcSrob 			return 1;
4176a0724fcSrob 		}
418*696b5899Stb 		if (ober_scanf_elements(elm, "s", &string) == -1) {
419*696b5899Stb 			printf("failed (octet string) ober_scanf_elements\n");
4206a0724fcSrob 			return 1;
4216a0724fcSrob 		}
4226a0724fcSrob 		break;
4236a0724fcSrob 	case BER_TYPE_NULL:
424*696b5899Stb 		if (ober_get_null(elm) == -1) {
4256a0724fcSrob 			printf("failed (null) encoding check\n");
4266a0724fcSrob 			return 1;
4276a0724fcSrob 		}
428*696b5899Stb 		if (ober_scanf_elements(elm, "0", &val) == -1) {
429*696b5899Stb 			printf("failed (null) ober_scanf_elements\n");
4306a0724fcSrob 			return 1;
4316a0724fcSrob 		}
4326a0724fcSrob 		break;
4336a0724fcSrob 	case BER_TYPE_OBJECT:	/* OID */
434*696b5899Stb 		if (ober_get_oid(elm, &oid) == -1) {
435c95a2219Srob 			printf("failed (oid) encoding check\n");
4366a0724fcSrob 			return 1;
4376a0724fcSrob 		}
438*696b5899Stb 		if (ober_scanf_elements(elm, "o", &oid) == -1) {
439*696b5899Stb 			printf("failed (oid) ober_scanf_elements\n");
4406a0724fcSrob 			return 1;
4416a0724fcSrob 		}
4426a0724fcSrob 		break;
4436a0724fcSrob 	case BER_TYPE_SET:
4446a0724fcSrob 	case BER_TYPE_SEQUENCE:
4456a0724fcSrob 		if (elm->be_sub != NULL) {
4466a0724fcSrob 			ptr = elm->be_sub;
447*696b5899Stb 			if (ober_getpos(ptr) <= pos) {
4486a0724fcSrob 				printf("unexpected element position within "
4496a0724fcSrob 				    "byte stream\n");
4506a0724fcSrob 				return 1;
4516a0724fcSrob 			}
4526a0724fcSrob 		} else {
4536a0724fcSrob 			printf("expected sub element was not present\n");
4546a0724fcSrob 			return 1;
4556a0724fcSrob 		}
4566a0724fcSrob 		break;
4576a0724fcSrob 	default:
4586a0724fcSrob 		printf("failed with unknown encoding (%ud)\n",
4596a0724fcSrob 		    elm->be_encoding);
4606a0724fcSrob 		return 1;
4616a0724fcSrob 	}
4626a0724fcSrob 
4636a0724fcSrob 	/*
46417b9f730Srob 	 * additional testing on short form encoding
4656a0724fcSrob 	 */
46636a71bf8Srob 	if (test_vectors[i].memcheck) {
467*696b5899Stb 		len = ober_calc_len(elm);
4686a0724fcSrob 		if (len != test_vectors[i].length) {
4696a0724fcSrob 			printf("failed to calculate length\n");
4706a0724fcSrob 			return 1;
4716a0724fcSrob 		}
4726a0724fcSrob 
4736a0724fcSrob 		ber.br_wbuf = NULL;
474*696b5899Stb 		len = ober_write_elements(&ber, elm);
4756a0724fcSrob 		if (len != test_vectors[i].length) {
4766a0724fcSrob 			printf("failed length check (was %zd want "
4776a0724fcSrob 			    "%zd)\n", len, test_vectors[i].length);
4786a0724fcSrob 			return 1;
4796a0724fcSrob 		}
4806a0724fcSrob 
4816a0724fcSrob 		if (memcmp(ber.br_wbuf, test_vectors[i].input,
482cc5c2ffaSrob 		    test_vectors[i].length) != 0) {
483cc5c2ffaSrob 			printf("failed byte stream compare\n");
484cc5c2ffaSrob 			printf("Got:\n");
485cc5c2ffaSrob 			hexdump(ber.br_wbuf, len);
486cc5c2ffaSrob 			printf("Expected:\n");
487cc5c2ffaSrob 			hexdump(test_vectors[i].input, test_vectors[i].length);
4886a0724fcSrob 			return 1;
489cc5c2ffaSrob 		}
490*696b5899Stb 		ober_free(&ber);
4916a0724fcSrob 
4926a0724fcSrob 	}
493*696b5899Stb 	ober_free_elements(elm);
4946a0724fcSrob 
4956a0724fcSrob 	return 0;
4966a0724fcSrob }
4976a0724fcSrob 
4986a0724fcSrob int
test_ber_printf_elements_integer(void)4996a0724fcSrob test_ber_printf_elements_integer(void) {
5006a0724fcSrob 	int			 val = 1, len = 0;
5016a0724fcSrob 	struct ber_element	*elm = NULL;
5026a0724fcSrob 	struct ber		 ber;
5036a0724fcSrob 
5046a0724fcSrob 	unsigned char		 exp[3] = { 0x02, 0x01, 0x01 };
5056a0724fcSrob 
506*696b5899Stb 	elm = ober_printf_elements(elm, "d", val);
5076a0724fcSrob 	if (elm == NULL) {
508*696b5899Stb 		printf("failed ober_printf_elements\n");
5096a0724fcSrob 		return 1;
5106a0724fcSrob 	}
5116a0724fcSrob 
5126a0724fcSrob 	bzero(&ber, sizeof(ber));
5136a0724fcSrob 	ber.br_wbuf = NULL;
514*696b5899Stb 	len = ober_write_elements(&ber, elm);
5156a0724fcSrob 	if (len != sizeof(exp)) {
5166a0724fcSrob 		printf("failed length check (was %d want %zd)\n", len,
5176a0724fcSrob 		    sizeof(exp));
5186a0724fcSrob 		return 1;
5196a0724fcSrob 	}
5206a0724fcSrob 
5216a0724fcSrob 	if (memcmp(ber.br_wbuf, exp, len) != 0) {
5226a0724fcSrob 		printf("failed (int) byte stream compare\n");
5236a0724fcSrob 		return 1;
5246a0724fcSrob 	}
5256a0724fcSrob 
526*696b5899Stb 	ober_free_elements(elm);
527*696b5899Stb 	ober_free(&ber);
5286a0724fcSrob 	return 0;
5296a0724fcSrob }
5306a0724fcSrob 
5316a0724fcSrob #define LDAP_REQ_BIND		0
5326a0724fcSrob #define LDAP_REQ_SEARCH		0
5336a0724fcSrob #define VERSION			3
5346a0724fcSrob #define	LDAP_AUTH_SIMPLE	0
5356a0724fcSrob 
5366a0724fcSrob int
test_ber_printf_elements_ldap_bind(void)5376a0724fcSrob test_ber_printf_elements_ldap_bind(void) {
5386a0724fcSrob 	int			 len = 0, msgid = 1;
5396a0724fcSrob 	char			*binddn = "cn=admin";
5406a0724fcSrob 	char			*bindcred = "password";
5416a0724fcSrob 	struct ber_element	*root = NULL, *elm = NULL;
5426a0724fcSrob 	struct ber		 ber;
5436a0724fcSrob 
5446a0724fcSrob 	unsigned char		 exp[] = {
5456a0724fcSrob 		0x30, 0x1c,
5466a0724fcSrob 		0x02, 0x01, 0x01,
5476a0724fcSrob 		0x60, 0x17,
5486a0724fcSrob 		0x02, 0x01, 0x03,
5496a0724fcSrob 		0x04, 0x08, 0x63, 0x6e, 0x3d, 0x61, 0x64, 0x6d, 0x69, 0x6e,
5506a0724fcSrob 		0x80, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
5516a0724fcSrob 	};
5526a0724fcSrob 
553*696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
5546a0724fcSrob 		return 1;
5556a0724fcSrob 
556*696b5899Stb 	elm = ober_printf_elements(root, "d{tdsst", msgid,
5576a0724fcSrob 	    BER_CLASS_APP, LDAP_REQ_BIND,
5586a0724fcSrob 	    VERSION,
5596a0724fcSrob 	    binddn, bindcred,
5606a0724fcSrob 	    BER_CLASS_CONTEXT, LDAP_AUTH_SIMPLE);
5616a0724fcSrob 
5626a0724fcSrob 	if (elm == NULL) {
563*696b5899Stb 		printf("failed ober_printf_elements\n");
5646a0724fcSrob 		return 1;
5656a0724fcSrob 	}
5666a0724fcSrob 
5676a0724fcSrob 	bzero(&ber, sizeof(ber));
5686a0724fcSrob 	ber.br_wbuf = NULL;
569*696b5899Stb 	ober_set_application(&ber, ldap_application);
570*696b5899Stb 	len = ober_write_elements(&ber, root);
5716a0724fcSrob 	if (len != sizeof(exp)) {
5726a0724fcSrob 		printf("failed length check (was %d want %zd)\n", len,
5736a0724fcSrob 		    sizeof(exp));
5746a0724fcSrob 		return 1;
5756a0724fcSrob 	}
5766a0724fcSrob 
5776a0724fcSrob 	if (memcmp(ber.br_wbuf, exp, len) != 0) {
5786a0724fcSrob 		printf("failed (ldap bind) byte stream compare\n");
5796a0724fcSrob 		hexdump(ber.br_wbuf, len);
5806a0724fcSrob 		return 1;
5816a0724fcSrob 	}
5826a0724fcSrob 
583*696b5899Stb 	ober_free_elements(elm);
584*696b5899Stb 	ober_free(&ber);
5856a0724fcSrob 	return 0;
5866a0724fcSrob }
5876a0724fcSrob 
5886a0724fcSrob int
test_ber_printf_elements_ldap_search(void)5896a0724fcSrob test_ber_printf_elements_ldap_search(void) {
5906a0724fcSrob 	int			 len = 0, msgid = 1;
5916a0724fcSrob 	int			 sizelimit = 0, timelimit = 0;
5926a0724fcSrob 	int			 typesonly = 0;
5936a0724fcSrob 	long long		 scope = 0, deref = 0;
5946a0724fcSrob 	char			*basedn = "ou=people";
5956a0724fcSrob 	char			*filter = "cn";
596c95a2219Srob 	struct ber_element	*root = NULL, *elm = NULL, *felm = NULL;
5976a0724fcSrob 	struct ber		 ber;
5986a0724fcSrob 
5996a0724fcSrob 	unsigned char		 exp[] = {
600cc5c2ffaSrob 		0x30, 0x23, 0x02, 0x01, 0x01, 0x60, 0x1e, 0x04,
601cc5c2ffaSrob 		0x09, 0x6f, 0x75, 0x3d, 0x70, 0x65, 0x6f, 0x70,
602cc5c2ffaSrob 		0x6c, 0x65, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x00,
603cc5c2ffaSrob 		0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01,
604cc5c2ffaSrob 		0x00, 0x04, 0x02, 0x63, 0x6e
6056a0724fcSrob 	};
6066a0724fcSrob 
607*696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
6086a0724fcSrob 		return 1;
6096a0724fcSrob 
610*696b5899Stb 	elm = ober_printf_elements(root, "d{tsEEddbs",
611cc5c2ffaSrob 	    msgid, BER_CLASS_APP, LDAP_REQ_SEARCH,
612cc5c2ffaSrob 	    basedn, scope, deref, sizelimit, timelimit, typesonly, filter);
6136a0724fcSrob 	if (elm == NULL) {
614*696b5899Stb 		printf("failed ober_printf_elements\n");
6156a0724fcSrob 		return 1;
6166a0724fcSrob 	}
6176a0724fcSrob 
6186a0724fcSrob 	bzero(&ber, sizeof(ber));
6196a0724fcSrob 	ber.br_wbuf = NULL;
620*696b5899Stb 	ober_set_application(&ber, ldap_application);
621*696b5899Stb 	len = ober_write_elements(&ber, root);
6226a0724fcSrob 	if (len != sizeof(exp)) {
6236a0724fcSrob 		printf("failed length check (was %d want %zd)\n", len,
6246a0724fcSrob 		    sizeof(exp));
6256a0724fcSrob 		return 1;
6266a0724fcSrob 	}
6276a0724fcSrob 
6286a0724fcSrob 	if (memcmp(ber.br_wbuf, exp, len) != 0) {
6296a0724fcSrob 		printf("failed (ldap search) byte stream compare\n");
6306a0724fcSrob 		hexdump(ber.br_wbuf, len);
6316a0724fcSrob 		return 1;
6326a0724fcSrob 	}
6336a0724fcSrob 
634*696b5899Stb 	ober_free_elements(elm);
635*696b5899Stb 	ober_free(&ber);
6366a0724fcSrob 	return 0;
6376a0724fcSrob }
6386a0724fcSrob 
6396a0724fcSrob int
test_ber_printf_elements_snmp_v3_encode(void)6406a0724fcSrob test_ber_printf_elements_snmp_v3_encode(void) {
6416a0724fcSrob 	int			 len = 0;
6426a0724fcSrob 	u_int8_t		 f = 0x01;	/* verbose */
6436a0724fcSrob 	long long		 secmodel = 3;	/* USM */
6446a0724fcSrob 	long long		 msgid = 1, max_msg_size = 8192;
6456a0724fcSrob 	struct ber_element	*elm = NULL;
6466a0724fcSrob 	struct ber		 ber;
6476a0724fcSrob 
6486a0724fcSrob 	unsigned char		 exp[] = {
6494947a39fSrob 		0x30, 0x0d, 0x02, 0x01, 0x01, 0x02, 0x02, 0x20,
6504947a39fSrob 		0x00, 0x04, 0x01, 0x01, 0x02, 0x01, 0x03
6516a0724fcSrob 	};
6526a0724fcSrob 
653*696b5899Stb 	elm = ober_printf_elements(elm, "{iixi}", msgid, max_msg_size,
6546a0724fcSrob 	    &f, sizeof(f), secmodel);
6556a0724fcSrob 	if (elm == NULL) {
656*696b5899Stb 		printf("failed ober_printf_elements\n");
6576a0724fcSrob 		return 1;
6586a0724fcSrob 	}
6596a0724fcSrob 
6606a0724fcSrob 	bzero(&ber, sizeof(ber));
6616a0724fcSrob 	ber.br_wbuf = NULL;
662*696b5899Stb 	len = ober_write_elements(&ber, elm);
6636a0724fcSrob 	if (len != sizeof(exp)) {
6646a0724fcSrob 		printf("failed length check (was %d want %zd)\n", len,
6656a0724fcSrob 		    sizeof(exp));
6666a0724fcSrob 		return 1;
6676a0724fcSrob 	}
6686a0724fcSrob 
6696a0724fcSrob 	if (memcmp(ber.br_wbuf, exp, len) != 0) {
6706a0724fcSrob 		printf("failed (snmp_v3_encode) byte stream compare\n");
6716a0724fcSrob 		hexdump(ber.br_wbuf, len);
6726a0724fcSrob 		return 1;
6736a0724fcSrob 	}
6746a0724fcSrob 
675*696b5899Stb 	ober_free_elements(elm);
676*696b5899Stb 	ober_free(&ber);
6776a0724fcSrob 	return 0;
6786a0724fcSrob }
6796a0724fcSrob 
6806a0724fcSrob int
test_ber_null(void)681376546ccSrob test_ber_null(void)
682376546ccSrob {
683376546ccSrob 	long long		 val;
684376546ccSrob 	struct ber_element	*elm = NULL;
685376546ccSrob 
686376546ccSrob 	/* scanning into a null ber_element should fail */
687*696b5899Stb 	if (ober_scanf_elements(elm, "0", &val) != -1) {
688*696b5899Stb 		printf("failed (null ber_element) ober_scanf_elements empty\n");
689376546ccSrob 		goto fail;
690376546ccSrob 	}
691376546ccSrob 
692*696b5899Stb 	if ((elm = ober_printf_elements(elm, "{d}", 1)) == NULL) {
693*696b5899Stb 		printf("failed (null ber_element) ober_printf_elements\n");
694376546ccSrob 	}
695376546ccSrob 
696376546ccSrob 	/*
6977ccbcfe6Srob 	 * Scanning after the last valid element should be able to descend back
698376546ccSrob 	 * into the parent level.
699376546ccSrob 	 */
700*696b5899Stb 	if (ober_scanf_elements(elm, "{i}", &val) != 0) {
701*696b5899Stb 		printf("failed (null ber_element) ober_scanf_elements valid\n");
702376546ccSrob 		goto fail;
703376546ccSrob 	}
704376546ccSrob 	/*
705376546ccSrob 	 * Scanning for a non-existent element should fail, even if it's just a
706376546ccSrob 	 * skip.
707376546ccSrob 	 */
708*696b5899Stb 	if (ober_scanf_elements(elm, "{lS}", &val) != -1) {
709*696b5899Stb 		printf("failed (null ber_element) ober_scanf_elements invalid\n");
710376546ccSrob 		goto fail;
711376546ccSrob 	}
712376546ccSrob 
713*696b5899Stb 	ober_free_elements(elm);
714376546ccSrob 	return 0;
715376546ccSrob 
716376546ccSrob fail:
717*696b5899Stb 	ober_free_elements(elm);
718376546ccSrob 	return 1;
719376546ccSrob }
720376546ccSrob 
721376546ccSrob int
main(void)7226a0724fcSrob main(void)
7236a0724fcSrob {
7246a0724fcSrob 	extern char *__progname;
7256a0724fcSrob 
7266a0724fcSrob 	ssize_t		len = 0;
7276a0724fcSrob 	int		i, ret = 0;
7286a0724fcSrob 
7296a0724fcSrob 	/*
7306a0724fcSrob 	 * drive test vectors for ber byte stream input validation, etc.
7316a0724fcSrob 	 */
7326a0724fcSrob 	for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) {
7336a0724fcSrob 		if (test(i) != 0) {
7346a0724fcSrob 			printf("FAILED: %s\n", test_vectors[i].title);
7356a0724fcSrob 			ret = 1;
7366a0724fcSrob 		} else
7376a0724fcSrob 			printf("SUCCESS: %s\n", test_vectors[i].title);
7386a0724fcSrob 	}
7396a0724fcSrob 
7406a0724fcSrob 	/*
7416a0724fcSrob 	 * run standalone functions for ber byte stream creation, etc.
7426a0724fcSrob 	 * (e.g. ldap, snmpd)
7436a0724fcSrob 	 */
744cca1463aSrob 	if (test_ber_printf_elements_integer() != 0) {
745cca1463aSrob 		printf("FAILED: test_ber_printf_elements_integer\n");
7466a0724fcSrob 		ret = 1;
747cca1463aSrob 	} else
7486a0724fcSrob 		printf("SUCCESS: test_ber_printf_elements_integer\n");
7496a0724fcSrob 
750cca1463aSrob 	if (test_ber_printf_elements_ldap_bind() != 0) {
751cca1463aSrob 		printf("FAILED: test_ber_printf_elements_ldap_bind\n");
7526a0724fcSrob 		ret = 1;
753cca1463aSrob 	} else
7546a0724fcSrob 		printf("SUCCESS: test_ber_printf_elements_ldap_bind\n");
7556a0724fcSrob 
756cca1463aSrob 	if (test_ber_printf_elements_ldap_search() != 0) {
757cca1463aSrob 		printf("FAILED: test_ber_printf_elements_ldap_search\n");
7586a0724fcSrob 		ret = 1;
759cca1463aSrob 	} else
7606a0724fcSrob 		printf("SUCCESS: test_ber_printf_elements_ldap_search\n");
7616a0724fcSrob 
762cca1463aSrob 	if (test_ber_printf_elements_snmp_v3_encode() != 0) {
763cca1463aSrob 		printf("FAILED: test_ber_printf_elements_snmpd_v3_encode\n");
7646a0724fcSrob 		ret = 1;
765cca1463aSrob 	} else
7666a0724fcSrob 		printf("SUCCESS: test_ber_printf_elements_snmpd_v3_encode\n");
767cca1463aSrob 
768376546ccSrob 	if (test_ber_null() != 0) {
769376546ccSrob 		printf("FAILED: test_ber_null\n");
770376546ccSrob 		ret = 1;
771376546ccSrob 	} else
772376546ccSrob 		printf("SUCCESS: test_ber_null\n");
773376546ccSrob 
7746a0724fcSrob 	if (ret != 0) {
7756a0724fcSrob 		printf("FAILED: %s\n", __progname);
7766a0724fcSrob 		return 1;
7776a0724fcSrob 	}
7786a0724fcSrob 
7796a0724fcSrob 	return 0;
7806a0724fcSrob }
781