#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"
#define TEST_PORT 80
#define TEST_PORT_STR "80"
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 capret, sysret;
memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.sin_family = family;
inet_pton(family, ip, &ipaddr.sin_addr);
capret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
if (capret != 0 && capret == ENOTCAPABLE)
return (ENOTCAPABLE);
sysret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
sizeof(origfn), NULL, 0, NI_NAMEREQD);
if (sysret != 0) {
atf_tc_skip("getnameinfo(%s) failed: %s",
ip, gai_strerror(sysret));
}
ATF_REQUIRE(capret == 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 capret, sysret;
memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.sin6_family = AF_INET6;
inet_pton(AF_INET6, ip, &ipaddr.sin6_addr);
capret = cap_getnameinfo(chan, (struct sockaddr *)&ipaddr, sizeof(ipaddr),
capfn, sizeof(capfn), NULL, 0, NI_NAMEREQD);
if (capret != 0 && capret == ENOTCAPABLE)
return (ENOTCAPABLE);
sysret = getnameinfo((struct sockaddr *)&ipaddr, sizeof(ipaddr), origfn,
sizeof(origfn), NULL, 0, NI_NAMEREQD);
if (sysret != 0) {
atf_tc_skip("getnameinfo(%s) failed: %s",
ip, gai_strerror(sysret));
}
ATF_REQUIRE(capret == 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 && h_errno == ENOTCAPABLE)
return (ENOTCAPABLE);
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), family);
if (orighp == NULL)
atf_tc_skip("gethostbyaddr(%s) failed", ip);
ATF_REQUIRE(caphp != NULL);
ATF_REQUIRE(strcmp(orighp->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 && h_errno == ENOTCAPABLE)
return (ENOTCAPABLE);
orighp = gethostbyaddr(&ipaddr, sizeof(ipaddr), AF_INET6);
if (orighp == NULL)
atf_tc_skip("gethostbyaddr(%s) failed", ip);
ATF_REQUIRE(caphp != NULL);
ATF_REQUIRE(strcmp(orighp->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 capret, sysret;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
capret = cap_getaddrinfo(chan, domain, servname, &hints, &capres);
if (capret != 0 && capret == ENOTCAPABLE)
return (capret);
sysret = getaddrinfo(domain, servname, &hints, &origres);
if (sysret != 0)
atf_tc_skip("getaddrinfo(%s) failed: %s",
domain, gai_strerror(sysret));
ATF_REQUIRE(capret == 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 && h_errno == ENOTCAPABLE)
return (h_errno);
orighp = gethostbyname2(domain, family);
if (orighp == NULL)
atf_tc_skip("gethostbyname2(%s) failed", domain);
ATF_REQUIRE(caphp != 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;
ATF_REQUIRE(close(capfd) == 0);
if (ret < 0 && serrno != ENOTCAPABLE) {
int sd;
sd = socket(AF_INET, SOCK_STREAM, 0);
ATF_REQUIRE(sd >= 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 = connect(sd, (struct sockaddr *)&ipv4, sizeof(ipv4));
ATF_REQUIRE(ret < 0);
ATF_REQUIRE_MSG(errno == serrno, "errno %d != serrno %d",
errno, serrno);
ATF_REQUIRE(close(sd) == 0);
atf_tc_skip("connect(%s:%d) failed: %s",
ip, port, strerror(serrno));
}
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_DEPRECATED_ADDR2NAME,
CAPNET_DEPRECATED_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(capnet__getnameinfo);
ATF_TC_HEAD(capnet__getnameinfo, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__getnameinfo, tc)
{
cap_channel_t *capnet;
capnet = create_network_service();
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0);
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET6, TEST_IPV6) == 0);
cap_close(capnet);
}
ATF_TC(capnet__connect);
ATF_TC_HEAD(capnet__connect, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__connect, tc)
{
cap_channel_t *capnet;
capnet = create_network_service();
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == 0);
cap_close(capnet);
}
ATF_TC(capnet__bind);
ATF_TC_HEAD(capnet__bind, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__bind, tc)
{
cap_channel_t *capnet;
capnet = create_network_service();
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == 0);
cap_close(capnet);
}
ATF_TC(capnet__getaddrinfo);
ATF_TC_HEAD(capnet__getaddrinfo, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__getaddrinfo, tc)
{
cap_channel_t *capnet;
struct addrinfo hints, *capres;
capnet = create_network_service();
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
ATF_REQUIRE(cap_getaddrinfo(capnet, TEST_IPV4, "80", &hints, &capres) ==
0);
cap_close(capnet);
}
ATF_TC(capnet__gethostbyname);
ATF_TC_HEAD(capnet__gethostbyname, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__gethostbyname, tc)
{
cap_channel_t *capnet;
capnet = create_network_service();
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0);
cap_close(capnet);
}
ATF_TC(capnet__gethostbyaddr);
ATF_TC_HEAD(capnet__gethostbyaddr, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__gethostbyaddr, tc)
{
cap_channel_t *capnet;
capnet = create_network_service();
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0);
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET6, TEST_IPV6) == 0);
cap_close(capnet);
}
ATF_TC(capnet__getnameinfo_buffer);
ATF_TC_HEAD(capnet__getnameinfo_buffer, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__getnameinfo_buffer, tc)
{
cap_channel_t *chan;
struct sockaddr_in sin;
int ret;
struct {
char host[sizeof(TEST_IPV4)];
char host_canary;
char serv[sizeof(TEST_PORT_STR)];
char serv_canary;
} buffers;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(TEST_PORT);
ret = inet_pton(AF_INET, TEST_IPV4, &sin.sin_addr);
ATF_REQUIRE_EQ(1, ret);
memset(&buffers, '!', sizeof(buffers));
chan = create_network_service();
ret = cap_getnameinfo(chan, (struct sockaddr *)&sin, sizeof(sin),
buffers.host, sizeof(buffers.host),
buffers.serv, sizeof(buffers.serv),
NI_NUMERICHOST | NI_NUMERICSERV);
ATF_REQUIRE_EQ_MSG(0, ret, "%d", ret);
ATF_CHECK_EQ(0, strcmp(TEST_IPV4, buffers.host));
ATF_CHECK_EQ(0, strcmp(TEST_PORT_STR, buffers.serv));
ATF_CHECK_EQ('!', buffers.host_canary);
ATF_CHECK_EQ('!', buffers.serv_canary);
cap_close(chan);
}
ATF_TC(capnet__limits_addr2name_mode);
ATF_TC_HEAD(capnet__limits_addr2name_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_addr2name_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_getnameinfo(capnet, AF_INET, TEST_IPV4) == 0);
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(capnet__limits_addr2name_family);
ATF_TC_HEAD(capnet__limits_addr2name_family, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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 = 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 = 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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_addr2name);
ATF_TC_HEAD(capnet__limits_addr2name, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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();
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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_deprecated_addr2name_mode);
ATF_TC_HEAD(capnet__limits_deprecated_addr2name_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_addr2name_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_ADDR2NAME);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_gethostbyaddr(capnet, AF_INET, TEST_IPV4) == 0);
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(capnet__limits_deprecated_addr2name_family);
ATF_TC_HEAD(capnet__limits_deprecated_addr2name_family, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_addr2name_family, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
int family[] = { AF_INET6, AF_INET };
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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);
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_ADDR2NAME);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_deprecated_addr2name);
ATF_TC_HEAD(capnet__limits_deprecated_addr2name, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_addr2name, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
struct in_addr ipaddrv4;
struct in6_addr ipaddrv6;
capnet = create_network_service();
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_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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);
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_ADDR2NAME);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_name2addr_mode);
ATF_TC_HEAD(capnet__limits_name2addr_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_name2addr_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_getaddrinfo(capnet, AF_INET, TEST_DOMAIN_0, NULL) ==
0);
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(capnet__limits_name2addr_hosts);
ATF_TC_HEAD(capnet__limits_name2addr_hosts, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_name2addr_hosts, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(limit != NULL);
cap_net_limit_name2addr(limit, TEST_DOMAIN_1, NULL);
ATF_REQUIRE(cap_net_limit(limit) != 0);
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, TEST_DOMAIN_1, NULL);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_name2addr_hosts_servnames_strict);
ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_strict, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_strict, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_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);
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_name2addr_hosts_servnames_mix);
ATF_TC_HEAD(capnet__limits_name2addr_hosts_servnames_mix, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_name2addr_hosts_servnames_mix, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_name2addr_family);
ATF_TC_HEAD(capnet__limits_name2addr_family, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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 = 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 = 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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_deprecated_name2addr_mode);
ATF_TC_HEAD(capnet__limits_deprecated_name2addr_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_NAME2ADDR);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_gethostbyname(capnet, AF_INET, TEST_DOMAIN_0) == 0);
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(capnet__limits_deprecated_name2addr_hosts);
ATF_TC_HEAD(capnet__limits_deprecated_name2addr_hosts, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_hosts, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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);
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_deprecated_name2addr_family);
ATF_TC_HEAD(capnet__limits_deprecated_name2addr_family, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_name2addr_family, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
int family[] = { AF_INET6, AF_INET };
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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 = cap_net_limit_init(capnet, CAPNET_DEPRECATED_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);
limit = cap_net_limit_init(capnet, CAPNET_DEPRECATED_NAME2ADDR);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_bind_mode);
ATF_TC_HEAD(capnet__limits_bind_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_bind_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_BIND);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_bind(capnet, TEST_BIND_IPV4) == 0);
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(capnet__limits_bind);
ATF_TC_HEAD(capnet__limits_bind, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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(capnet__limits_connect_mode);
ATF_TC_HEAD(capnet__limits_connect_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_connect_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_CONNECT);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == 0);
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(capnet__limits_connect_dns_mode);
ATF_TC_HEAD(capnet__limits_connect_dns_mode, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_connect_dns_mode, tc)
{
cap_channel_t *capnet;
cap_net_limit_t *limit;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_CONNECT | CAPNET_CONNECTDNS);
ATF_REQUIRE(limit != NULL);
ATF_REQUIRE(cap_net_limit(limit) == 0);
ATF_REQUIRE(test_connect(capnet, TEST_IPV4, 80) == 0);
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(capnet__limits_connect);
ATF_TC_HEAD(capnet__limits_connect, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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 = 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 = 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);
limit = cap_net_limit_init(capnet, CAPNET_CONNECT);
ATF_REQUIRE(cap_net_limit(limit) != 0);
cap_close(capnet);
}
ATF_TC(capnet__limits_connecttodns);
ATF_TC_HEAD(capnet__limits_connecttodns, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
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 };
int error;
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);
error = cap_connect(capnet, s, res->ai_addr,
res->ai_addrlen);
if (error != 0 && errno != ENOTCAPABLE)
atf_tc_skip("unable to connect: %s", strerror(errno));
ATF_REQUIRE(error == 0);
ATF_REQUIRE(close(s) == 0);
}
freeaddrinfo(capres);
cap_close(capnet);
}
ATF_TC(capnet__limits_deprecated_connecttodns);
ATF_TC_HEAD(capnet__limits_deprecated_connecttodns, tc)
{
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
}
ATF_TC_BODY(capnet__limits_deprecated_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 error, i;
capnet = create_network_service();
limit = cap_net_limit_init(capnet, CAPNET_CONNECTDNS |
CAPNET_DEPRECATED_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);
error = cap_connect(capnet, s, (struct sockaddr *)&connaddr,
sizeof(connaddr));
if (error != 0 && errno != ENOTCAPABLE)
atf_tc_skip("unable to connect: %s", strerror(errno));
ATF_REQUIRE(error == 0);
ATF_REQUIRE(close(s) == 0);
}
cap_close(capnet);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, capnet__connect);
ATF_TP_ADD_TC(tp, capnet__bind);
ATF_TP_ADD_TC(tp, capnet__getnameinfo);
ATF_TP_ADD_TC(tp, capnet__getaddrinfo);
ATF_TP_ADD_TC(tp, capnet__gethostbyname);
ATF_TP_ADD_TC(tp, capnet__gethostbyaddr);
ATF_TP_ADD_TC(tp, capnet__getnameinfo_buffer);
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_deprecated_addr2name_mode);
ATF_TP_ADD_TC(tp, capnet__limits_deprecated_addr2name_family);
ATF_TP_ADD_TC(tp, capnet__limits_deprecated_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_deprecated_name2addr_mode);
ATF_TP_ADD_TC(tp, capnet__limits_deprecated_name2addr_hosts);
ATF_TP_ADD_TC(tp, capnet__limits_deprecated_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_dns_mode);
ATF_TP_ADD_TC(tp, capnet__limits_connect);
ATF_TP_ADD_TC(tp, capnet__limits_connecttodns);
ATF_TP_ADD_TC(tp, capnet__limits_deprecated_connecttodns);
return (atf_no_error());
}