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$ 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 47 static char policy_bypass[] = "in bypass"; 48 static char policy_entrust[] = "in entrust"; 49 static char *bypassbuf = NULL; 50 static char *entrustbuf = NULL; 51 static int sd = -1; 52 53 54 static int 55 priv_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 86 int 87 priv_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 95 int 96 priv_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 106 static int 107 priv_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 138 int 139 priv_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 147 int 148 priv_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 157 void 158 priv_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 188 static void 189 priv_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 223 void 224 priv_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 230 void 231 priv_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 238 static void 239 priv_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 273 void 274 priv_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 280 void 281 priv_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 288 void 289 priv_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 303 void 304 priv_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