1/*- 2 * Copyright (c) 2007 Bjoern A. Zeeb 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 18 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 20 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: releng/10.2/tools/regression/priv/priv_netinet_ipsec.c 196172 2009-08-13 09:11:47Z bz $ 27 */ 28 29/* 30 * 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#ifdef INET6 73 case AF_INET6: 74 sd = socket(AF_INET6, SOCK_DGRAM, 0); 75 if (sd < 0) { 76 warn("%s: socket6", __func__); 77 return (-1); 78 } 79 break; 80#endif 81 default: 82 warnx("%s: unexpected address family", __func__); 83 return (-1); 84 } 85 return (0); 86} 87 88int 89priv_netinet_ipsec_policy4_bypass_setup(int asroot, int injail, 90 struct test *test) 91{ 92 93 return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 94 AF_INET)); 95} 96 97#ifdef INET6 98int 99priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail, 100 struct test *test) 101{ 102 103 return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 104 AF_INET6)); 105} 106#endif 107 108 109static int 110priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail, 111 struct test *test, int af) 112{ 113 114 entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1); 115 if (entrustbuf == NULL) { 116 warn("%s: ipsec_set_policy(NULL)", __func__); 117 return (-1); 118 } 119 switch (af) { 120 case AF_INET: 121 sd = socket(AF_INET, SOCK_DGRAM, 0); 122 if (sd < 0) { 123 warn("%s: socket4", __func__); 124 return (-1); 125 } 126 break; 127#ifdef INET6 128 case AF_INET6: 129 sd = socket(AF_INET6, SOCK_DGRAM, 0); 130 if (sd < 0) { 131 warn("%s: socket6", __func__); 132 return (-1); 133 } 134 break; 135#endif 136 default: 137 warnx("%s: unexpected address family", __func__); 138 return (-1); 139 } 140 return (0); 141} 142 143int 144priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail, 145 struct test *test) 146{ 147 148 return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 149 AF_INET)); 150} 151 152#ifdef INET6 153int 154priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail, 155 struct test *test) 156{ 157 158 return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 159 AF_INET6)); 160} 161#endif 162 163void 164priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test) 165{ 166 int error, fd; 167 168 fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 169 if (fd < 0) 170 error = -1; 171 else 172 error = 0; 173 /* 174 * The injail checks are not really priv checks but making sure 175 * sys/kern/uipc_socket.c:socreate cred checks are working correctly. 176 */ 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 0, 0); 183 if (!asroot && injail) 184 expect("priv_netinet_ipsec_pfkey(!asroot, injail)", error, 185 -1, EPROTONOSUPPORT); 186 if (!asroot && !injail) 187 expect("priv_netinet_ipsec_pfkey(!asroot, !injail)", error, 188 -1, EPERM); 189 if (fd >= 0) 190 (void)close(fd); 191} 192 193 194static void 195priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test, 196 int af) 197{ 198 int error, level, optname; 199 200 switch (af) { 201 case AF_INET: 202 level = IPPROTO_IP; 203 optname = IP_IPSEC_POLICY; 204 break; 205#ifdef INET6 206 case AF_INET6: 207 level = IPPROTO_IPV6; 208 optname = IPV6_IPSEC_POLICY; 209 break; 210#endif 211 default: 212 warnx("%s: unexpected address family", __func__); 213 return; 214 } 215 error = setsockopt(sd, level, optname, 216 bypassbuf, ipsec_get_policylen(bypassbuf)); 217 if (asroot && injail) 218 expect("priv_netinet_ipsec_policy_bypass(asroot, injail)", 219 error, -1, EACCES); /* see ipsec_set_policy */ 220 if (asroot && !injail) 221 expect("priv_netinet_ipsec_policy_bypass(asroot, !injail)", 222 error, 0, 0); 223 if (!asroot && injail) 224 expect("priv_netinet_ipsec_policy_bypass(!asroot, injail)", 225 error, -1, EACCES); /* see ipsec_set_policy */ 226 if (!asroot && !injail) 227 expect("priv_netinet_ipsec_policy_bypass(!asroot, !injail)", 228 error, -1, EACCES); /* see ipsec_set_policy */ 229} 230 231void 232priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test) 233{ 234 235 priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET); 236} 237 238#ifdef INET6 239void 240priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test) 241{ 242 243 priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6); 244} 245#endif 246 247static void 248priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test, 249 int af) 250{ 251 int error, level, optname; 252 253 switch (af) { 254 case AF_INET: 255 level = IPPROTO_IP; 256 optname = IP_IPSEC_POLICY; 257 break; 258#ifdef INET6 259 case AF_INET6: 260 level = IPPROTO_IPV6; 261 optname = IPV6_IPSEC_POLICY; 262 break; 263#endif 264 default: 265 warnx("%s: unexpected address family", __func__); 266 return; 267 } 268 error = setsockopt(sd, level, optname, 269 entrustbuf, ipsec_get_policylen(entrustbuf)); 270 if (asroot && injail) 271 expect("priv_netinet_ipsec_policy_entrust(asroot, injail)", 272 error, 0, 0); /* XXX ipsec_set_policy */ 273 if (asroot && !injail) 274 expect("priv_netinet_ipsec_policy_entrust(asroot, !injail)", 275 error, 0, 0); 276 if (!asroot && injail) 277 expect("priv_netinet_ipsec_policy_entrust(!asroot, injail)", 278 error, 0, 0); /* XXX ipsec_set_policy */ 279 if (!asroot && !injail) 280 expect("priv_netinet_ipsec_policy_entrust(!asroot, !injail)", 281 error, 0, 0); /* XXX ipsec_set_policy */ 282} 283 284void 285priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test) 286{ 287 288 priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET); 289} 290 291#ifdef INET6 292void 293priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test) 294{ 295 296 priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6); 297} 298#endif 299 300void 301priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail, 302 struct test *test) 303{ 304 305 if (bypassbuf != NULL) { 306 free(bypassbuf); 307 bypassbuf = NULL; 308 } 309 if (sd >= 0) { 310 close(sd); 311 sd = -1; 312 } 313} 314 315void 316priv_netinet_ipsec_policy_entrust_cleanup(int asroot, int injail, 317 struct test *test) 318{ 319 320 if (entrustbuf != NULL) { 321 free(entrustbuf); 322 entrustbuf = NULL; 323 } 324 if (sd >= 0) { 325 close(sd); 326 sd = -1; 327 } 328} 329 330