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" },
7862583Sitojun{ 0, "in ipsec
7955505Sshin	ah / transport
8062583Sitojun	esp / tunnel / ::1-::2" },
8162583Sitojun{ 0, "out ipsec
8262583Sitojun	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
8362583Sitojun	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
8462583Sitojun	ah/transport/::1-::2 esp/tunnel/::3-::4/use ah/transport/::5-::6/require
8562583Sitojun	" },
8662583Sitojun{ 0, "out ipsec esp/transport/fec0::10-fec0::11/use" },
8755505Sshin};
8855505Sshin
8992917Sobrienint test1(void);
9092917Sobrienint test1sub1(struct req_t *);
9192917Sobrienint test1sub2(char *, int);
9292917Sobrienint test2(void);
9392917Sobrienint test2sub(int);
9455505Sshin
9555505Sshinint
9655505Sshinmain(ac, av)
9755505Sshin	int ac;
9855505Sshin	char **av;
9955505Sshin{
10062583Sitojun	test1();
10162583Sitojun	test2();
10262583Sitojun
10362583Sitojun	exit(0);
10462583Sitojun}
10562583Sitojun
10662583Sitojunint
10762583Sitojuntest1()
10862583Sitojun{
10955505Sshin	int i;
11062583Sitojun	int result;
11155505Sshin
11262583Sitojun	printf("TEST1\n");
11362583Sitojun	for (i = 0; i < sizeof(reqs)/sizeof(reqs[0]); i++) {
11462583Sitojun		printf("#%d [%s]\n", i + 1, reqs[i].str);
11555505Sshin
11662583Sitojun		result = test1sub1(&reqs[i]);
11762583Sitojun		if (result == 0 && reqs[i].result == 1) {
118121572Sume			warnx("ERROR: expecting failure.");
11962583Sitojun		} else if (result == 1 && reqs[i].result == 0) {
120121572Sume			warnx("ERROR: expecting success.");
12155505Sshin		}
12262583Sitojun	}
12355505Sshin
12462583Sitojun	return 0;
12562583Sitojun}
12655505Sshin
12762583Sitojunint
12862583Sitojuntest1sub1(req)
12962583Sitojun	struct req_t *req;
13062583Sitojun{
13162583Sitojun	char *buf;
13255505Sshin
13362583Sitojun	buf = ipsec_set_policy(req->str, strlen(req->str));
13462583Sitojun	if (buf == NULL) {
13562583Sitojun		printf("ipsec_set_policy: %s\n", ipsec_strerror());
13662583Sitojun		return 1;
13762583Sitojun	}
13862583Sitojun
13962583Sitojun	if (test1sub2(buf, PF_INET) != 0
14062583Sitojun	 || test1sub2(buf, PF_INET6) != 0) {
14155505Sshin		free(buf);
14262583Sitojun		return 1;
14355505Sshin	}
14462583Sitojun#if 0
14562583Sitojun	kdebug_sadb_x_policy((struct sadb_ext *)buf);
14662583Sitojun#endif
14755505Sshin
14862583Sitojun	free(buf);
14955505Sshin	return 0;
15055505Sshin}
15155505Sshin
15255505Sshinint
15362583Sitojuntest1sub2(policy, family)
15455505Sshin	char *policy;
15555505Sshin	int family;
15655505Sshin{
15762583Sitojun	int so;
15862583Sitojun	int proto = 0, optname = 0;
15955505Sshin	int len;
16055505Sshin	char getbuf[1024];
16155505Sshin
16255505Sshin	switch (family) {
16355505Sshin	case PF_INET:
16455505Sshin		proto = IPPROTO_IP;
16555505Sshin		optname = IP_IPSEC_POLICY;
16655505Sshin		break;
16755505Sshin	case PF_INET6:
16855505Sshin		proto = IPPROTO_IPV6;
16955505Sshin		optname = IPV6_IPSEC_POLICY;
17055505Sshin		break;
17155505Sshin	}
17255505Sshin
17355505Sshin	if ((so = socket(family, SOCK_DGRAM, 0)) < 0)
17455505Sshin		err(1, "socket");
17555505Sshin
17655505Sshin	len = ipsec_get_policylen(policy);
17762583Sitojun#if 0
17862583Sitojun	printf("\tsetlen:%d\n", len);
17962583Sitojun#endif
18062583Sitojun
18155505Sshin	if (setsockopt(so, proto, optname, policy, len) < 0) {
18262583Sitojun		printf("fail to set sockopt; %s\n", strerror(errno));
18362583Sitojun		close(so);
18462583Sitojun		return 1;
18555505Sshin	}
18655505Sshin
18755505Sshin	memset(getbuf, 0, sizeof(getbuf));
18862583Sitojun	memcpy(getbuf, policy, sizeof(struct sadb_x_policy));
18955505Sshin	if (getsockopt(so, proto, optname, getbuf, &len) < 0) {
19062583Sitojun		printf("fail to get sockopt; %s\n", strerror(errno));
19162583Sitojun		close(so);
19262583Sitojun		return 1;
19355505Sshin	}
19455505Sshin
19555505Sshin    {
19655505Sshin	char *buf = NULL;
19755505Sshin
19862583Sitojun#if 0
19955505Sshin	printf("\tgetlen:%d\n", len);
20062583Sitojun#endif
20155505Sshin
20255505Sshin	if ((buf = ipsec_dump_policy(getbuf, NULL)) == NULL) {
20355505Sshin		printf("%s\n", ipsec_strerror());
20462583Sitojun		close(so);
20562583Sitojun		return 1;
20655505Sshin	}
20762583Sitojun#if 0
20862583Sitojun	printf("\t[%s]\n", buf);
20962583Sitojun#endif
21062583Sitojun	free(buf);
21155505Sshin    }
21255505Sshin
21355505Sshin	close (so);
21462583Sitojun	return 0;
21562583Sitojun}
21655505Sshin
21762583Sitojunchar addr[] = {
21862583Sitojun	28, 28, 0, 0,
21962583Sitojun	0, 0, 0, 0,
22062583Sitojun	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
22162583Sitojun	0, 0, 0, 0,
22262583Sitojun};
22362583Sitojun
22462583Sitojunint
22562583Sitojuntest2()
22662583Sitojun{
22762583Sitojun	int so;
22862583Sitojun	char *pol1 = "out ipsec";
22962583Sitojun	char *pol2 = "out ipsec ah/transport//use";
23062583Sitojun	char *sp1, *sp2;
23162583Sitojun	int splen1, splen2;
23262583Sitojun	int spid;
23362583Sitojun	struct sadb_msg *m;
23462583Sitojun
23562583Sitojun	printf("TEST2\n");
23662583Sitojun	if (getuid() != 0)
237121572Sume		errx(1, "root privilege required.");
23862583Sitojun
23962583Sitojun	sp1 = ipsec_set_policy(pol1, strlen(pol1));
24062583Sitojun	splen1 = ipsec_get_policylen(sp1);
24162583Sitojun	sp2 = ipsec_set_policy(pol2, strlen(pol2));
24262583Sitojun	splen2 = ipsec_get_policylen(sp2);
24362583Sitojun
24462583Sitojun	if ((so = pfkey_open()) < 0)
245121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
24662583Sitojun
24762583Sitojun	printf("spdflush()\n");
24862583Sitojun	if (pfkey_send_spdflush(so) < 0)
249121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
25062583Sitojun	m = pfkey_recv(so);
25162583Sitojun	free(m);
25278064Sume
25362583Sitojun	printf("spdsetidx()\n");
25462583Sitojun	if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128,
25562583Sitojun				(struct sockaddr *)addr, 128,
25662583Sitojun				255, sp1, splen1, 0) < 0)
257121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
25862583Sitojun	m = pfkey_recv(so);
25962583Sitojun	free(m);
26062583Sitojun
26162583Sitojun	printf("spdupdate()\n");
26262583Sitojun	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
26362583Sitojun				(struct sockaddr *)addr, 128,
26462583Sitojun				255, sp2, splen2, 0) < 0)
265121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
26662583Sitojun	m = pfkey_recv(so);
26762583Sitojun	free(m);
26862583Sitojun
269121572Sume	printf("sleep(4)\n");
27078064Sume	sleep(4);
27178064Sume
27262583Sitojun	printf("spddelete()\n");
27362583Sitojun	if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128,
27462583Sitojun				(struct sockaddr *)addr, 128,
27562583Sitojun				255, sp1, splen1, 0) < 0)
276121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
27762583Sitojun	m = pfkey_recv(so);
27862583Sitojun	free(m);
27962583Sitojun
28062583Sitojun	printf("spdadd()\n");
28162583Sitojun	if (pfkey_send_spdadd(so, (struct sockaddr *)addr, 128,
28262583Sitojun				(struct sockaddr *)addr, 128,
28362583Sitojun				255, sp2, splen2, 0) < 0)
284121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
28562583Sitojun	spid = test2sub(so);
28662583Sitojun
28762583Sitojun	printf("spdget(%u)\n", spid);
28862583Sitojun	if (pfkey_send_spdget(so, spid) < 0)
289121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
29062583Sitojun	m = pfkey_recv(so);
29162583Sitojun	free(m);
29262583Sitojun
293121572Sume	printf("sleep(4)\n");
29478064Sume	sleep(4);
29578064Sume
29662583Sitojun	printf("spddelete2()\n");
29762583Sitojun	if (pfkey_send_spddelete2(so, spid) < 0)
298121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
29962583Sitojun	m = pfkey_recv(so);
30062583Sitojun	free(m);
30162583Sitojun
30278064Sume	printf("spdadd() with lifetime's 10(s)\n");
30378064Sume	if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128,
30478064Sume				(struct sockaddr *)addr, 128,
30578064Sume				255, 0, 10, sp2, splen2, 0) < 0)
306121572Sume		errx(1, "ERROR: %s", ipsec_strerror());
30778064Sume	spid = test2sub(so);
30878064Sume
30962583Sitojun	/* expecting failure */
31062583Sitojun	printf("spdupdate()\n");
31162583Sitojun	if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128,
31262583Sitojun				(struct sockaddr *)addr, 128,
31362583Sitojun				255, sp2, splen2, 0) == 0) {
314121572Sume		warnx("ERROR: expecting failure.");
31562583Sitojun	}
31662583Sitojun
31755505Sshin	return 0;
31855505Sshin}
31955505Sshin
32062583Sitojunint
32162583Sitojuntest2sub(so)
32262583Sitojun	int so;
32362583Sitojun{
32462583Sitojun	struct sadb_msg *msg;
32562583Sitojun	caddr_t mhp[SADB_EXT_MAX + 1];
32662583Sitojun
32762583Sitojun	if ((msg = pfkey_recv(so)) == NULL)
328121572Sume		errx(1, "ERROR: pfkey_recv failure.");
32962583Sitojun	if (pfkey_align(msg, mhp) < 0)
330121572Sume		errx(1, "ERROR: pfkey_align failure.");
33162583Sitojun
33262583Sitojun	return ((struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY])->sadb_x_policy_id;
33362583Sitojun}
33462583Sitojun
335