16007da5fSBjoern A. Zeeb /*- 26007da5fSBjoern A. Zeeb * Copyright (c) 2007 Bjoern A. Zeeb 36007da5fSBjoern A. Zeeb * All rights reserved. 46007da5fSBjoern A. Zeeb * 56007da5fSBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without 66007da5fSBjoern A. Zeeb * modification, are permitted provided that the following conditions 76007da5fSBjoern A. Zeeb * are met: 86007da5fSBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright 96007da5fSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer. 106007da5fSBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright 116007da5fSBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the 126007da5fSBjoern A. Zeeb * documentation and/or other materials provided with the distribution. 136007da5fSBjoern A. Zeeb * 146007da5fSBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 156007da5fSBjoern A. Zeeb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 166007da5fSBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 176007da5fSBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY, 186007da5fSBjoern A. Zeeb * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 196007da5fSBjoern A. Zeeb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 206007da5fSBjoern A. Zeeb * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 216007da5fSBjoern A. Zeeb * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 226007da5fSBjoern A. Zeeb * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 236007da5fSBjoern A. Zeeb * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 246007da5fSBjoern A. Zeeb * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 256007da5fSBjoern A. Zeeb * 266007da5fSBjoern A. Zeeb * $FreeBSD$ 276007da5fSBjoern A. Zeeb */ 286007da5fSBjoern A. Zeeb 296007da5fSBjoern A. Zeeb /* 306007da5fSBjoern A. Zeeb * Confirm that privilege is required to open a pfkey socket, and that this 316007da5fSBjoern A. Zeeb * is not allowed in jail. 326007da5fSBjoern A. Zeeb */ 336007da5fSBjoern A. Zeeb 346007da5fSBjoern A. Zeeb #include <sys/types.h> 356007da5fSBjoern A. Zeeb #include <sys/socket.h> 366007da5fSBjoern A. Zeeb #include <net/pfkeyv2.h> 37f3d220fbSBjoern A. Zeeb #include <netinet/in.h> 38f3d220fbSBjoern A. Zeeb #include <netipsec/ipsec.h> 396007da5fSBjoern A. Zeeb 40f3d220fbSBjoern A. Zeeb #include <err.h> 416007da5fSBjoern A. Zeeb #include <errno.h> 42f3d220fbSBjoern A. Zeeb #include <stdlib.h> 436007da5fSBjoern A. Zeeb #include <unistd.h> 446007da5fSBjoern A. Zeeb 456007da5fSBjoern A. Zeeb #include "main.h" 466007da5fSBjoern A. Zeeb 47f3d220fbSBjoern A. Zeeb static char policy_bypass[] = "in bypass"; 48f3d220fbSBjoern A. Zeeb static char policy_entrust[] = "in entrust"; 49f3d220fbSBjoern A. Zeeb static char *bypassbuf = NULL; 50f3d220fbSBjoern A. Zeeb static char *entrustbuf = NULL; 51f3d220fbSBjoern A. Zeeb static int sd = -1; 52f3d220fbSBjoern A. Zeeb 53f3d220fbSBjoern A. Zeeb 54f3d220fbSBjoern A. Zeeb static int 55f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_setup_af(int asroot, int injail, 56f3d220fbSBjoern A. Zeeb struct test *test, int af) 576007da5fSBjoern A. Zeeb { 586007da5fSBjoern A. Zeeb 59f3d220fbSBjoern A. Zeeb bypassbuf = ipsec_set_policy(policy_bypass, sizeof(policy_bypass) - 1); 60f3d220fbSBjoern A. Zeeb if (bypassbuf == NULL) { 61f3d220fbSBjoern A. Zeeb warn("%s: ipsec_set_policy(NULL)", __func__); 62f3d220fbSBjoern A. Zeeb return (-1); 63f3d220fbSBjoern A. Zeeb } 64f3d220fbSBjoern A. Zeeb switch (af) { 65f3d220fbSBjoern A. Zeeb case AF_INET: 66f3d220fbSBjoern A. Zeeb sd = socket(AF_INET, SOCK_DGRAM, 0); 67f3d220fbSBjoern A. Zeeb if (sd < 0) { 68f3d220fbSBjoern A. Zeeb warn("%s: socket4", __func__); 69f3d220fbSBjoern A. Zeeb return (-1); 70f3d220fbSBjoern A. Zeeb } 71f3d220fbSBjoern A. Zeeb break; 72e7fba5c7SBjoern A. Zeeb #ifdef INET6 73f3d220fbSBjoern A. Zeeb case AF_INET6: 74f3d220fbSBjoern A. Zeeb sd = socket(AF_INET6, SOCK_DGRAM, 0); 75f3d220fbSBjoern A. Zeeb if (sd < 0) { 76f3d220fbSBjoern A. Zeeb warn("%s: socket6", __func__); 77f3d220fbSBjoern A. Zeeb return (-1); 78f3d220fbSBjoern A. Zeeb } 79f3d220fbSBjoern A. Zeeb break; 80e7fba5c7SBjoern A. Zeeb #endif 81f3d220fbSBjoern A. Zeeb default: 82f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 83f3d220fbSBjoern A. Zeeb return (-1); 84f3d220fbSBjoern A. Zeeb } 856007da5fSBjoern A. Zeeb return (0); 866007da5fSBjoern A. Zeeb } 876007da5fSBjoern A. Zeeb 88f3d220fbSBjoern A. Zeeb int 89f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass_setup(int asroot, int injail, 90f3d220fbSBjoern A. Zeeb struct test *test) 91f3d220fbSBjoern A. Zeeb { 92f3d220fbSBjoern A. Zeeb 93f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 94f3d220fbSBjoern A. Zeeb AF_INET)); 95f3d220fbSBjoern A. Zeeb } 96f3d220fbSBjoern A. Zeeb 97e7fba5c7SBjoern A. Zeeb #ifdef INET6 98f3d220fbSBjoern A. Zeeb int 99f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail, 100f3d220fbSBjoern A. Zeeb struct test *test) 101f3d220fbSBjoern A. Zeeb { 102f3d220fbSBjoern A. Zeeb 103f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 104f3d220fbSBjoern A. Zeeb AF_INET6)); 105f3d220fbSBjoern A. Zeeb } 106e7fba5c7SBjoern A. Zeeb #endif 107f3d220fbSBjoern A. Zeeb 108f3d220fbSBjoern A. Zeeb 109f3d220fbSBjoern A. Zeeb static int 110f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail, 111f3d220fbSBjoern A. Zeeb struct test *test, int af) 112f3d220fbSBjoern A. Zeeb { 113f3d220fbSBjoern A. Zeeb 114f3d220fbSBjoern A. Zeeb entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1); 115f3d220fbSBjoern A. Zeeb if (entrustbuf == NULL) { 116f3d220fbSBjoern A. Zeeb warn("%s: ipsec_set_policy(NULL)", __func__); 117f3d220fbSBjoern A. Zeeb return (-1); 118f3d220fbSBjoern A. Zeeb } 119f3d220fbSBjoern A. Zeeb switch (af) { 120f3d220fbSBjoern A. Zeeb case AF_INET: 121f3d220fbSBjoern A. Zeeb sd = socket(AF_INET, SOCK_DGRAM, 0); 122f3d220fbSBjoern A. Zeeb if (sd < 0) { 123f3d220fbSBjoern A. Zeeb warn("%s: socket4", __func__); 124f3d220fbSBjoern A. Zeeb return (-1); 125f3d220fbSBjoern A. Zeeb } 126f3d220fbSBjoern A. Zeeb break; 127e7fba5c7SBjoern A. Zeeb #ifdef INET6 128f3d220fbSBjoern A. Zeeb case AF_INET6: 129f3d220fbSBjoern A. Zeeb sd = socket(AF_INET6, SOCK_DGRAM, 0); 130f3d220fbSBjoern A. Zeeb if (sd < 0) { 131f3d220fbSBjoern A. Zeeb warn("%s: socket6", __func__); 132f3d220fbSBjoern A. Zeeb return (-1); 133f3d220fbSBjoern A. Zeeb } 134f3d220fbSBjoern A. Zeeb break; 135e7fba5c7SBjoern A. Zeeb #endif 136f3d220fbSBjoern A. Zeeb default: 137f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 138f3d220fbSBjoern A. Zeeb return (-1); 139f3d220fbSBjoern A. Zeeb } 140f3d220fbSBjoern A. Zeeb return (0); 141f3d220fbSBjoern A. Zeeb } 142f3d220fbSBjoern A. Zeeb 143f3d220fbSBjoern A. Zeeb int 144f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail, 145f3d220fbSBjoern A. Zeeb struct test *test) 146f3d220fbSBjoern A. Zeeb { 147f3d220fbSBjoern A. Zeeb 148f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 149f3d220fbSBjoern A. Zeeb AF_INET)); 150f3d220fbSBjoern A. Zeeb } 151f3d220fbSBjoern A. Zeeb 152e7fba5c7SBjoern A. Zeeb #ifdef INET6 153f3d220fbSBjoern A. Zeeb int 154f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail, 155f3d220fbSBjoern A. Zeeb struct test *test) 156f3d220fbSBjoern A. Zeeb { 157f3d220fbSBjoern A. Zeeb 158f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 159f3d220fbSBjoern A. Zeeb AF_INET6)); 160f3d220fbSBjoern A. Zeeb } 161e7fba5c7SBjoern A. Zeeb #endif 162f3d220fbSBjoern A. Zeeb 1636007da5fSBjoern A. Zeeb void 1646007da5fSBjoern A. Zeeb priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test) 1656007da5fSBjoern A. Zeeb { 1666007da5fSBjoern A. Zeeb int error, fd; 1676007da5fSBjoern A. Zeeb 1686007da5fSBjoern A. Zeeb fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 1696007da5fSBjoern A. Zeeb if (fd < 0) 1706007da5fSBjoern A. Zeeb error = -1; 1716007da5fSBjoern A. Zeeb else 1726007da5fSBjoern A. Zeeb error = 0; 1736007da5fSBjoern A. Zeeb /* 1746007da5fSBjoern A. Zeeb * The injail checks are not really priv checks but making sure 1756007da5fSBjoern A. Zeeb * sys/kern/uipc_socket.c:socreate cred checks are working correctly. 1766007da5fSBjoern A. Zeeb */ 1776007da5fSBjoern A. Zeeb if (asroot && injail) 1786007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(asroot, injail)", error, 1796007da5fSBjoern A. Zeeb -1, EPROTONOSUPPORT); 1806007da5fSBjoern A. Zeeb if (asroot && !injail) 1816007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(asroot, !injail)", error, 1826007da5fSBjoern A. Zeeb 0, 0); 1836007da5fSBjoern A. Zeeb if (!asroot && injail) 1846007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(!asroot, injail)", error, 1856007da5fSBjoern A. Zeeb -1, EPROTONOSUPPORT); 1866007da5fSBjoern A. Zeeb if (!asroot && !injail) 1876007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(!asroot, !injail)", error, 1886007da5fSBjoern A. Zeeb -1, EPERM); 1896007da5fSBjoern A. Zeeb if (fd >= 0) 1906007da5fSBjoern A. Zeeb (void)close(fd); 1916007da5fSBjoern A. Zeeb } 1926007da5fSBjoern A. Zeeb 193f3d220fbSBjoern A. Zeeb 194f3d220fbSBjoern A. Zeeb static void 195f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test, 196f3d220fbSBjoern A. Zeeb int af) 197f3d220fbSBjoern A. Zeeb { 198f3d220fbSBjoern A. Zeeb int error, level, optname; 199f3d220fbSBjoern A. Zeeb 200f3d220fbSBjoern A. Zeeb switch (af) { 201f3d220fbSBjoern A. Zeeb case AF_INET: 202f3d220fbSBjoern A. Zeeb level = IPPROTO_IP; 203f3d220fbSBjoern A. Zeeb optname = IP_IPSEC_POLICY; 204f3d220fbSBjoern A. Zeeb break; 205e7fba5c7SBjoern A. Zeeb #ifdef INET6 206f3d220fbSBjoern A. Zeeb case AF_INET6: 207f3d220fbSBjoern A. Zeeb level = IPPROTO_IPV6; 208f3d220fbSBjoern A. Zeeb optname = IPV6_IPSEC_POLICY; 209f3d220fbSBjoern A. Zeeb break; 210e7fba5c7SBjoern A. Zeeb #endif 211f3d220fbSBjoern A. Zeeb default: 212f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 213f3d220fbSBjoern A. Zeeb return; 214f3d220fbSBjoern A. Zeeb } 215f3d220fbSBjoern A. Zeeb error = setsockopt(sd, level, optname, 216f3d220fbSBjoern A. Zeeb bypassbuf, ipsec_get_policylen(bypassbuf)); 217f3d220fbSBjoern A. Zeeb if (asroot && injail) 218f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(asroot, injail)", 219f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 220f3d220fbSBjoern A. Zeeb if (asroot && !injail) 221f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(asroot, !injail)", 222f3d220fbSBjoern A. Zeeb error, 0, 0); 223f3d220fbSBjoern A. Zeeb if (!asroot && injail) 224f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(!asroot, injail)", 225f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 226f3d220fbSBjoern A. Zeeb if (!asroot && !injail) 227f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(!asroot, !injail)", 228f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 229f3d220fbSBjoern A. Zeeb } 230f3d220fbSBjoern A. Zeeb 2316007da5fSBjoern A. Zeeb void 232f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test) 2336007da5fSBjoern A. Zeeb { 2346007da5fSBjoern A. Zeeb 235f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET); 236f3d220fbSBjoern A. Zeeb } 237f3d220fbSBjoern A. Zeeb 238e7fba5c7SBjoern A. Zeeb #ifdef INET6 239f3d220fbSBjoern A. Zeeb void 240f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test) 241f3d220fbSBjoern A. Zeeb { 242f3d220fbSBjoern A. Zeeb 243f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6); 244f3d220fbSBjoern A. Zeeb } 245e7fba5c7SBjoern A. Zeeb #endif 246f3d220fbSBjoern A. Zeeb 247f3d220fbSBjoern A. Zeeb static void 248f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test, 249f3d220fbSBjoern A. Zeeb int af) 250f3d220fbSBjoern A. Zeeb { 251f3d220fbSBjoern A. Zeeb int error, level, optname; 252f3d220fbSBjoern A. Zeeb 253f3d220fbSBjoern A. Zeeb switch (af) { 254f3d220fbSBjoern A. Zeeb case AF_INET: 255f3d220fbSBjoern A. Zeeb level = IPPROTO_IP; 256f3d220fbSBjoern A. Zeeb optname = IP_IPSEC_POLICY; 257f3d220fbSBjoern A. Zeeb break; 258e7fba5c7SBjoern A. Zeeb #ifdef INET6 259f3d220fbSBjoern A. Zeeb case AF_INET6: 260f3d220fbSBjoern A. Zeeb level = IPPROTO_IPV6; 261f3d220fbSBjoern A. Zeeb optname = IPV6_IPSEC_POLICY; 262f3d220fbSBjoern A. Zeeb break; 263e7fba5c7SBjoern A. Zeeb #endif 264f3d220fbSBjoern A. Zeeb default: 265f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 266f3d220fbSBjoern A. Zeeb return; 267f3d220fbSBjoern A. Zeeb } 268f3d220fbSBjoern A. Zeeb error = setsockopt(sd, level, optname, 269f3d220fbSBjoern A. Zeeb entrustbuf, ipsec_get_policylen(entrustbuf)); 270f3d220fbSBjoern A. Zeeb if (asroot && injail) 271f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(asroot, injail)", 272f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 273f3d220fbSBjoern A. Zeeb if (asroot && !injail) 274f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(asroot, !injail)", 275f3d220fbSBjoern A. Zeeb error, 0, 0); 276f3d220fbSBjoern A. Zeeb if (!asroot && injail) 277f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(!asroot, injail)", 278f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 279f3d220fbSBjoern A. Zeeb if (!asroot && !injail) 280f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(!asroot, !injail)", 281f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 282f3d220fbSBjoern A. Zeeb } 283f3d220fbSBjoern A. Zeeb 284f3d220fbSBjoern A. Zeeb void 285f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test) 286f3d220fbSBjoern A. Zeeb { 287f3d220fbSBjoern A. Zeeb 288f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET); 289f3d220fbSBjoern A. Zeeb } 290f3d220fbSBjoern A. Zeeb 291e7fba5c7SBjoern A. Zeeb #ifdef INET6 292f3d220fbSBjoern A. Zeeb void 293f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test) 294f3d220fbSBjoern A. Zeeb { 295f3d220fbSBjoern A. Zeeb 296f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6); 297f3d220fbSBjoern A. Zeeb } 298e7fba5c7SBjoern A. Zeeb #endif 299f3d220fbSBjoern A. Zeeb 300f3d220fbSBjoern A. Zeeb void 301f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail, 302f3d220fbSBjoern A. Zeeb struct test *test) 303f3d220fbSBjoern A. Zeeb { 304f3d220fbSBjoern A. Zeeb 305f3d220fbSBjoern A. Zeeb if (bypassbuf != NULL) { 306f3d220fbSBjoern A. Zeeb free(bypassbuf); 307f3d220fbSBjoern A. Zeeb bypassbuf = NULL; 308f3d220fbSBjoern A. Zeeb } 309f3d220fbSBjoern A. Zeeb if (sd >= 0) { 310f3d220fbSBjoern A. Zeeb close(sd); 311f3d220fbSBjoern A. Zeeb sd = -1; 312f3d220fbSBjoern A. Zeeb } 313f3d220fbSBjoern A. Zeeb } 314f3d220fbSBjoern A. Zeeb 315f3d220fbSBjoern A. Zeeb void 316f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_cleanup(int asroot, int injail, 317f3d220fbSBjoern A. Zeeb struct test *test) 318f3d220fbSBjoern A. Zeeb { 319f3d220fbSBjoern A. Zeeb 320f3d220fbSBjoern A. Zeeb if (entrustbuf != NULL) { 321f3d220fbSBjoern A. Zeeb free(entrustbuf); 322f3d220fbSBjoern A. Zeeb entrustbuf = NULL; 323f3d220fbSBjoern A. Zeeb } 324f3d220fbSBjoern A. Zeeb if (sd >= 0) { 325f3d220fbSBjoern A. Zeeb close(sd); 326f3d220fbSBjoern A. Zeeb sd = -1; 327f3d220fbSBjoern A. Zeeb } 3286007da5fSBjoern A. Zeeb } 3296007da5fSBjoern A. Zeeb 330