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; 72f3d220fbSBjoern A. Zeeb case AF_INET6: 73f3d220fbSBjoern A. Zeeb sd = socket(AF_INET6, SOCK_DGRAM, 0); 74f3d220fbSBjoern A. Zeeb if (sd < 0) { 75f3d220fbSBjoern A. Zeeb warn("%s: socket6", __func__); 76f3d220fbSBjoern A. Zeeb return (-1); 77f3d220fbSBjoern A. Zeeb } 78f3d220fbSBjoern A. Zeeb break; 79f3d220fbSBjoern A. Zeeb default: 80f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 81f3d220fbSBjoern A. Zeeb return (-1); 82f3d220fbSBjoern A. Zeeb } 836007da5fSBjoern A. Zeeb return (0); 846007da5fSBjoern A. Zeeb } 856007da5fSBjoern A. Zeeb 86f3d220fbSBjoern A. Zeeb int 87f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass_setup(int asroot, int injail, 88f3d220fbSBjoern A. Zeeb struct test *test) 89f3d220fbSBjoern A. Zeeb { 90f3d220fbSBjoern A. Zeeb 91f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 92f3d220fbSBjoern A. Zeeb AF_INET)); 93f3d220fbSBjoern A. Zeeb } 94f3d220fbSBjoern A. Zeeb 95f3d220fbSBjoern A. Zeeb int 96f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass_setup(int asroot, int injail, 97f3d220fbSBjoern A. Zeeb struct test *test) 98f3d220fbSBjoern A. Zeeb { 99f3d220fbSBjoern A. Zeeb 100f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_bypass_setup_af(asroot, injail, test, 101f3d220fbSBjoern A. Zeeb AF_INET6)); 102f3d220fbSBjoern A. Zeeb } 103f3d220fbSBjoern A. Zeeb 104f3d220fbSBjoern A. Zeeb 105f3d220fbSBjoern A. Zeeb 106f3d220fbSBjoern A. Zeeb static int 107f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail, 108f3d220fbSBjoern A. Zeeb struct test *test, int af) 109f3d220fbSBjoern A. Zeeb { 110f3d220fbSBjoern A. Zeeb 111f3d220fbSBjoern A. Zeeb entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1); 112f3d220fbSBjoern A. Zeeb if (entrustbuf == NULL) { 113f3d220fbSBjoern A. Zeeb warn("%s: ipsec_set_policy(NULL)", __func__); 114f3d220fbSBjoern A. Zeeb return (-1); 115f3d220fbSBjoern A. Zeeb } 116f3d220fbSBjoern A. Zeeb switch (af) { 117f3d220fbSBjoern A. Zeeb case AF_INET: 118f3d220fbSBjoern A. Zeeb sd = socket(AF_INET, SOCK_DGRAM, 0); 119f3d220fbSBjoern A. Zeeb if (sd < 0) { 120f3d220fbSBjoern A. Zeeb warn("%s: socket4", __func__); 121f3d220fbSBjoern A. Zeeb return (-1); 122f3d220fbSBjoern A. Zeeb } 123f3d220fbSBjoern A. Zeeb break; 124f3d220fbSBjoern A. Zeeb case AF_INET6: 125f3d220fbSBjoern A. Zeeb sd = socket(AF_INET6, SOCK_DGRAM, 0); 126f3d220fbSBjoern A. Zeeb if (sd < 0) { 127f3d220fbSBjoern A. Zeeb warn("%s: socket6", __func__); 128f3d220fbSBjoern A. Zeeb return (-1); 129f3d220fbSBjoern A. Zeeb } 130f3d220fbSBjoern A. Zeeb break; 131f3d220fbSBjoern A. Zeeb default: 132f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 133f3d220fbSBjoern A. Zeeb return (-1); 134f3d220fbSBjoern A. Zeeb } 135f3d220fbSBjoern A. Zeeb return (0); 136f3d220fbSBjoern A. Zeeb } 137f3d220fbSBjoern A. Zeeb 138f3d220fbSBjoern A. Zeeb int 139f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust_setup(int asroot, int injail, 140f3d220fbSBjoern A. Zeeb struct test *test) 141f3d220fbSBjoern A. Zeeb { 142f3d220fbSBjoern A. Zeeb 143f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 144f3d220fbSBjoern A. Zeeb AF_INET)); 145f3d220fbSBjoern A. Zeeb } 146f3d220fbSBjoern A. Zeeb 147f3d220fbSBjoern A. Zeeb int 148f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust_setup(int asroot, int injail, 149f3d220fbSBjoern A. Zeeb struct test *test) 150f3d220fbSBjoern A. Zeeb { 151f3d220fbSBjoern A. Zeeb 152f3d220fbSBjoern A. Zeeb return (priv_netinet_ipsec_policy_entrust_setup_af(asroot, injail, test, 153f3d220fbSBjoern A. Zeeb AF_INET6)); 154f3d220fbSBjoern A. Zeeb } 155f3d220fbSBjoern A. Zeeb 156f3d220fbSBjoern A. Zeeb 1576007da5fSBjoern A. Zeeb void 1586007da5fSBjoern A. Zeeb priv_netinet_ipsec_pfkey(int asroot, int injail, struct test *test) 1596007da5fSBjoern A. Zeeb { 1606007da5fSBjoern A. Zeeb int error, fd; 1616007da5fSBjoern A. Zeeb 1626007da5fSBjoern A. Zeeb fd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); 1636007da5fSBjoern A. Zeeb if (fd < 0) 1646007da5fSBjoern A. Zeeb error = -1; 1656007da5fSBjoern A. Zeeb else 1666007da5fSBjoern A. Zeeb error = 0; 1676007da5fSBjoern A. Zeeb /* 1686007da5fSBjoern A. Zeeb * The injail checks are not really priv checks but making sure 1696007da5fSBjoern A. Zeeb * sys/kern/uipc_socket.c:socreate cred checks are working correctly. 1706007da5fSBjoern A. Zeeb */ 1716007da5fSBjoern A. Zeeb if (asroot && injail) 1726007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(asroot, injail)", error, 1736007da5fSBjoern A. Zeeb -1, EPROTONOSUPPORT); 1746007da5fSBjoern A. Zeeb if (asroot && !injail) 1756007da5fSBjoern A. Zeeb expect("priv_netinet_ipsec_pfkey(asroot, !injail)", error, 1766007da5fSBjoern A. Zeeb 0, 0); 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 -1, EPERM); 1836007da5fSBjoern A. Zeeb if (fd >= 0) 1846007da5fSBjoern A. Zeeb (void)close(fd); 1856007da5fSBjoern A. Zeeb } 1866007da5fSBjoern A. Zeeb 187f3d220fbSBjoern A. Zeeb 188f3d220fbSBjoern A. Zeeb static void 189f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(int asroot, int injail, struct test *test, 190f3d220fbSBjoern A. Zeeb int af) 191f3d220fbSBjoern A. Zeeb { 192f3d220fbSBjoern A. Zeeb int error, level, optname; 193f3d220fbSBjoern A. Zeeb 194f3d220fbSBjoern A. Zeeb switch (af) { 195f3d220fbSBjoern A. Zeeb case AF_INET: 196f3d220fbSBjoern A. Zeeb level = IPPROTO_IP; 197f3d220fbSBjoern A. Zeeb optname = IP_IPSEC_POLICY; 198f3d220fbSBjoern A. Zeeb break; 199f3d220fbSBjoern A. Zeeb case AF_INET6: 200f3d220fbSBjoern A. Zeeb level = IPPROTO_IPV6; 201f3d220fbSBjoern A. Zeeb optname = IPV6_IPSEC_POLICY; 202f3d220fbSBjoern A. Zeeb break; 203f3d220fbSBjoern A. Zeeb default: 204f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 205f3d220fbSBjoern A. Zeeb return; 206f3d220fbSBjoern A. Zeeb } 207f3d220fbSBjoern A. Zeeb error = setsockopt(sd, level, optname, 208f3d220fbSBjoern A. Zeeb bypassbuf, ipsec_get_policylen(bypassbuf)); 209f3d220fbSBjoern A. Zeeb if (asroot && injail) 210f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(asroot, injail)", 211f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 212f3d220fbSBjoern A. Zeeb if (asroot && !injail) 213f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(asroot, !injail)", 214f3d220fbSBjoern A. Zeeb error, 0, 0); 215f3d220fbSBjoern A. Zeeb if (!asroot && injail) 216f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(!asroot, injail)", 217f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 218f3d220fbSBjoern A. Zeeb if (!asroot && !injail) 219f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_bypass(!asroot, !injail)", 220f3d220fbSBjoern A. Zeeb error, -1, EACCES); /* see ipsec_set_policy */ 221f3d220fbSBjoern A. Zeeb } 222f3d220fbSBjoern A. Zeeb 2236007da5fSBjoern A. Zeeb void 224f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_bypass(int asroot, int injail, struct test *test) 2256007da5fSBjoern A. Zeeb { 2266007da5fSBjoern A. Zeeb 227f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET); 228f3d220fbSBjoern A. Zeeb } 229f3d220fbSBjoern A. Zeeb 230f3d220fbSBjoern A. Zeeb void 231f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_bypass(int asroot, int injail, struct test *test) 232f3d220fbSBjoern A. Zeeb { 233f3d220fbSBjoern A. Zeeb 234f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_af(asroot, injail, test, AF_INET6); 235f3d220fbSBjoern A. Zeeb } 236f3d220fbSBjoern A. Zeeb 237f3d220fbSBjoern A. Zeeb 238f3d220fbSBjoern A. Zeeb static void 239f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(int asroot, int injail, struct test *test, 240f3d220fbSBjoern A. Zeeb int af) 241f3d220fbSBjoern A. Zeeb { 242f3d220fbSBjoern A. Zeeb int error, level, optname; 243f3d220fbSBjoern A. Zeeb 244f3d220fbSBjoern A. Zeeb switch (af) { 245f3d220fbSBjoern A. Zeeb case AF_INET: 246f3d220fbSBjoern A. Zeeb level = IPPROTO_IP; 247f3d220fbSBjoern A. Zeeb optname = IP_IPSEC_POLICY; 248f3d220fbSBjoern A. Zeeb break; 249f3d220fbSBjoern A. Zeeb case AF_INET6: 250f3d220fbSBjoern A. Zeeb level = IPPROTO_IPV6; 251f3d220fbSBjoern A. Zeeb optname = IPV6_IPSEC_POLICY; 252f3d220fbSBjoern A. Zeeb break; 253f3d220fbSBjoern A. Zeeb default: 254f3d220fbSBjoern A. Zeeb warnx("%s: unexpected address family", __func__); 255f3d220fbSBjoern A. Zeeb return; 256f3d220fbSBjoern A. Zeeb } 257f3d220fbSBjoern A. Zeeb error = setsockopt(sd, level, optname, 258f3d220fbSBjoern A. Zeeb entrustbuf, ipsec_get_policylen(entrustbuf)); 259f3d220fbSBjoern A. Zeeb if (asroot && injail) 260f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(asroot, injail)", 261f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 262f3d220fbSBjoern A. Zeeb if (asroot && !injail) 263f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(asroot, !injail)", 264f3d220fbSBjoern A. Zeeb error, 0, 0); 265f3d220fbSBjoern A. Zeeb if (!asroot && injail) 266f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(!asroot, injail)", 267f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 268f3d220fbSBjoern A. Zeeb if (!asroot && !injail) 269f3d220fbSBjoern A. Zeeb expect("priv_netinet_ipsec_policy_entrust(!asroot, !injail)", 270f3d220fbSBjoern A. Zeeb error, 0, 0); /* XXX ipsec_set_policy */ 271f3d220fbSBjoern A. Zeeb } 272f3d220fbSBjoern A. Zeeb 273f3d220fbSBjoern A. Zeeb void 274f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy4_entrust(int asroot, int injail, struct test *test) 275f3d220fbSBjoern A. Zeeb { 276f3d220fbSBjoern A. Zeeb 277f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET); 278f3d220fbSBjoern A. Zeeb } 279f3d220fbSBjoern A. Zeeb 280f3d220fbSBjoern A. Zeeb void 281f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy6_entrust(int asroot, int injail, struct test *test) 282f3d220fbSBjoern A. Zeeb { 283f3d220fbSBjoern A. Zeeb 284f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_af(asroot, injail, test, AF_INET6); 285f3d220fbSBjoern A. Zeeb } 286f3d220fbSBjoern A. Zeeb 287f3d220fbSBjoern A. Zeeb 288f3d220fbSBjoern A. Zeeb void 289f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_bypass_cleanup(int asroot, int injail, 290f3d220fbSBjoern A. Zeeb struct test *test) 291f3d220fbSBjoern A. Zeeb { 292f3d220fbSBjoern A. Zeeb 293f3d220fbSBjoern A. Zeeb if (bypassbuf != NULL) { 294f3d220fbSBjoern A. Zeeb free(bypassbuf); 295f3d220fbSBjoern A. Zeeb bypassbuf = NULL; 296f3d220fbSBjoern A. Zeeb } 297f3d220fbSBjoern A. Zeeb if (sd >= 0) { 298f3d220fbSBjoern A. Zeeb close(sd); 299f3d220fbSBjoern A. Zeeb sd = -1; 300f3d220fbSBjoern A. Zeeb } 301f3d220fbSBjoern A. Zeeb } 302f3d220fbSBjoern A. Zeeb 303f3d220fbSBjoern A. Zeeb void 304f3d220fbSBjoern A. Zeeb priv_netinet_ipsec_policy_entrust_cleanup(int asroot, int injail, 305f3d220fbSBjoern A. Zeeb struct test *test) 306f3d220fbSBjoern A. Zeeb { 307f3d220fbSBjoern A. Zeeb 308f3d220fbSBjoern A. Zeeb if (entrustbuf != NULL) { 309f3d220fbSBjoern A. Zeeb free(entrustbuf); 310f3d220fbSBjoern A. Zeeb entrustbuf = NULL; 311f3d220fbSBjoern A. Zeeb } 312f3d220fbSBjoern A. Zeeb if (sd >= 0) { 313f3d220fbSBjoern A. Zeeb close(sd); 314f3d220fbSBjoern A. Zeeb sd = -1; 315f3d220fbSBjoern A. Zeeb } 3166007da5fSBjoern A. Zeeb } 3176007da5fSBjoern A. Zeeb 318