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 "config.h"
33
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37
38#include <netinet/in.h>
39#include <net/pfkeyv2.h>
40#include <netinet6/ipsec.h>
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <unistd.h>
45#include <string.h>
46#include <errno.h>
47#include <err.h>
48
49#include "libpfkey.h"
50
51struct req_t {
52	int result;	/* expected result; 0:ok 1:ng */
53	char *str;
54} reqs[] = {
55{ 0, "out ipsec" },
56{ 1, "must_error" },
57{ 1, "in ipsec must_error" },
58{ 1, "out ipsec esp/must_error" },
59{ 1, "out discard" },
60{ 1, "out none" },
61{ 0, "in entrust" },
62{ 0, "out entrust" },
63{ 1, "out ipsec esp" },
64{ 0, "in ipsec ah/transport" },
65{ 1, "in ipsec ah/tunnel" },
66{ 0, "out ipsec ah/transport/" },
67{ 1, "out ipsec ah/tunnel/" },
68{ 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" },
69{ 0, "in ipsec esp/tunnel/::1-::2" },
70{ 1, "in ipsec esp/tunnel/10.0.0.1-::2" },
71{ 0, "in ipsec esp/tunnel/::1-::2/require" },
72{ 0, "out ipsec ah/transport//use" },
73{ 1, "out ipsec ah/transport esp/use" },
74{ 1, "in ipsec ah/transport esp/tunnel" },
75{ 0, "in ipsec ah/transport esp/tunnel/::1-::1" },
76{ 0, "in ipsec ah / transport esp / tunnel / ::1-::2" },
77{ 0, "out ipsec \
78	 ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require \
79	 ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require \
80	 ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require \
81	" },
82{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" },
83};
84
85int test1 (void);
86int test1sub1 (struct req_t *);
87int test1sub2 (char *, int);
88int test2 (void);
89int test2sub (int);
90
91int
92main(ac, av)
93	int ac;
94	char **av;
95{
96	test1();
97	test2();
98
99	exit(0);
100}
101
102int
103test1()
104{
105	int i;
106	int result;
107
108	printf("TEST1\n");
109	for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) {
110		printf("#%d [%s]\n", i + 1, reqs[i].str);
111
112		result = test1sub1(&reqs[i]);
113		if (result == 0 && reqs[i].result == 1) {
114			warnx("ERROR: expecting failure.");
115		} else if (result == 1 && reqs[i].result == 0) {
116			warnx("ERROR: expecting success.");
117		}
118	}
119
120	return 0;
121}
122
123int
124test1sub1(req)
125	struct req_t *req;
126{
127	char *buf;
128
129	buf = ipsec_set_policy(req->str, strlen(req->str));
130	if (buf == NULL) {
131		printf("ipsec_set_policy: %s\n", ipsec_strerror());
132		return 1;
133	}
134
135	if (test1sub2(buf, PF_INET) != 0
136	 || test1sub2(buf, PF_INET6) != 0) {
137		free(buf);
138		return 1;
139	}
140#if 0
141	kdebug_sadb_x_policy((struct sadb_ext *)buf);
142#endif
143
144	free(buf);
145	return 0;
146}
147
148int
149test1sub2(policy, family)
150	char *policy;
151	int family;
152{
153	int so;
154	int proto = 0, optname = 0;
155	int len;
156	char getbuf[1024];
157
158	switch (family) {
159	case PF_INET:
160		proto = IPPROTO_IP;
161		optname = IP_IPSEC_POLICY;
162		break;
163	case PF_INET6:
164		proto = IPPROTO_IPV6;
165		optname = IPV6_IPSEC_POLICY;
166		break;
167	}
168
169	if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
170		err(1, "socket");
171
172	len = ipsec_get_policylen(policy);
173#if 0
174	printf("\tsetlen:%d\n", len);
175#endif
176
177	if (setsockopt(so, proto, optname, policy, len) < 0) {
178		printf("fail to set sockopt; %s\n", strerror(errno));
179		close(so);
180		return 1;
181	}
182
183	memset(getbuf, 0, sizeof(getbuf));
184	memcpy(getbuf, policy, sizeof(struct sadb_x_policy));
185	if (getsockopt(so, proto, optname, getbuf, &len) < 0) {
186		printf("fail to get sockopt; %s\n", strerror(errno));
187		close(so);
188		return 1;
189	}
190
191    {
192	char *buf = NULL;
193
194#if 0
195	printf("\tgetlen:%d\n", len);
196#endif
197
198	if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) {
199		printf("%s\n", ipsec_strerror());
200		close(so);
201		return 1;
202	}
203#if 0
204	printf("\t[%s]\n", buf);
205#endif
206	free(buf);
207    }
208
209	close (so);
210	return 0;
211}
212
213char addr[] = {
214	28, 28, 0, 0,
215	0, 0, 0, 0,
216	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
217	0, 0, 0, 0,
218};
219
220int
221test2()
222{
223	int so;
224	char *pol1 = "out ipsec";
225	char *pol2 = "out ipsec ah/transport//use";
226	char *sp1, *sp2;
227	int splen1, splen2;
228	int spid;
229	struct sadb_msg *m;
230
231	printf("TEST2\n");
232	if (getuid() != 0)
233		errx(1, "root privilege required.");
234
235	sp1 = ipsec_set_policy(pol1, strlen(pol1));
236	splen1 = ipsec_get_policylen(sp1);
237	sp2 = ipsec_set_policy(pol2, strlen(pol2));
238	splen2 = ipsec_get_policylen(sp2);
239
240	if ((so = pfkey_open()) < 0)
241		errx(1, "ERROR: %s", ipsec_strerror());
242
243	printf("spdflush()\n");
244	if (pfkey_send_spdflush(so) < 0)
245		errx(1, "ERROR: %s", ipsec_strerror());
246	m = pfkey_recv(so);
247	free(m);
248
249	printf("spdsetidx()\n");
250	if (pfkey_send_spdsetidx(so, (struct sockaddr_storage *)addr, 128,
251				(struct sockaddr_storage *)addr, 128,
252				255, sp1, splen1, 0) < 0)
253		errx(1, "ERROR: %s", ipsec_strerror());
254	m = pfkey_recv(so);
255	free(m);
256
257	printf("spdupdate()\n");
258	if (pfkey_send_spdupdate(so, (struct sockaddr_storage *)addr, 128,
259				(struct sockaddr_storage *)addr, 128,
260				255, sp2, splen2, 0) < 0)
261		errx(1, "ERROR: %s", ipsec_strerror());
262	m = pfkey_recv(so);
263	free(m);
264
265	printf("sleep(4)\n");
266	sleep(4);
267
268	printf("spddelete()\n");
269	if (pfkey_send_spddelete(so, (struct sockaddr_storage *)addr, 128,
270				(struct sockaddr_storage *)addr, 128,
271				255, sp1, splen1, 0) < 0)
272		errx(1, "ERROR: %s", ipsec_strerror());
273	m = pfkey_recv(so);
274	free(m);
275
276	printf("spdadd()\n");
277	if (pfkey_send_spdadd(so, (struct sockaddr_storage *)addr, 128,
278				(struct sockaddr_storage *)addr, 128,
279				255, sp2, splen2, 0) < 0)
280		errx(1, "ERROR: %s", ipsec_strerror());
281	spid = test2sub(so);
282
283	printf("spdget(%u)\n", spid);
284	if (pfkey_send_spdget(so, spid) < 0)
285		errx(1, "ERROR: %s", ipsec_strerror());
286	m = pfkey_recv(so);
287	free(m);
288
289	printf("sleep(4)\n");
290	sleep(4);
291
292	printf("spddelete2()\n");
293	if (pfkey_send_spddelete2(so, spid) < 0)
294		errx(1, "ERROR: %s", ipsec_strerror());
295	m = pfkey_recv(so);
296	free(m);
297
298	printf("spdadd() with lifetime's 10(s)\n");
299	if (pfkey_send_spdadd2(so, (struct sockaddr_storage *)addr, 128,
300				(struct sockaddr_storage *)addr, 128,
301				255, 0, 10, sp2, splen2, 0) < 0)
302		errx(1, "ERROR: %s", ipsec_strerror());
303	spid = test2sub(so);
304
305	/* expecting failure */
306	printf("spdupdate()\n");
307	if (pfkey_send_spdupdate(so, (struct sockaddr_storage *)addr, 128,
308				(struct sockaddr_storage *)addr, 128,
309				255, sp2, splen2, 0) == 0) {
310		warnx("ERROR: expecting failure.");
311	}
312
313	return 0;
314}
315
316int
317test2sub(so)
318	int so;
319{
320	struct sadb_msg *msg;
321	caddr_t mhp[SADB_EXT_MAX + 1];
322
323	if ((msg = pfkey_recv(so)) == NULL)
324		errx(1, "ERROR: pfkey_recv failure.");
325	if (pfkey_align(msg, mhp) < 0)
326		errx(1, "ERROR: pfkey_align failure.");
327
328	return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id;
329}
330
331