1/*	$KAME: test-policy.c,v 1.16 2003/08/26 03:24:08 itojun Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <sys/types.h>
36#include <sys/param.h>
37#include <sys/socket.h>
38
39#include <netinet/in.h>
40#include <net/pfkeyv2.h>
41#include <netipsec/key_debug.h>
42#include <netipsec/ipsec.h>
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <unistd.h>
47#include <string.h>
48#include <errno.h>
49#include <err.h>
50
51#include "libpfkey.h"
52
53struct req_t {
54	int result;	/* expected result; 0:ok 1:ng */
55	char *str;
56} reqs[] = {
57{ 0, "out ipsec" },
58{ 1, "must_error" },
59{ 1, "in ipsec must_error" },
60{ 1, "out ipsec esp/must_error" },
61{ 1, "out discard" },
62{ 1, "out none" },
63{ 0, "in entrust" },
64{ 0, "out entrust" },
65{ 1, "out ipsec esp" },
66{ 0, "in ipsec ah/transport" },
67{ 1, "in ipsec ah/tunnel" },
68{ 0, "out ipsec ah/transport/" },
69{ 1, "out ipsec ah/tunnel/" },
70{ 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" },
71{ 0, "in ipsec esp/tunnel/::1-::2" },
72{ 1, "in ipsec esp/tunnel/10.0.0.1-::2" },
73{ 0, "in ipsec esp/tunnel/::1-::2/require" },
74{ 0, "out ipsec ah/transport//use" },
75{ 1, "out ipsec ah/transport esp/use" },
76{ 1, "in ipsec ah/transport esp/tunnel" },
77{ 0, "in ipsec ah/transport esp/tunnel/::1-::1" },
78{ 0, "in ipsec\n"
79	"ah / transport\n"
80	"esp / tunnel / ::1-::2" },
81{ 0, "out ipsec\n"
82	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n"
83	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n"
84	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n" },
85{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" },
86};
87
88int test1(void);
89int test1sub1(struct req_t *);
90int test1sub2(char *, int);
91int test2(void);
92int test2sub(int);
93
94int
95main(ac, av)
96	int ac;
97	char **av;
98{
99	test1();
100	test2();
101
102	exit(0);
103}
104
105int
106test1()
107{
108	int i;
109	int result;
110
111	printf("TEST1\n");
112	for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) {
113		printf("#%d [%s]\n", i + 1, reqs[i].str);
114
115		result = test1sub1(&reqs[i]);
116		if (result == 0 && reqs[i].result == 1) {
117			warnx("ERROR: expecting failure.");
118		} else if (result == 1 && reqs[i].result == 0) {
119			warnx("ERROR: expecting success.");
120		}
121	}
122
123	return 0;
124}
125
126int
127test1sub1(req)
128	struct req_t *req;
129{
130	char *buf;
131
132	buf = ipsec_set_policy(req->str, strlen(req->str));
133	if (buf == NULL) {
134		printf("ipsec_set_policy: %s\n", ipsec_strerror());
135		return 1;
136	}
137
138	if (test1sub2(buf, PF_INET) != 0
139	 || test1sub2(buf, PF_INET6) != 0) {
140		free(buf);
141		return 1;
142	}
143#if 0
144	kdebug_sadb_x_policy((struct sadb_ext *)buf);
145#endif
146
147	free(buf);
148	return 0;
149}
150
151int
152test1sub2(policy, family)
153	char *policy;
154	int family;
155{
156	int so;
157	int proto = 0, optname = 0;
158	int len;
159	char getbuf[1024];
160
161	switch (family) {
162	case PF_INET:
163		proto = IPPROTO_IP;
164		optname = IP_IPSEC_POLICY;
165		break;
166	case PF_INET6:
167		proto = IPPROTO_IPV6;
168		optname = IPV6_IPSEC_POLICY;
169		break;
170	}
171
172	if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
173		err(1, "socket");
174
175	len = ipsec_get_policylen(policy);
176#if 0
177	printf("\tsetlen:%d\n", len);
178#endif
179
180	if (setsockopt(so, proto, optname, policy, len) < 0) {
181		printf("fail to set sockopt; %s\n", strerror(errno));
182		close(so);
183		return 1;
184	}
185
186	memset(getbuf, 0, sizeof(getbuf));
187	memcpy(getbuf, policy, sizeof(struct sadb_x_policy));
188	if (getsockopt(so, proto, optname, getbuf, &len) < 0) {
189		printf("fail to get sockopt; %s\n", strerror(errno));
190		close(so);
191		return 1;
192	}
193
194    {
195	char *buf = NULL;
196
197#if 0
198	printf("\tgetlen:%d\n", len);
199#endif
200
201	if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) {
202		printf("%s\n", ipsec_strerror());
203		close(so);
204		return 1;
205	}
206#if 0
207	printf("\t[%s]\n", buf);
208#endif
209	free(buf);
210    }
211
212	close (so);
213	return 0;
214}
215
216char addr[] = {
217	28, 28, 0, 0,
218	0, 0, 0, 0,
219	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
220	0, 0, 0, 0,
221};
222
223int
224test2()
225{
226	int so;
227	char *pol1 = "out ipsec";
228	char *pol2 = "out ipsec ah/transport//use";
229	char *sp1, *sp2;
230	int splen1, splen2;
231	int spid;
232	struct sadb_msg *m;
233
234	printf("TEST2\n");
235	if (getuid() != 0)
236		errx(1, "root privilege required.");
237
238	sp1 = ipsec_set_policy(pol1, strlen(pol1));
239	splen1 = ipsec_get_policylen(sp1);
240	sp2 = ipsec_set_policy(pol2, strlen(pol2));
241	splen2 = ipsec_get_policylen(sp2);
242
243	if ((so = pfkey_open()) < 0)
244		errx(1, "ERROR: %s", ipsec_strerror());
245
246	printf("spdflush()\n");
247	if (pfkey_send_spdflush(so) < 0)
248		errx(1, "ERROR: %s", ipsec_strerror());
249	m = pfkey_recv(so);
250	free(m);
251
252	printf("spdsetidx()\n");
253	if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128,
254				(struct sockaddr *)addr, 128,
255				255, sp1, splen1, 0) < 0)
256		errx(1, "ERROR: %s", ipsec_strerror());
257	m = pfkey_recv(so);
258	free(m);
259
260	printf("spdupdate()\n");
261	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
262				(struct sockaddr *)addr, 128,
263				255, sp2, splen2, 0) < 0)
264		errx(1, "ERROR: %s", ipsec_strerror());
265	m = pfkey_recv(so);
266	free(m);
267
268	printf("sleep(4)\n");
269	sleep(4);
270
271	printf("spddelete()\n");
272	if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128,
273				(struct sockaddr *)addr, 128,
274				255, sp1, splen1, 0) < 0)
275		errx(1, "ERROR: %s", ipsec_strerror());
276	m = pfkey_recv(so);
277	free(m);
278
279	printf("spdadd()\n");
280	if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128,
281				(struct sockaddr *)addr, 128,
282				255, sp2, splen2, 0) < 0)
283		errx(1, "ERROR: %s", ipsec_strerror());
284	spid = test2sub(so);
285
286	printf("spdget(%u)\n", spid);
287	if (pfkey_send_spdget(so, spid) < 0)
288		errx(1, "ERROR: %s", ipsec_strerror());
289	m = pfkey_recv(so);
290	free(m);
291
292	printf("sleep(4)\n");
293	sleep(4);
294
295	printf("spddelete2()\n");
296	if (pfkey_send_spddelete2(so, spid) < 0)
297		errx(1, "ERROR: %s", ipsec_strerror());
298	m = pfkey_recv(so);
299	free(m);
300
301	printf("spdadd() with lifetime's 10(s)\n");
302	if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128,
303				(struct sockaddr *)addr, 128,
304				255, 0, 10, sp2, splen2, 0) < 0)
305		errx(1, "ERROR: %s", ipsec_strerror());
306	spid = test2sub(so);
307
308	/* expecting failure */
309	printf("spdupdate()\n");
310	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
311				(struct sockaddr *)addr, 128,
312				255, sp2, splen2, 0) == 0) {
313		warnx("ERROR: expecting failure.");
314	}
315
316	return 0;
317}
318
319int
320test2sub(so)
321	int so;
322{
323	struct sadb_msg *msg;
324	caddr_t mhp[SADB_EXT_MAX + 1];
325
326	if ((msg = pfkey_recv(so)) == NULL)
327		errx(1, "ERROR: pfkey_recv failure.");
328	if (pfkey_align(msg, mhp) < 0)
329		errx(1, "ERROR: pfkey_align failure.");
330
331	return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id;
332}
333
334