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 27 /* 28 * Confirm that privilege is required to open a pfkey socket, and that this 29 * is not allowed in jail. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <net/pfkeyv2.h> 35 #include <netinet/in.h> 36 #include <netipsec/ipsec.h> 37 38 #include <err.h> 39 #include <errno.h> 40 #include <stdlib.h> 41 #include <unistd.h> 42 43 #include "main.h" 44 45 static char policy_bypass[] = "in bypass"; 46 static char policy_entrust[] = "in entrust"; 47 static char *bypassbuf = NULL; 48 static char *entrustbuf = NULL; 49 static int sd = -1; 50 51 52 static int 53 priv_netinet_ipsec_policy_bypass_setup_af(int asroot, int injail, 54 struct test *test, int af) 55 { 56 57 bypassbuf = ipsec_set_policy(policy_bypass, sizeof(policy_bypass) - 1); 58 if (bypassbuf == NULL) { 59 warn("%s: ipsec_set_policy(NULL)", __func__); 60 return (-1); 61 } 62 switch (af) { 63 case AF_INET: 64 sd = socket(AF_INET, SOCK_DGRAM, 0); 65 if (sd < 0) { 66 warn("%s: socket4", __func__); 67 return (-1); 68 } 69 break; 70 #ifdef INET6 71 case AF_INET6: 72 sd = socket(AF_INET6, SOCK_DGRAM, 0); 73 if (sd < 0) { 74 warn("%s: socket6", __func__); 75 return (-1); 76 } 77 break; 78 #endif 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 #ifdef INET6 96 int 97 priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail, 98 struct test *test) 99 { 100 101 return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 102 AF_INET6)); 103 } 104 #endif 105 106 107 static int 108 priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail, 109 struct test *test, int af) 110 { 111 112 entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1); 113 if (entrustbuf == NULL) { 114 warn("%s: ipsec_set_policy(NULL)", __func__); 115 return (-1); 116 } 117 switch (af) { 118 case AF_INET: 119 sd = socket(AF_INET, SOCK_DGRAM, 0); 120 if (sd < 0) { 121 warn("%s: socket4", __func__); 122 return (-1); 123 } 124 break; 125 #ifdef INET6 126 case AF_INET6: 127 sd = socket(AF_INET6, SOCK_DGRAM, 0); 128 if (sd < 0) { 129 warn("%s: socket6", __func__); 130 return (-1); 131 } 132 break; 133 #endif 134 default: 135 warnx("%s: unexpected address family", __func__); 136 return (-1); 137 } 138 return (0); 139 } 140 141 int 142 priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail, 143 struct test *test) 144 { 145 146 return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 147 AF_INET)); 148 } 149 150 #ifdef INET6 151 int 152 priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail, 153 struct test *test) 154 { 155 156 return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 157 AF_INET6)); 158 } 159 #endif 160 161 void 162 priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test) 163 { 164 int error, fd; 165 166 fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 167 if (fd < 0) 168 error = -1; 169 else 170 error = 0; 171 /* 172 * The injail checks are not really priv checks but making sure 173 * sys/kern/uipc_socket.c:socreate cred checks are working correctly. 174 */ 175 if (asroot && injail) 176 expect("priv_netinet_ipsec_pfkey(asroot, injail)", error, 177 -1, EPROTONOSUPPORT); 178 if (asroot && !injail) 179 expect("priv_netinet_ipsec_pfkey(asroot, !injail)", error, 180 0, 0); 181 if (!asroot && injail) 182 expect("priv_netinet_ipsec_pfkey(!asroot, injail)", error, 183 -1, EPROTONOSUPPORT); 184 if (!asroot && !injail) 185 expect("priv_netinet_ipsec_pfkey(!asroot, !injail)", error, 186 -1, EPERM); 187 if (fd >= 0) 188 (void)close(fd); 189 } 190 191 192 static void 193 priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test, 194 int af) 195 { 196 int error, level, optname; 197 198 switch (af) { 199 case AF_INET: 200 level = IPPROTO_IP; 201 optname = IP_IPSEC_POLICY; 202 break; 203 #ifdef INET6 204 case AF_INET6: 205 level = IPPROTO_IPV6; 206 optname = IPV6_IPSEC_POLICY; 207 break; 208 #endif 209 default: 210 warnx("%s: unexpected address family", __func__); 211 return; 212 } 213 error = setsockopt(sd, level, optname, 214 bypassbuf, ipsec_get_policylen(bypassbuf)); 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, 0, 0); 221 if (!asroot && injail) 222 expect("priv_netinet_ipsec_policy_bypass(!asroot, injail)", 223 error, -1, EACCES); /* see ipsec_set_policy */ 224 if (!asroot && !injail) 225 expect("priv_netinet_ipsec_policy_bypass(!asroot, !injail)", 226 error, -1, EACCES); /* see ipsec_set_policy */ 227 } 228 229 void 230 priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test) 231 { 232 233 priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET); 234 } 235 236 #ifdef INET6 237 void 238 priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test) 239 { 240 241 priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6); 242 } 243 #endif 244 245 static void 246 priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test, 247 int af) 248 { 249 int error, level, optname; 250 251 switch (af) { 252 case AF_INET: 253 level = IPPROTO_IP; 254 optname = IP_IPSEC_POLICY; 255 break; 256 #ifdef INET6 257 case AF_INET6: 258 level = IPPROTO_IPV6; 259 optname = IPV6_IPSEC_POLICY; 260 break; 261 #endif 262 default: 263 warnx("%s: unexpected address family", __func__); 264 return; 265 } 266 error = setsockopt(sd, level, optname, 267 entrustbuf, ipsec_get_policylen(entrustbuf)); 268 if (asroot && injail) 269 expect("priv_netinet_ipsec_policy_entrust(asroot, injail)", 270 error, 0, 0); /* XXX ipsec_set_policy */ 271 if (asroot && !injail) 272 expect("priv_netinet_ipsec_policy_entrust(asroot, !injail)", 273 error, 0, 0); 274 if (!asroot && injail) 275 expect("priv_netinet_ipsec_policy_entrust(!asroot, injail)", 276 error, 0, 0); /* XXX ipsec_set_policy */ 277 if (!asroot && !injail) 278 expect("priv_netinet_ipsec_policy_entrust(!asroot, !injail)", 279 error, 0, 0); /* XXX ipsec_set_policy */ 280 } 281 282 void 283 priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test) 284 { 285 286 priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET); 287 } 288 289 #ifdef INET6 290 void 291 priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test) 292 { 293 294 priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6); 295 } 296 #endif 297 298 void 299 priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail, 300 struct test *test) 301 { 302 303 if (bypassbuf != NULL) { 304 free(bypassbuf); 305 bypassbuf = NULL; 306 } 307 if (sd >= 0) { 308 close(sd); 309 sd = -1; 310 } 311 } 312 313 void 314 priv_netinet_ipsec_policy_entrust_cleanup(int asroot, int injail, 315 struct test *test) 316 { 317 318 if (entrustbuf != NULL) { 319 free(entrustbuf); 320 entrustbuf = NULL; 321 } 322 if (sd >= 0) { 323 close(sd); 324 sd = -1; 325 } 326 } 327 328