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 #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 88 int 89 priv_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 98 int 99 priv_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 109 static int 110 priv_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 143 int 144 priv_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 153 int 154 priv_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 163 void 164 priv_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 194 static void 195 priv_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 231 void 232 priv_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 239 void 240 priv_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 247 static void 248 priv_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 284 void 285 priv_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 292 void 293 priv_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 300 void 301 priv_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 315 void 316 priv_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