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