priv_netinet_ipsec.c revision 173679
1164022Sdds/*-
2164022Sdds * Copyright (c) 2007 Bjoern A. Zeeb
3164022Sdds * All rights reserved.
4164022Sdds *
5164022Sdds * Redistribution and use in source and binary forms, with or without
6164022Sdds * modification, are permitted provided that the following conditions
7164022Sdds * are met:
8164022Sdds * 1. Redistributions of source code must retain the above copyright
9164022Sdds *    notice, this list of conditions and the following disclaimer.
10164022Sdds * 2. Redistributions in binary form must reproduce the above copyright
11164022Sdds *    notice, this list of conditions and the following disclaimer in the
12164022Sdds *    documentation and/or other materials provided with the distribution.
13164022Sdds *
14164022Sdds * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15164022Sdds * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16164022Sdds * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17164022Sdds * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
18164022Sdds * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19164022Sdds * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20164022Sdds * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21164022Sdds * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22164022Sdds * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23164022Sdds * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24164022Sdds * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25164022Sdds *
26164022Sdds * $FreeBSD: head/tools/regression/priv/priv_netinet_ipsec.c 173679 2007-11-16 21:24:45Z bz $
27164022Sdds */
28164022Sdds
29164022Sdds/*
30164022Sdds * Confirm that privilege is required to open a pfkey socket, and that this
31 * is not allowed in jail.
32 */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <net/pfkeyv2.h>
37#include <netinet/in.h>
38#include <netipsec/ipsec.h>
39
40#include <err.h>
41#include <errno.h>
42#include <stdlib.h>
43#include <unistd.h>
44
45#include "main.h"
46
47static char	policy_bypass[]	= "in bypass";
48static char	policy_entrust[] = "in entrust";
49static char	*bypassbuf = NULL;
50static char	*entrustbuf = NULL;
51static int	sd = -1;
52
53
54static int
55priv_netinet_ipsec_policy_bypass_setup_af(int asroot, int injail,
56    struct test *test, int af)
57{
58
59	bypassbuf = ipsec_set_policy(policy_bypass, sizeof(policy_bypass) - 1);
60	if (bypassbuf == NULL) {
61		warn("%s: ipsec_set_policy(NULL)", __func__);
62		return (-1);
63	}
64	switch (af) {
65	case AF_INET:
66		sd = socket(AF_INET, SOCK_DGRAM, 0);
67		if (sd < 0) {
68			warn("%s: socket4", __func__);
69			return (-1);
70		}
71		break;
72	case AF_INET6:
73		sd = socket(AF_INET6, SOCK_DGRAM, 0);
74		if (sd < 0) {
75			warn("%s: socket6", __func__);
76			return (-1);
77		}
78		break;
79	default:
80		warnx("%s: unexpected address family", __func__);
81		return (-1);
82	}
83	return (0);
84}
85
86int
87priv_netinet_ipsec_policy4_bypass_setup(int asroot, int injail,
88    struct test *test)
89{
90
91	return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test,
92	    AF_INET));
93}
94
95int
96priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail,
97    struct test *test)
98{
99
100	return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test,
101	    AF_INET6));
102}
103
104
105
106static int
107priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail,
108    struct test *test, int af)
109{
110
111	entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1);
112	if (entrustbuf == NULL) {
113		warn("%s: ipsec_set_policy(NULL)", __func__);
114		return (-1);
115	}
116	switch (af) {
117	case AF_INET:
118		sd = socket(AF_INET, SOCK_DGRAM, 0);
119		if (sd < 0) {
120			warn("%s: socket4", __func__);
121			return (-1);
122		}
123		break;
124	case AF_INET6:
125		sd = socket(AF_INET6, SOCK_DGRAM, 0);
126		if (sd < 0) {
127			warn("%s: socket6", __func__);
128			return (-1);
129		}
130		break;
131	default:
132		warnx("%s: unexpected address family", __func__);
133		return (-1);
134	}
135	return (0);
136}
137
138int
139priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail,
140    struct test *test)
141{
142
143	return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test,
144	    AF_INET));
145}
146
147int
148priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail,
149    struct test *test)
150{
151
152	return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test,
153	    AF_INET6));
154}
155
156
157void
158priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test)
159{
160	int error, fd;
161
162	fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
163	if (fd < 0)
164		error = -1;
165	else
166		error = 0;
167	/*
168	 * The injail checks are not really priv checks but making sure
169	 * sys/kern/uipc_socket.c:socreate cred checks are working correctly.
170	 */
171	if (asroot && injail)
172		expect("priv_netinet_ipsec_pfkey(asroot, injail)", error,
173		    -1, EPROTONOSUPPORT);
174	if (asroot && !injail)
175		expect("priv_netinet_ipsec_pfkey(asroot, !injail)", error,
176		    0, 0);
177	if (!asroot && injail)
178		expect("priv_netinet_ipsec_pfkey(!asroot, injail)", error,
179		    -1, EPROTONOSUPPORT);
180	if (!asroot && !injail)
181		expect("priv_netinet_ipsec_pfkey(!asroot, !injail)", error,
182		    -1, EPERM);
183	if (fd >= 0)
184		(void)close(fd);
185}
186
187
188static void
189priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test,
190    int af)
191{
192	int error, level, optname;
193
194	switch (af) {
195	case AF_INET:
196		level = IPPROTO_IP;
197		optname = IP_IPSEC_POLICY;
198		break;
199	case AF_INET6:
200		level = IPPROTO_IPV6;
201		optname = IPV6_IPSEC_POLICY;
202		break;
203	default:
204		warnx("%s: unexpected address family", __func__);
205		return;
206	}
207	error = setsockopt(sd, level, optname,
208	    bypassbuf, ipsec_get_policylen(bypassbuf));
209	if (asroot && injail)
210		expect("priv_netinet_ipsec_policy_bypass(asroot, injail)",
211		    error, -1, EACCES); /* see ipsec_set_policy */
212	if (asroot && !injail)
213		expect("priv_netinet_ipsec_policy_bypass(asroot, !injail)",
214		    error, 0, 0);
215	if (!asroot && injail)
216		expect("priv_netinet_ipsec_policy_bypass(!asroot, injail)",
217		    error, -1, EACCES); /* see ipsec_set_policy */
218	if (!asroot && !injail)
219		expect("priv_netinet_ipsec_policy_bypass(!asroot, !injail)",
220		    error, -1, EACCES); /* see ipsec_set_policy */
221}
222
223void
224priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test)
225{
226
227	priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET);
228}
229
230void
231priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test)
232{
233
234	priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6);
235}
236
237
238static void
239priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test,
240    int af)
241{
242	int error, level, optname;
243
244	switch (af) {
245	case AF_INET:
246		level = IPPROTO_IP;
247		optname = IP_IPSEC_POLICY;
248		break;
249	case AF_INET6:
250		level = IPPROTO_IPV6;
251		optname = IPV6_IPSEC_POLICY;
252		break;
253	default:
254		warnx("%s: unexpected address family", __func__);
255		return;
256	}
257	error = setsockopt(sd, level, optname,
258	    entrustbuf, ipsec_get_policylen(entrustbuf));
259	if (asroot && injail)
260		expect("priv_netinet_ipsec_policy_entrust(asroot, injail)",
261		    error, 0, 0); /* XXX ipsec_set_policy */
262	if (asroot && !injail)
263		expect("priv_netinet_ipsec_policy_entrust(asroot, !injail)",
264		    error, 0, 0);
265	if (!asroot && injail)
266		expect("priv_netinet_ipsec_policy_entrust(!asroot, injail)",
267		    error, 0, 0); /* XXX ipsec_set_policy */
268	if (!asroot && !injail)
269		expect("priv_netinet_ipsec_policy_entrust(!asroot, !injail)",
270		    error, 0, 0); /* XXX ipsec_set_policy */
271}
272
273void
274priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test)
275{
276
277	priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET);
278}
279
280void
281priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test)
282{
283
284	priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6);
285}
286
287
288void
289priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail,
290    struct test *test)
291{
292
293	if (bypassbuf != NULL) {
294		free(bypassbuf);
295		bypassbuf = NULL;
296	}
297	if (sd >= 0) {
298		close(sd);
299		sd = -1;
300	}
301}
302
303void
304priv_netinet_ipsec_policy_entrust_cleanup(int asroot, int injail,
305    struct test *test)
306{
307
308	if (entrustbuf != NULL) {
309		free(entrustbuf);
310		entrustbuf = NULL;
311	}
312	if (sd >= 0) {
313		close(sd);
314		sd = -1;
315	}
316}
317
318