Changeset View
Changeset View
Standalone View
Standalone View
lib/libcasper/services/cap_net/tests/net_test.c
- This file was added.
/*- | |||||
* Copyright (c) 2020 Mariusz Zaborski <oshogbo@FreeBSD.org> | |||||
* All rights reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
* POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/socket.h> | |||||
#include <netinet/in.h> | |||||
#include <arpa/inet.h> | |||||
#include <errno.h> | |||||
#include <netdb.h> | |||||
#include <atf-c.h> | |||||
#include <libcasper.h> | |||||
#include <casper/cap_net.h> | |||||
#define TEST_DOMAIN_0 "example.com" | |||||
#define TEST_DOMAIN_1 "freebsd.org" | |||||
#define TEST_IPV4 "1.1.1.1" | |||||
#define TEST_IPV6 "2001:4860:4860::8888" | |||||
#define TEST_BIND_IPV4 "127.0.0.1" | |||||
static cap_channel_t * | |||||
create_network_service(void) | |||||
{ | |||||
cap_channel_t *capcas, *capnet; | |||||
capcas = cap_init(); | |||||
ATF_REQUIRE(capcas != NULL); | |||||
capnet = cap_service_open(capcas, "system.net"); | |||||
ATF_REQUIRE(capnet != NULL); | |||||
cap_close(capcas); | |||||
return (capnet); | |||||
} | |||||
static int | |||||
test_getnameinfo_v4(cap_channel_t *chan, int family, const char *ip) | |||||
{ | |||||
struct sockaddr_in ipaddr; | |||||
char capfn[MAXHOSTNAMELEN]; | |||||
char origfn[MAXHOSTNAMELEN]; | |||||
int ret; | |||||
memset(&ipaddr, 0, sizeof(ipaddr)); | |||||
ipaddr.sin_family = family; | |||||
inet_pton(family, ip, &ipaddr.sin_addr); | |||||
ret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr), | |||||
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD); | |||||
if (ret != 0) { | |||||
return (ret); | |||||
} | |||||
ret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn, | |||||
sizeof(origfn), NULL, 0, NI_NAMEREQD); | |||||
ATF_REQUIRE(ret == 0); | |||||
ATF_REQUIRE(strcmp(origfn, capfn) == 0); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_getnameinfo_v6(cap_channel_t *chan, const char *ip) | |||||
{ | |||||
struct sockaddr_in6 ipaddr; | |||||
char capfn[MAXHOSTNAMELEN]; | |||||
char origfn[MAXHOSTNAMELEN]; | |||||
int ret; | |||||
memset(&ipaddr, 0, sizeof(ipaddr)); | |||||
ipaddr.sin6_family = AF_INET6; | |||||
inet_pton(AF_INET6, ip, &ipaddr.sin6_addr); | |||||
ret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr), | |||||
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD); | |||||
if (ret != 0) { | |||||
return (ret); | |||||
} | |||||
ret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn, | |||||
sizeof(origfn), NULL, 0, NI_NAMEREQD); | |||||
ATF_REQUIRE(ret == 0); | |||||
ATF_REQUIRE(strcmp(origfn, capfn) == 0); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_getnameinfo(cap_channel_t *chan, int family, const char *ip) | |||||
{ | |||||
if (family == AF_INET6) { | |||||
return (test_getnameinfo_v6(chan, ip)); | |||||
} | |||||
return (test_getnameinfo_v4(chan, family, ip)); | |||||
} | |||||
static int | |||||
test_gethostbyaddr_v4(cap_channel_t *chan, int family, const char *ip) | |||||
{ | |||||
struct in_addr ipaddr; | |||||
struct hostent *caphp, *orighp; | |||||
memset(&ipaddr, 0, sizeof(ipaddr)); | |||||
inet_pton(AF_INET, ip, &ipaddr); | |||||
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), family); | |||||
if (caphp == NULL) { | |||||
return (h_errno); | |||||
} | |||||
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), family); | |||||
ATF_REQUIRE(orighp != NULL); | |||||
ATF_REQUIRE(strcmp(caphp->h_name, caphp->h_name) == 0); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_gethostbyaddr_v6(cap_channel_t *chan, const char *ip) | |||||
{ | |||||
struct in6_addr ipaddr; | |||||
struct hostent *caphp, *orighp; | |||||
memset(&ipaddr, 0, sizeof(ipaddr)); | |||||
inet_pton(AF_INET6, ip, &ipaddr); | |||||
caphp = cap_gethostbyaddr(chan, &ipaddr, sizeof(ipaddr), AF_INET6); | |||||
if (caphp == NULL) | |||||
return (h_errno); | |||||
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), AF_INET6); | |||||
ATF_REQUIRE(orighp != NULL); | |||||
ATF_REQUIRE(strcmp(caphp->h_name, caphp->h_name) == 0); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_gethostbyaddr(cap_channel_t *chan, int family, const char *ip) | |||||
{ | |||||
if (family == AF_INET6) { | |||||
return (test_gethostbyaddr_v6(chan, ip)); | |||||
} else { | |||||
return (test_gethostbyaddr_v4(chan, family, ip)); | |||||
} | |||||
} | |||||
static int | |||||
test_getaddrinfo(cap_channel_t *chan, int family, const char *domain, | |||||
const char *servname) | |||||
{ | |||||
struct addrinfo hints, *capres, *origres, *res0, *res1; | |||||
bool found; | |||||
int ret; | |||||
memset(&hints, 0, sizeof(hints)); | |||||
hints.ai_family = family; | |||||
hints.ai_socktype = SOCK_STREAM; | |||||
ret = cap_getaddrinfo(chan, domain, servname, &hints, &capres); | |||||
if (ret != 0) { | |||||
return (ret); | |||||
} | |||||
ret = getaddrinfo(domain, servname, &hints, &origres); | |||||
ATF_REQUIRE(ret == 0); | |||||
for (res0 = capres; res0 != NULL; res0 = res0->ai_next) { | |||||
found = false; | |||||
for (res1 = origres; res1 != NULL; res1 = res1->ai_next) { | |||||
if (res1->ai_addrlen == res0->ai_addrlen && | |||||
memcmp(res1->ai_addr, res0->ai_addr, | |||||
res0->ai_addrlen) == 0) { | |||||
found = true; | |||||
break; | |||||
} | |||||
} | |||||
ATF_REQUIRE(found); | |||||
} | |||||
freeaddrinfo(capres); | |||||
freeaddrinfo(origres); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_gethostbyname(cap_channel_t *chan, int family, const char *domain) | |||||
{ | |||||
struct hostent *caphp, *orighp; | |||||
caphp = cap_gethostbyname2(chan, domain, family); | |||||
if (caphp == NULL) { | |||||
return (h_errno); | |||||
} | |||||
orighp = gethostbyname2(domain, family); | |||||
ATF_REQUIRE(orighp != NULL); | |||||
ATF_REQUIRE(strcmp(caphp->h_name, orighp->h_name) == 0); | |||||
return (0); | |||||
} | |||||
static int | |||||
test_bind(cap_channel_t *chan, const char *ip) | |||||
{ | |||||
struct sockaddr_in ipv4; | |||||
int capfd, ret, serrno; | |||||
capfd = socket(AF_INET, SOCK_STREAM, 0); | |||||
ATF_REQUIRE(capfd > 0); | |||||
memset(&ipv4, 0, sizeof(ipv4)); | |||||
ipv4.sin_family = AF_INET; | |||||
inet_pton(AF_INET, ip, &ipv4.sin_addr); | |||||
ret = cap_bind(chan, capfd, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
serrno = errno; | |||||
close(capfd); | |||||
return (ret < 0 ? serrno : 0); | |||||
} | |||||
static int | |||||
test_connect(cap_channel_t *chan, const char *ip, unsigned short port) | |||||
{ | |||||
struct sockaddr_in ipv4; | |||||
int capfd, ret, serrno; | |||||
capfd = socket(AF_INET, SOCK_STREAM, 0); | |||||
ATF_REQUIRE(capfd > 0); | |||||
memset(&ipv4, 0, sizeof(ipv4)); | |||||
ipv4.sin_family = AF_INET; | |||||
ipv4.sin_port = htons(port); | |||||
inet_pton(AF_INET, ip, &ipv4.sin_addr); | |||||
ret = cap_connect(chan, capfd, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
serrno = errno; | |||||
close(capfd); | |||||
return (ret < 0 ? serrno : 0); | |||||
} | |||||
static void | |||||
test_extend_mode(cap_channel_t *capnet, int current) | |||||
{ | |||||
cap_net_limit_t *limit; | |||||
const int rights[] = { | |||||
CAPNET_ADDR2NAME, | |||||
CAPNET_NAME2ADDR, | |||||
CAPNET_OBSOLETE_ADDR2NAME, | |||||
CAPNET_OBSOLETE_NAME2ADDR, | |||||
CAPNET_CONNECT, | |||||
CAPNET_BIND, | |||||
CAPNET_CONNECTDNS | |||||
}; | |||||
size_t i; | |||||
for (i = 0; i < nitems(rights); i++) { | |||||
if (current == rights[i]) | |||||
continue; | |||||
limit = cap_net_limit_init(capnet, current | rights[i]); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
} | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_mode); | |||||
ATF_TC_BODY(capnet__limits_addr2name_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == ENOTCAPABLE); | |||||
test_extend_mode(capnet, CAPNET_ADDR2NAME); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name_family); | |||||
ATF_TC_BODY(capnet__limits_addr2name_family, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
int family[] = { AF_INET6, AF_INET }; | |||||
capnet = create_network_service(); | |||||
/* Limit to AF_INET6 and AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, family, nitems(family)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
/* Limit to AF_INET6 and AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, &family[0], 1); | |||||
cap_net_limit_addr2name_family(limit, &family[1], 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
/* Limit to AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_addr2name); | |||||
ATF_TC_BODY(capnet__limits_addr2name, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct sockaddr_in ipaddrv4; | |||||
struct sockaddr_in6 ipaddrv6; | |||||
capnet = create_network_service(); | |||||
/* Limit to TEST_IPV4 and TEST_IPV6. */ | |||||
memset(&ipaddrv4, 0, sizeof(ipaddrv4)); | |||||
memset(&ipaddrv6, 0, sizeof(ipaddrv6)); | |||||
ipaddrv4.sin_family = AF_INET; | |||||
inet_pton(AF_INET, TEST_IPV4, &ipaddrv4.sin_addr); | |||||
ipaddrv6.sin6_family = AF_INET6; | |||||
inet_pton(AF_INET6, TEST_IPV6, &ipaddrv6.sin6_addr); | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv4, | |||||
sizeof(ipaddrv4)); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv6, | |||||
sizeof(ipaddrv6)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, "127.0.0.1") == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv4, | |||||
sizeof(ipaddrv4)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, "127.0.0.1") == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_addr2name_mode); | |||||
ATF_TC_BODY(capnet__limits_obsolete_addr2name_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == ENOTCAPABLE); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_addr2name_family); | |||||
ATF_TC_BODY(capnet__limits_obsolete_addr2name_family, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
int family[] = { AF_INET6, AF_INET }; | |||||
capnet = create_network_service(); | |||||
/* Limit to AF_INET6 and AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, family, nitems(family)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, PF_LINK, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET6 and AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, &family[0], 1); | |||||
cap_net_limit_addr2name_family(limit, &family[1], 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, PF_LINK, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, PF_LINK, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_addr2name); | |||||
ATF_TC_BODY(capnet__limits_obsolete_addr2name, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct in_addr ipaddrv4; | |||||
struct in6_addr ipaddrv6; | |||||
capnet = create_network_service(); | |||||
/* Limit to TEST_IPV4 and TEST_IPV6. */ | |||||
memset(&ipaddrv4, 0, sizeof(ipaddrv4)); | |||||
memset(&ipaddrv6, 0, sizeof(ipaddrv6)); | |||||
inet_pton(AF_INET, TEST_IPV4, &ipaddrv4); | |||||
inet_pton(AF_INET6, TEST_IPV6, &ipaddrv6); | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv4, | |||||
sizeof(ipaddrv4)); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv6, | |||||
sizeof(ipaddrv6)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, "127.0.0.1") == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_addr2name(limit, (struct sockaddr *)&ipaddrv4, | |||||
sizeof(ipaddrv4)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, "127.0.0.1") == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_ADDR2NAME); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_mode); | |||||
ATF_TC_BODY(capnet__limits_name2addr_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == ENOTCAPABLE); | |||||
test_extend_mode(capnet, CAPNET_ADDR2NAME); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts); | |||||
ATF_TC_BODY(capnet__limits_name2addr_hosts, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* Limit to TEST_DOMAIN_0 and localhost only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr(limit, "localhost", NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, "localhost", NULL) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, NULL) == | |||||
ENOTCAPABLE); | |||||
/* Limit to TEST_DOMAIN_0 only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, "localhost", NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_strict); | |||||
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* | |||||
* Limit to TEST_DOMAIN_0 and HTTP service. | |||||
*/ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, "http"); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, "http") == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, "snmp") == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, "http") == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_hosts_servnames_mix); | |||||
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* | |||||
* Limit to TEST_DOMAIN_0 and any servnamex, and any domain with | |||||
* servname HTTP. | |||||
*/ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr(limit, NULL, "http"); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, "http") == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, "http") == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, "snmp") == | |||||
ENOTCAPABLE); | |||||
/* Limit to HTTTP servname only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, NULL, "http"); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, "http") == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, "http") == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_1, "snmp") == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_name2addr_family); | |||||
ATF_TC_BODY(capnet__limits_name2addr_family, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
int family[] = { AF_INET6, AF_INET }; | |||||
capnet = create_network_service(); | |||||
/* Limit to AF_INET and AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, family, nitems(family)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET6, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, PF_LINK, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET and AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, &family[0], 1); | |||||
cap_net_limit_name2addr_family(limit, &family[1], 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET6, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, PF_LINK, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
/* Limit to AF_INET6 only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET6, TEST_DOMAIN_0, NULL) == | |||||
0); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, PF_LINK, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_name2addr_mode); | |||||
ATF_TC_BODY(capnet__limits_obsolete_name2addr_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == ENOTCAPABLE); | |||||
test_extend_mode(capnet, CAPNET_ADDR2NAME); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_name2addr_hosts); | |||||
ATF_TC_BODY(capnet__limits_obsolete_name2addr_hosts, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* Limit to TEST_DOMAIN_0 and localhost only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr(limit, "localhost", NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, "localhost") == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_1) == ENOTCAPABLE); | |||||
/* Limit to TEST_DOMAIN_0 only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, "localhost") == ENOTCAPABLE); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_1) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_name2addr_family); | |||||
ATF_TC_BODY(capnet__limits_obsolete_name2addr_family, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
int family[] = { AF_INET6, AF_INET }; | |||||
capnet = create_network_service(); | |||||
/* Limit to AF_INET and AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, family, nitems(family)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET6, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, PF_LINK, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
/* Limit to AF_INET and AF_INET6. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, &family[0], 1); | |||||
cap_net_limit_name2addr_family(limit, &family[1], 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET6, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, PF_LINK, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
/* Limit to AF_INET6 only. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_DOMAIN_0, NULL); | |||||
cap_net_limit_name2addr_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET6, TEST_DOMAIN_0) == 0); | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, PF_LINK, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_bind_mode); | |||||
ATF_TC_BODY(capnet__limits_bind_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_BIND); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == 0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == ENOTCAPABLE); | |||||
test_extend_mode(capnet, CAPNET_ADDR2NAME); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_bind); | |||||
ATF_TC_BODY(capnet__limits_bind, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct sockaddr_in ipv4; | |||||
capnet = create_network_service(); | |||||
limit = cap_net_limit_init(capnet, CAPNET_BIND); | |||||
ATF_REQUIRE(limit != NULL); | |||||
memset(&ipv4, 0, sizeof(ipv4)); | |||||
ipv4.sin_family = AF_INET; | |||||
inet_pton(AF_INET, TEST_BIND_IPV4, &ipv4.sin_addr); | |||||
cap_net_limit_bind(limit, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == 0); | |||||
ATF_REQUIRE(test_bind(capnet, "127.0.0.2") == ENOTCAPABLE); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_connect_mode); | |||||
ATF_TC_BODY(capnet__limits_connect_mode, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
capnet = create_network_service(); | |||||
/* LIMIT */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECT); | |||||
ATF_REQUIRE(limit != NULL); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
/* ALLOWED */ | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == 0); | |||||
/* DISALLOWED */ | |||||
ATF_REQUIRE( | |||||
test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) == | |||||
ENOTCAPABLE); | |||||
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == ENOTCAPABLE); | |||||
test_extend_mode(capnet, CAPNET_ADDR2NAME); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_connect); | |||||
ATF_TC_BODY(capnet__limits_connect, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct sockaddr_in ipv4; | |||||
capnet = create_network_service(); | |||||
/* Limit only to TEST_IPV4 on port 80 and 443. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECT); | |||||
ATF_REQUIRE(limit != NULL); | |||||
memset(&ipv4, 0, sizeof(ipv4)); | |||||
ipv4.sin_family = AF_INET; | |||||
ipv4.sin_port = htons(80); | |||||
inet_pton(AF_INET, TEST_IPV4, &ipv4.sin_addr); | |||||
cap_net_limit_connect(limit, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
ipv4.sin_port = htons(443); | |||||
cap_net_limit_connect(limit, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == 0); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 80) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 443) == 0); | |||||
/* Limit only to TEST_IPV4 on port 443. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECT); | |||||
cap_net_limit_connect(limit, (struct sockaddr *)&ipv4, sizeof(ipv4)); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 433) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 80) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 443) == 0); | |||||
/* Unable to set empty limits. Empty limits means full access. */ | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECT); | |||||
ATF_REQUIRE(cap_net_limit(limit) != 0); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_connecttodns); | |||||
ATF_TC_BODY(capnet__limits_connecttodns, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct addrinfo hints, *capres, *res; | |||||
int family[] = { AF_INET }; | |||||
capnet = create_network_service(); | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECTDNS | | |||||
CAPNET_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_IPV4, "80"); | |||||
cap_net_limit_name2addr_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
memset(&hints, 0, sizeof(hints)); | |||||
hints.ai_family = AF_INET; | |||||
hints.ai_socktype = SOCK_STREAM; | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
ATF_REQUIRE(cap_getaddrinfo(capnet, TEST_IPV4, "80", &hints, &capres) == | |||||
0); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
for (res = capres; res != NULL; res = res->ai_next) { | |||||
int s; | |||||
ATF_REQUIRE(res->ai_family == AF_INET); | |||||
ATF_REQUIRE(res->ai_socktype == SOCK_STREAM); | |||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |||||
ATF_REQUIRE(s >= 0); | |||||
ATF_REQUIRE(cap_connect(capnet, s, res->ai_addr, | |||||
res->ai_addrlen) == 0); | |||||
close(s); | |||||
} | |||||
freeaddrinfo(capres); | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TC_WITHOUT_HEAD(capnet__limits_obsolete_connecttodns); | |||||
ATF_TC_BODY(capnet__limits_obsolete_connecttodns, tc) | |||||
{ | |||||
cap_channel_t *capnet; | |||||
cap_net_limit_t *limit; | |||||
struct hostent *caphp; | |||||
struct in_addr ipaddr; | |||||
struct sockaddr_in connaddr; | |||||
int family[] = { AF_INET }; | |||||
int i; | |||||
capnet = create_network_service(); | |||||
limit = cap_net_limit_init(capnet, CAPNET_CONNECTDNS | | |||||
CAPNET_OBSOLETE_NAME2ADDR); | |||||
ATF_REQUIRE(limit != NULL); | |||||
cap_net_limit_name2addr(limit, TEST_IPV4, NULL); | |||||
cap_net_limit_name2addr_family(limit, family, 1); | |||||
ATF_REQUIRE(cap_net_limit(limit) == 0); | |||||
memset(&ipaddr, 0, sizeof(ipaddr)); | |||||
inet_pton(AF_INET, TEST_IPV4, &ipaddr); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
caphp = cap_gethostbyname2(capnet, TEST_IPV4, AF_INET); | |||||
ATF_REQUIRE(caphp != NULL); | |||||
ATF_REQUIRE(caphp->h_addrtype == AF_INET); | |||||
ATF_REQUIRE(test_connect(capnet, "8.8.8.8", 433) == ENOTCAPABLE); | |||||
for (i = 0; caphp->h_addr_list[i] != NULL; i++) { | |||||
int s; | |||||
s = socket(AF_INET, SOCK_STREAM, 0); | |||||
ATF_REQUIRE(s >= 0); | |||||
memset(&connaddr, 0, sizeof(connaddr)); | |||||
connaddr.sin_family = AF_INET; | |||||
memcpy((char *)&connaddr.sin_addr.s_addr, | |||||
(char *)caphp->h_addr_list[i], caphp->h_length); | |||||
connaddr.sin_port = htons(80); | |||||
ATF_REQUIRE(cap_connect(capnet, s, (struct sockaddr *)&connaddr, | |||||
sizeof(connaddr)) == 0); | |||||
close(s); | |||||
} | |||||
cap_close(capnet); | |||||
} | |||||
ATF_TP_ADD_TCS(tp) | |||||
{ | |||||
ATF_TP_ADD_TC(tp, capnet__limits_addr2name_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_addr2name_family); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_addr2name); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_addr2name_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_addr2name_family); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_addr2name); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_name2addr_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_name2addr_hosts); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_name2addr_hosts_servnames_strict); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_name2addr_hosts_servnames_mix); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_name2addr_family); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_name2addr_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_name2addr_hosts); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_name2addr_family); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_bind_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_bind); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_connect_mode); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_connect); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_connecttodns); | |||||
ATF_TP_ADD_TC(tp, capnet__limits_obsolete_connecttodns); | |||||
return (atf_no_error()); | |||||
} |