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