1121572Sume/*	$KAME: test-policy.c,v 1.16 2003/08/26 03:24:08 itojun Exp $	*/
262583Sitojun
355505Sshin/*
455505Sshin * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
555505Sshin * All rights reserved.
655505Sshin *
755505Sshin * Redistribution and use in source and binary forms, with or without
855505Sshin * modification, are permitted provided that the following conditions
955505Sshin * are met:
1055505Sshin * 1. Redistributions of source code must retain the above copyright
1155505Sshin *    notice, this list of conditions and the following disclaimer.
1255505Sshin * 2. Redistributions in binary form must reproduce the above copyright
1355505Sshin *    notice, this list of conditions and the following disclaimer in the
1455505Sshin *    documentation and/or other materials provided with the distribution.
1555505Sshin * 3. Neither the name of the project nor the names of its contributors
1655505Sshin *    may be used to endorse or promote products derived from this software
1755505Sshin *    without specific prior written permission.
1855505Sshin *
1955505Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2055505Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2155505Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2255505Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2355505Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2455505Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2555505Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2655505Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2755505Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2855505Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2955505Sshin * SUCH DAMAGE.
3055505Sshin */
3155505Sshin
3284208Sdillon#include <sys/cdefs.h>
3384208Sdillon__FBSDID("$FreeBSD$");
3484208Sdillon
3555505Sshin#include <sys/types.h>
3655505Sshin#include <sys/param.h>
3755505Sshin#include <sys/socket.h>
3855505Sshin
3955505Sshin#include <netinet/in.h>
4057855Sshin#include <net/pfkeyv2.h>
41171135Sgnn#include <netipsec/key_debug.h>
42171135Sgnn#include <netipsec/ipsec.h>
4355505Sshin
4455505Sshin#include <stdio.h>
4555505Sshin#include <stdlib.h>
4655505Sshin#include <unistd.h>
4755505Sshin#include <string.h>
4862583Sitojun#include <errno.h>
4955505Sshin#include <err.h>
5055505Sshin
5178064Sume#include "libpfkey.h"
5278064Sume
5362583Sitojunstruct req_t {
5462583Sitojun	int result;	/* expected result; 0:ok 1:ng */
5562583Sitojun	char *str;
5662583Sitojun} reqs[] = {
5762583Sitojun{ 0, "out ipsec" },
5862583Sitojun{ 1, "must_error" },
5962583Sitojun{ 1, "in ipsec must_error" },
6062583Sitojun{ 1, "out ipsec esp/must_error" },
6162583Sitojun{ 1, "out discard" },
6262583Sitojun{ 1, "out none" },
6362583Sitojun{ 0, "in entrust" },
6462583Sitojun{ 0, "out entrust" },
6562583Sitojun{ 1, "out ipsec esp" },
6662583Sitojun{ 0, "in ipsec ah/transport" },
6762583Sitojun{ 1, "in ipsec ah/tunnel" },
6862583Sitojun{ 0, "out ipsec ah/transport/" },
6962583Sitojun{ 1, "out ipsec ah/tunnel/" },
7062583Sitojun{ 0, "in ipsec esp / transport / 10.0.0.1-10.0.0.2" },
7162583Sitojun{ 0, "in ipsec esp/tunnel/::1-::2" },
7262583Sitojun{ 1, "in ipsec esp/tunnel/10.0.0.1-::2" },
7362583Sitojun{ 0, "in ipsec esp/tunnel/::1-::2/require" },
7462583Sitojun{ 0, "out ipsec ah/transport//use" },
7562583Sitojun{ 1, "out ipsec ah/transport esp/use" },
7662583Sitojun{ 1, "in ipsec ah/transport esp/tunnel" },
7762583Sitojun{ 0, "in ipsec ah/transport esp/tunnel/::1-::1" },
78248314Sglebius{ 0, "in ipsec\n"
79248314Sglebius	"ah / transport\n"
80248314Sglebius	"esp / tunnel / ::1-::2" },
81248314Sglebius{ 0, "out ipsec\n"
82248314Sglebius	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n"
83248314Sglebius	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n"
84248314Sglebius	"ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require\n" },
8562583Sitojun{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" },
8655505Sshin};
8755505Sshin
8892917Sobrienint test1(void);
8992917Sobrienint test1sub1(struct req_t *);
9092917Sobrienint test1sub2(char *, int);
9192917Sobrienint test2(void);
9292917Sobrienint test2sub(int);
9355505Sshin
9455505Sshinint
9555505Sshinmain(ac, av)
9655505Sshin	int ac;
9755505Sshin	char **av;
9855505Sshin{
9962583Sitojun	test1();
10062583Sitojun	test2();
10162583Sitojun
10262583Sitojun	exit(0);
10362583Sitojun}
10462583Sitojun
10562583Sitojunint
10662583Sitojuntest1()
10762583Sitojun{
10855505Sshin	int i;
10962583Sitojun	int result;
11055505Sshin
11162583Sitojun	printf("TEST1\n");
11262583Sitojun	for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) {
11362583Sitojun		printf("#%d [%s]\n", i + 1, reqs[i].str);
11455505Sshin
11562583Sitojun		result = test1sub1(&reqs[i]);
11662583Sitojun		if (result == 0 && reqs[i].result == 1) {
117121572Sume			warnx("ERROR: expecting failure.");
11862583Sitojun		} else if (result == 1 && reqs[i].result == 0) {
119121572Sume			warnx("ERROR: expecting success.");
12055505Sshin		}
12162583Sitojun	}
12255505Sshin
12362583Sitojun	return 0;
12462583Sitojun}
12555505Sshin
12662583Sitojunint
12762583Sitojuntest1sub1(req)
12862583Sitojun	struct req_t *req;
12962583Sitojun{
13062583Sitojun	char *buf;
13155505Sshin
13262583Sitojun	buf = ipsec_set_policy(req->str, strlen(req->str));
13362583Sitojun	if (buf == NULL) {
13462583Sitojun		printf("ipsec_set_policy: %s\n", ipsec_strerror());
13562583Sitojun		return 1;
13662583Sitojun	}
13762583Sitojun
13862583Sitojun	if (test1sub2(buf, PF_INET) != 0
13962583Sitojun	 || test1sub2(buf, PF_INET6) != 0) {
14055505Sshin		free(buf);
14162583Sitojun		return 1;
14255505Sshin	}
14362583Sitojun#if 0
14462583Sitojun	kdebug_sadb_x_policy((struct sadb_ext *)buf);
14562583Sitojun#endif
14655505Sshin
14762583Sitojun	free(buf);
14855505Sshin	return 0;
14955505Sshin}
15055505Sshin
15155505Sshinint
15262583Sitojuntest1sub2(policy, family)
15355505Sshin	char *policy;
15455505Sshin	int family;
15555505Sshin{
15662583Sitojun	int so;
15762583Sitojun	int proto = 0, optname = 0;
15855505Sshin	int len;
15955505Sshin	char getbuf[1024];
16055505Sshin
16155505Sshin	switch (family) {
16255505Sshin	case PF_INET:
16355505Sshin		proto = IPPROTO_IP;
16455505Sshin		optname = IP_IPSEC_POLICY;
16555505Sshin		break;
16655505Sshin	case PF_INET6:
16755505Sshin		proto = IPPROTO_IPV6;
16855505Sshin		optname = IPV6_IPSEC_POLICY;
16955505Sshin		break;
17055505Sshin	}
17155505Sshin
17255505Sshin	if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
17355505Sshin		err(1, "socket");
17455505Sshin
17555505Sshin	len = ipsec_get_policylen(policy);
17662583Sitojun#if 0
17762583Sitojun	printf("\tsetlen:%d\n", len);
17862583Sitojun#endif
17962583Sitojun
18055505Sshin	if (setsockopt(so, proto, optname, policy, len) < 0) {
18162583Sitojun		printf("fail to set sockopt; %s\n", strerror(errno));
18262583Sitojun		close(so);
18362583Sitojun		return 1;
18455505Sshin	}
18555505Sshin
18655505Sshin	memset(getbuf, 0, sizeof(getbuf));
18762583Sitojun	memcpy(getbuf, policy, sizeof(struct sadb_x_policy));
18855505Sshin	if (getsockopt(so, proto, optname, getbuf, &len) < 0) {
18962583Sitojun		printf("fail to get sockopt; %s\n", strerror(errno));
19062583Sitojun		close(so);
19162583Sitojun		return 1;
19255505Sshin	}
19355505Sshin
19455505Sshin    {
19555505Sshin	char *buf = NULL;
19655505Sshin
19762583Sitojun#if 0
19855505Sshin	printf("\tgetlen:%d\n", len);
19962583Sitojun#endif
20055505Sshin
20155505Sshin	if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) {
20255505Sshin		printf("%s\n", ipsec_strerror());
20362583Sitojun		close(so);
20462583Sitojun		return 1;
20555505Sshin	}
20662583Sitojun#if 0
20762583Sitojun	printf("\t[%s]\n", buf);
20862583Sitojun#endif
20962583Sitojun	free(buf);
21055505Sshin    }
21155505Sshin
21255505Sshin	close (so);
21362583Sitojun	return 0;
21462583Sitojun}
21555505Sshin
21662583Sitojunchar addr[] = {
21762583Sitojun	28, 28, 0, 0,
21862583Sitojun	0, 0, 0, 0,
21962583Sitojun	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
22062583Sitojun	0, 0, 0, 0,
22162583Sitojun};
22262583Sitojun
22362583Sitojunint
22462583Sitojuntest2()
22562583Sitojun{
22662583Sitojun	int so;
22762583Sitojun	char *pol1 = "out ipsec";
22862583Sitojun	char *pol2 = "out ipsec ah/transport//use";
22962583Sitojun	char *sp1, *sp2;
23062583Sitojun	int splen1, splen2;
23162583Sitojun	int spid;
23262583Sitojun	struct sadb_msg *m;
23362583Sitojun
23462583Sitojun	printf("TEST2\n");
23562583Sitojun	if (getuid() != 0)
236121572Sume		errx(1, "root privilege required.");
23762583Sitojun
23862583Sitojun	sp1 = ipsec_set_policy(pol1, strlen(pol1));
23962583Sitojun	splen1 = ipsec_get_policylen(sp1);
24062583Sitojun	sp2 = ipsec_set_policy(pol2, strlen(pol2));
24162583Sitojun	splen2 = ipsec_get_policylen(sp2);
24262583Sitojun
24362583Sitojun	if ((so = pfkey_open()) < 0)
244121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
24562583Sitojun
24662583Sitojun	printf("spdflush()\n");
24762583Sitojun	if (pfkey_send_spdflush(so) < 0)
248121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
24962583Sitojun	m = pfkey_recv(so);
25062583Sitojun	free(m);
25178064Sume
25262583Sitojun	printf("spdsetidx()\n");
25362583Sitojun	if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128,
25462583Sitojun				(struct sockaddr *)addr, 128,
25562583Sitojun				255, sp1, splen1, 0) < 0)
256121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
25762583Sitojun	m = pfkey_recv(so);
25862583Sitojun	free(m);
25962583Sitojun
26062583Sitojun	printf("spdupdate()\n");
26162583Sitojun	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
26262583Sitojun				(struct sockaddr *)addr, 128,
26362583Sitojun				255, sp2, splen2, 0) < 0)
264121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
26562583Sitojun	m = pfkey_recv(so);
26662583Sitojun	free(m);
26762583Sitojun
268121572Sume	printf("sleep(4)\n");
26978064Sume	sleep(4);
27078064Sume
27162583Sitojun	printf("spddelete()\n");
27262583Sitojun	if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128,
27362583Sitojun				(struct sockaddr *)addr, 128,
27462583Sitojun				255, sp1, splen1, 0) < 0)
275121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
27662583Sitojun	m = pfkey_recv(so);
27762583Sitojun	free(m);
27862583Sitojun
27962583Sitojun	printf("spdadd()\n");
28062583Sitojun	if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128,
28162583Sitojun				(struct sockaddr *)addr, 128,
28262583Sitojun				255, sp2, splen2, 0) < 0)
283121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
28462583Sitojun	spid = test2sub(so);
28562583Sitojun
28662583Sitojun	printf("spdget(%u)\n", spid);
28762583Sitojun	if (pfkey_send_spdget(so, spid) < 0)
288121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
28962583Sitojun	m = pfkey_recv(so);
29062583Sitojun	free(m);
29162583Sitojun
292121572Sume	printf("sleep(4)\n");
29378064Sume	sleep(4);
29478064Sume
29562583Sitojun	printf("spddelete2()\n");
29662583Sitojun	if (pfkey_send_spddelete2(so, spid) < 0)
297121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
29862583Sitojun	m = pfkey_recv(so);
29962583Sitojun	free(m);
30062583Sitojun
30178064Sume	printf("spdadd() with lifetime's 10(s)\n");
30278064Sume	if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128,
30378064Sume				(struct sockaddr *)addr, 128,
30478064Sume				255, 0, 10, sp2, splen2, 0) < 0)
305121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
30678064Sume	spid = test2sub(so);
30778064Sume
30862583Sitojun	/* expecting failure */
30962583Sitojun	printf("spdupdate()\n");
31062583Sitojun	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
31162583Sitojun				(struct sockaddr *)addr, 128,
31262583Sitojun				255, sp2, splen2, 0) == 0) {
313121572Sume		warnx("ERROR: expecting failure.");
31462583Sitojun	}
31562583Sitojun
31655505Sshin	return 0;
31755505Sshin}
31855505Sshin
31962583Sitojunint
32062583Sitojuntest2sub(so)
32162583Sitojun	int so;
32262583Sitojun{
32362583Sitojun	struct sadb_msg *msg;
32462583Sitojun	caddr_t mhp[SADB_EXT_MAX + 1];
32562583Sitojun
32662583Sitojun	if ((msg = pfkey_recv(so)) == NULL)
327121572Sume		errx(1, "ERROR: pfkey_recv failure.");
32862583Sitojun	if (pfkey_align(msg, mhp) < 0)
329121572Sume		errx(1, "ERROR: pfkey_align failure.");
33062583Sitojun
33162583Sitojun	return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id;
33262583Sitojun}
33362583Sitojun
334