Index: head/lib/libcasper/services/cap_dns/Makefile =================================================================== --- head/lib/libcasper/services/cap_dns/Makefile +++ head/lib/libcasper/services/cap_dns/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PACKAGE=libcasper LIB= cap_dns @@ -15,4 +17,8 @@ CFLAGS+=-I${.CURDIR} +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include Index: head/lib/libcasper/services/cap_dns/tests/Makefile =================================================================== --- head/lib/libcasper/services/cap_dns/tests/Makefile +++ head/lib/libcasper/services/cap_dns/tests/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TAP_TESTS_C= dns_test + +LIBADD+= casper +LIBADD+= cap_dns +LIBADD+= nv + +WARNS?= 3 + +.include Index: head/lib/libcasper/services/cap_dns/tests/dns_test.c =================================================================== --- head/lib/libcasper/services/cap_dns/tests/dns_test.c +++ head/lib/libcasper/services/cap_dns/tests/dns_test.c @@ -0,0 +1,702 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + ntest++; \ +} while (0) +#define CHECKX(expr) do { \ + if ((expr)) { \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + } else { \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + exit(1); \ + } \ + ntest++; \ +} while (0) + +#define GETHOSTBYNAME 0x01 +#define GETHOSTBYNAME2_AF_INET 0x02 +#define GETHOSTBYNAME2_AF_INET6 0x04 +#define GETHOSTBYADDR_AF_INET 0x08 +#define GETHOSTBYADDR_AF_INET6 0x10 +#define GETADDRINFO_AF_UNSPEC 0x20 +#define GETADDRINFO_AF_INET 0x40 +#define GETADDRINFO_AF_INET6 0x80 + +static bool +addrinfo_compare(struct addrinfo *ai0, struct addrinfo *ai1) +{ + struct addrinfo *at0, *at1; + + if (ai0 == NULL && ai1 == NULL) + return (true); + if (ai0 == NULL || ai1 == NULL) + return (false); + + at0 = ai0; + at1 = ai1; + while (true) { + if ((at0->ai_flags == at1->ai_flags) && + (at0->ai_family == at1->ai_family) && + (at0->ai_socktype == at1->ai_socktype) && + (at0->ai_protocol == at1->ai_protocol) && + (at0->ai_addrlen == at1->ai_addrlen) && + (memcmp(at0->ai_addr, at1->ai_addr, + at0->ai_addrlen) == 0)) { + if (at0->ai_canonname != NULL && + at1->ai_canonname != NULL) { + if (strcmp(at0->ai_canonname, + at1->ai_canonname) != 0) { + return (false); + } + } + + if (at0->ai_canonname == NULL && + at1->ai_canonname != NULL) { + return (false); + } + if (at0->ai_canonname != NULL && + at1->ai_canonname == NULL) { + return (false); + } + + if (at0->ai_next == NULL && at1->ai_next == NULL) + return (true); + if (at0->ai_next == NULL || at1->ai_next == NULL) + return (false); + + at0 = at0->ai_next; + at1 = at1->ai_next; + } else { + return (false); + } + } + + /* NOTREACHED */ + fprintf(stderr, "Dead code reached in addrinfo_compare()\n"); + exit(1); +} + +static bool +hostent_aliases_compare(char **aliases0, char **aliases1) +{ + int i0, i1; + + if (aliases0 == NULL && aliases1 == NULL) + return (true); + if (aliases0 == NULL || aliases1 == NULL) + return (false); + + for (i0 = 0; aliases0[i0] != NULL; i0++) { + for (i1 = 0; aliases1[i1] != NULL; i1++) { + if (strcmp(aliases0[i0], aliases1[i1]) == 0) + break; + } + if (aliases1[i1] == NULL) + return (false); + } + + return (true); +} + +static bool +hostent_addr_list_compare(char **addr_list0, char **addr_list1, int length) +{ + int i0, i1; + + if (addr_list0 == NULL && addr_list1 == NULL) + return (true); + if (addr_list0 == NULL || addr_list1 == NULL) + return (false); + + for (i0 = 0; addr_list0[i0] != NULL; i0++) { + for (i1 = 0; addr_list1[i1] != NULL; i1++) { + if (memcmp(addr_list0[i0], addr_list1[i1], length) == 0) + break; + } + if (addr_list1[i1] == NULL) + return (false); + } + + return (true); +} + +static bool +hostent_compare(const struct hostent *hp0, const struct hostent *hp1) +{ + + if (hp0 == NULL && hp1 != NULL) + return (true); + + if (hp0 == NULL || hp1 == NULL) + return (false); + + if (hp0->h_name != NULL || hp1->h_name != NULL) { + if (hp0->h_name == NULL || hp1->h_name == NULL) + return (false); + if (strcmp(hp0->h_name, hp1->h_name) != 0) + return (false); + } + + if (!hostent_aliases_compare(hp0->h_aliases, hp1->h_aliases)) + return (false); + if (!hostent_aliases_compare(hp1->h_aliases, hp0->h_aliases)) + return (false); + + if (hp0->h_addrtype != hp1->h_addrtype) + return (false); + + if (hp0->h_length != hp1->h_length) + return (false); + + if (!hostent_addr_list_compare(hp0->h_addr_list, hp1->h_addr_list, + hp0->h_length)) { + return (false); + } + if (!hostent_addr_list_compare(hp1->h_addr_list, hp0->h_addr_list, + hp0->h_length)) { + return (false); + } + + return (true); +} + +static unsigned int +runtest(cap_channel_t *capdns) +{ + unsigned int result; + struct addrinfo *ais, *aic, hints, *hintsp; + struct hostent *hps, *hpc; + struct in_addr ip4; + struct in6_addr ip6; + + result = 0; + + hps = gethostbyname("example.com"); + if (hps == NULL) + fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); + hpc = cap_gethostbyname(capdns, "example.com"); + if (hostent_compare(hps, hpc)) + result |= GETHOSTBYNAME; + + hps = gethostbyname2("example.com", AF_INET); + if (hps == NULL) + fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); + hpc = cap_gethostbyname2(capdns, "example.com", AF_INET); + if (hostent_compare(hps, hpc)) + result |= GETHOSTBYNAME2_AF_INET; + + hps = gethostbyname2("example.com", AF_INET6); + if (hps == NULL) + fprintf(stderr, "Unable to resolve %s IPv6.\n", "example.com"); + hpc = cap_gethostbyname2(capdns, "example.com", AF_INET6); + if (hostent_compare(hps, hpc)) + result |= GETHOSTBYNAME2_AF_INET6; + + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + hintsp = &hints; + + if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { + fprintf(stderr, + "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", + gai_strerror(errno)); + } + if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { + if (addrinfo_compare(ais, aic)) + result |= GETADDRINFO_AF_UNSPEC; + freeaddrinfo(ais); + freeaddrinfo(aic); + } + + hints.ai_family = AF_INET; + if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { + fprintf(stderr, + "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", + gai_strerror(errno)); + } + if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { + if (addrinfo_compare(ais, aic)) + result |= GETADDRINFO_AF_INET; + freeaddrinfo(ais); + freeaddrinfo(aic); + } + + hints.ai_family = AF_INET6; + if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { + fprintf(stderr, + "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", + gai_strerror(errno)); + } + if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { + if (addrinfo_compare(ais, aic)) + result |= GETADDRINFO_AF_INET6; + freeaddrinfo(ais); + freeaddrinfo(aic); + } + + /* + * 8.8.178.135 is IPv4 address of freefall.freebsd.org + * as of 27 October 2013. + */ + inet_pton(AF_INET, "8.8.178.135", &ip4); + hps = gethostbyaddr(&ip4, sizeof(ip4), AF_INET); + if (hps == NULL) + fprintf(stderr, "Unable to resolve %s.\n", "8.8.178.135"); + hpc = cap_gethostbyaddr(capdns, &ip4, sizeof(ip4), AF_INET); + if (hostent_compare(hps, hpc)) + result |= GETHOSTBYADDR_AF_INET; + + /* + * 2001:1900:2254:206c::16:87 is IPv6 address of freefall.freebsd.org + * as of 27 October 2013. + */ + inet_pton(AF_INET6, "2001:1900:2254:206c::16:87", &ip6); + hps = gethostbyaddr(&ip6, sizeof(ip6), AF_INET6); + if (hps == NULL) { + fprintf(stderr, "Unable to resolve %s.\n", + "2001:1900:2254:206c::16:87"); + } + hpc = cap_gethostbyaddr(capdns, &ip6, sizeof(ip6), AF_INET6); + if (hostent_compare(hps, hpc)) + result |= GETHOSTBYADDR_AF_INET6; + + return (result); +} + +int +main(void) +{ + cap_channel_t *capcas, *capdns, *origcapdns; + const char *types[2]; + int families[2]; + + printf("1..91\n"); + + capcas = cap_init(); + CHECKX(capcas != NULL); + + origcapdns = capdns = cap_service_open(capcas, "system.dns"); + CHECKX(capdns != NULL); + + cap_close(capcas); + + /* No limits set. */ + + CHECK(runtest(capdns) == + (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 | + GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_UNSPEC | GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); + + /* + * Allow: + * type: NAME, ADDR + * family: AF_INET, AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + + CHECK(runtest(capdns) == + (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 | + GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); + + cap_close(capdns); + + /* + * Allow: + * type: NAME + * family: AF_INET, AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + + CHECK(runtest(capdns) == + (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6)); + + cap_close(capdns); + + /* + * Allow: + * type: ADDR + * family: AF_INET, AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + + CHECK(runtest(capdns) == + (GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); + + cap_close(capdns); + + /* + * Allow: + * type: NAME, ADDR + * family: AF_INET + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == + (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYADDR_AF_INET | + GETADDRINFO_AF_INET)); + + cap_close(capdns); + + /* + * Allow: + * type: NAME, ADDR + * family: AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == + (GETHOSTBYNAME2_AF_INET6 | GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_INET6)); + + cap_close(capdns); + + /* Below we also test further limiting capability. */ + + /* + * Allow: + * type: NAME + * family: AF_INET + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET)); + + cap_close(capdns); + + /* + * Allow: + * type: NAME + * family: AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == GETHOSTBYNAME2_AF_INET6); + + cap_close(capdns); + + /* + * Allow: + * type: ADDR + * family: AF_INET + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET | GETADDRINFO_AF_INET)); + + cap_close(capdns); + + /* + * Allow: + * type: ADDR + * family: AF_INET6 + */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == 0); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == 0); + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + types[1] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + families[1] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_INET6)); + + cap_close(capdns); + + /* Trying to rise the limits. */ + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 && + errno == ENOTCAPABLE); + CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 && + errno == ENOTCAPABLE); + + /* Do the limits still hold? */ + CHECK(runtest(capdns) == (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET)); + + cap_close(capdns); + + capdns = cap_clone(origcapdns); + CHECK(capdns != NULL); + + types[0] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 1) == 0); + families[0] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 1) == 0); + + types[0] = "NAME"; + types[1] = "ADDR"; + CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + families[1] = AF_INET6; + CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && + errno == ENOTCAPABLE); + + types[0] = "NAME"; + CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && + errno == ENOTCAPABLE); + families[0] = AF_INET; + CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 && + errno == ENOTCAPABLE); + CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 && + errno == ENOTCAPABLE); + + /* Do the limits still hold? */ + CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET6 | + GETADDRINFO_AF_INET6)); + + cap_close(capdns); + + cap_close(origcapdns); + + exit(0); +} Index: head/lib/libcasper/services/cap_grp/Makefile =================================================================== --- head/lib/libcasper/services/cap_grp/Makefile +++ head/lib/libcasper/services/cap_grp/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PACKAGE=libcasper LIB= cap_grp @@ -15,4 +17,8 @@ CFLAGS+=-I${.CURDIR} +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include Index: head/lib/libcasper/services/cap_grp/tests/Makefile =================================================================== --- head/lib/libcasper/services/cap_grp/tests/Makefile +++ head/lib/libcasper/services/cap_grp/tests/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TAP_TESTS_C= grp_test + +LIBADD+= casper +LIBADD+= cap_grp +LIBADD+= nv + +WARNS?= 3 + +.include Index: head/lib/libcasper/services/cap_grp/tests/grp_test.c =================================================================== --- head/lib/libcasper/services/cap_grp/tests/grp_test.c +++ head/lib/libcasper/services/cap_grp/tests/grp_test.c @@ -0,0 +1,1550 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + ntest++; \ +} while (0) +#define CHECKX(expr) do { \ + if ((expr)) { \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + } else { \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + exit(1); \ + } \ + ntest++; \ +} while (0) + +#define GID_WHEEL 0 +#define GID_OPERATOR 5 + +#define GETGRENT0 0x0001 +#define GETGRENT1 0x0002 +#define GETGRENT2 0x0004 +#define GETGRENT (GETGRENT0 | GETGRENT1 | GETGRENT2) +#define GETGRENT_R0 0x0008 +#define GETGRENT_R1 0x0010 +#define GETGRENT_R2 0x0020 +#define GETGRENT_R (GETGRENT_R0 | GETGRENT_R1 | GETGRENT_R2) +#define GETGRNAM 0x0040 +#define GETGRNAM_R 0x0080 +#define GETGRGID 0x0100 +#define GETGRGID_R 0x0200 +#define SETGRENT 0x0400 + +static bool +group_mem_compare(char **mem0, char **mem1) +{ + int i0, i1; + + if (mem0 == NULL && mem1 == NULL) + return (true); + if (mem0 == NULL || mem1 == NULL) + return (false); + + for (i0 = 0; mem0[i0] != NULL; i0++) { + for (i1 = 0; mem1[i1] != NULL; i1++) { + if (strcmp(mem0[i0], mem1[i1]) == 0) + break; + } + if (mem1[i1] == NULL) + return (false); + } + + return (true); +} + +static bool +group_compare(const struct group *grp0, const struct group *grp1) +{ + + if (grp0 == NULL && grp1 == NULL) + return (true); + if (grp0 == NULL || grp1 == NULL) + return (false); + + if (strcmp(grp0->gr_name, grp1->gr_name) != 0) + return (false); + + if (grp0->gr_passwd != NULL || grp1->gr_passwd != NULL) { + if (grp0->gr_passwd == NULL || grp1->gr_passwd == NULL) + return (false); + if (strcmp(grp0->gr_passwd, grp1->gr_passwd) != 0) + return (false); + } + + if (grp0->gr_gid != grp1->gr_gid) + return (false); + + if (!group_mem_compare(grp0->gr_mem, grp1->gr_mem)) + return (false); + + return (true); +} + +static unsigned int +runtest_cmds(cap_channel_t *capgrp) +{ + char bufs[1024], bufc[1024]; + unsigned int result; + struct group *grps, *grpc; + struct group sts, stc; + + result = 0; + + (void)setgrent(); + if (cap_setgrent(capgrp) == 1) + result |= SETGRENT; + + grps = getgrent(); + grpc = cap_getgrent(capgrp); + if (group_compare(grps, grpc)) { + result |= GETGRENT0; + grps = getgrent(); + grpc = cap_getgrent(capgrp); + if (group_compare(grps, grpc)) + result |= GETGRENT1; + } + + getgrent_r(&sts, bufs, sizeof(bufs), &grps); + cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); + if (group_compare(grps, grpc)) { + result |= GETGRENT_R0; + getgrent_r(&sts, bufs, sizeof(bufs), &grps); + cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); + if (group_compare(grps, grpc)) + result |= GETGRENT_R1; + } + + (void)setgrent(); + if (cap_setgrent(capgrp) == 1) + result |= SETGRENT; + + getgrent_r(&sts, bufs, sizeof(bufs), &grps); + cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); + if (group_compare(grps, grpc)) + result |= GETGRENT_R2; + + grps = getgrent(); + grpc = cap_getgrent(capgrp); + if (group_compare(grps, grpc)) + result |= GETGRENT2; + + grps = getgrnam("wheel"); + grpc = cap_getgrnam(capgrp, "wheel"); + if (group_compare(grps, grpc)) { + grps = getgrnam("operator"); + grpc = cap_getgrnam(capgrp, "operator"); + if (group_compare(grps, grpc)) + result |= GETGRNAM; + } + + getgrnam_r("wheel", &sts, bufs, sizeof(bufs), &grps); + cap_getgrnam_r(capgrp, "wheel", &stc, bufc, sizeof(bufc), &grpc); + if (group_compare(grps, grpc)) { + getgrnam_r("operator", &sts, bufs, sizeof(bufs), &grps); + cap_getgrnam_r(capgrp, "operator", &stc, bufc, sizeof(bufc), + &grpc); + if (group_compare(grps, grpc)) + result |= GETGRNAM_R; + } + + grps = getgrgid(GID_WHEEL); + grpc = cap_getgrgid(capgrp, GID_WHEEL); + if (group_compare(grps, grpc)) { + grps = getgrgid(GID_OPERATOR); + grpc = cap_getgrgid(capgrp, GID_OPERATOR); + if (group_compare(grps, grpc)) + result |= GETGRGID; + } + + getgrgid_r(GID_WHEEL, &sts, bufs, sizeof(bufs), &grps); + cap_getgrgid_r(capgrp, GID_WHEEL, &stc, bufc, sizeof(bufc), &grpc); + if (group_compare(grps, grpc)) { + getgrgid_r(GID_OPERATOR, &sts, bufs, sizeof(bufs), &grps); + cap_getgrgid_r(capgrp, GID_OPERATOR, &stc, bufc, sizeof(bufc), + &grpc); + if (group_compare(grps, grpc)) + result |= GETGRGID_R; + } + + return (result); +} + +static void +test_cmds(cap_channel_t *origcapgrp) +{ + cap_channel_t *capgrp; + const char *cmds[7], *fields[4], *names[5]; + gid_t gids[5]; + + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + + names[0] = "wheel"; + names[1] = "daemon"; + names[2] = "kmem"; + names[3] = "sys"; + names[4] = "operator"; + + gids[0] = 0; + gids[1] = 1; + gids[2] = 2; + gids[3] = 3; + gids[4] = 5; + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: setgrent + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "getgrent"; + cmds[1] = "getgrent_r"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "setgrent"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 | + GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: setgrent + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "getgrent"; + cmds[1] = "getgrent_r"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "setgrent"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 | + GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrent + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent_r"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrent"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrent + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent_r"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrent"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrent_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrent_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrnam, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrent_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrnam"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrent_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrnam + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrnam"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam_r, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrnam + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam_r"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrnam"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM_R | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrnam_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrnam_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, + * getgrgid, getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrnam_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrgid"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrnam_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRGID | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrgid + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrgid"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid_r + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrgid + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrgid"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID_R)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: wheel, daemon, kmem, sys, operator + * gids: + * Disallow: + * cmds: getgrgid_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID)); + + cap_close(capgrp); + + /* + * Allow: + * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, + * getgrgid + * fields: gr_name, gr_passwd, gr_gid, gr_mem + * groups: + * names: + * gids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getgrgid_r + * fields: + * groups: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); + cmds[0] = "setgrent"; + cmds[1] = "getgrent"; + cmds[2] = "getgrent_r"; + cmds[3] = "getgrnam"; + cmds[4] = "getgrnam_r"; + cmds[5] = "getgrgid"; + cmds[6] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getgrgid_r"; + CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID)); + + cap_close(capgrp); +} + +#define GR_NAME 0x01 +#define GR_PASSWD 0x02 +#define GR_GID 0x04 +#define GR_MEM 0x08 + +static unsigned int +group_fields(const struct group *grp) +{ + unsigned int result; + + result = 0; + + if (grp->gr_name != NULL && grp->gr_name[0] != '\0') + result |= GR_NAME; + + if (grp->gr_passwd != NULL && grp->gr_passwd[0] != '\0') + result |= GR_PASSWD; + + if (grp->gr_gid != (gid_t)-1) + result |= GR_GID; + + if (grp->gr_mem != NULL && grp->gr_mem[0] != NULL) + result |= GR_MEM; + + return (result); +} + +static bool +runtest_fields(cap_channel_t *capgrp, unsigned int expected) +{ + char buf[1024]; + struct group *grp; + struct group st; + + (void)cap_setgrent(capgrp); + grp = cap_getgrent(capgrp); + if (group_fields(grp) != expected) + return (false); + + (void)cap_setgrent(capgrp); + cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp); + if (group_fields(grp) != expected) + return (false); + + grp = cap_getgrnam(capgrp, "wheel"); + if (group_fields(grp) != expected) + return (false); + + cap_getgrnam_r(capgrp, "wheel", &st, buf, sizeof(buf), &grp); + if (group_fields(grp) != expected) + return (false); + + grp = cap_getgrgid(capgrp, GID_WHEEL); + if (group_fields(grp) != expected) + return (false); + + cap_getgrgid_r(capgrp, GID_WHEEL, &st, buf, sizeof(buf), &grp); + if (group_fields(grp) != expected) + return (false); + + return (true); +} + +static void +test_fields(cap_channel_t *origcapgrp) +{ + cap_channel_t *capgrp; + const char *fields[4]; + + /* No limits. */ + + CHECK(runtest_fields(origcapgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM)); + + /* + * Allow: + * fields: gr_name, gr_passwd, gr_gid, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_passwd, gr_gid, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_passwd"; + fields[1] = "gr_gid"; + fields[2] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_gid, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_gid"; + fields[2] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_passwd"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_GID | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_passwd, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_passwd, gr_gid + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_passwd + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_gid + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_GID)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_name, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_name"; + fields[1] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_passwd"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_NAME | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_passwd, gr_gid + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_passwd"; + fields[1] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_passwd, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_passwd"; + fields[1] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_gid"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_PASSWD | GR_MEM)); + + cap_close(capgrp); + + /* + * Allow: + * fields: gr_gid, gr_mem + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + fields[0] = "gr_gid"; + fields[1] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); + fields[0] = "gr_name"; + fields[1] = "gr_passwd"; + fields[2] = "gr_gid"; + fields[3] = "gr_mem"; + CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "gr_passwd"; + CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(capgrp, GR_GID | GR_MEM)); + + cap_close(capgrp); +} + +static bool +runtest_groups(cap_channel_t *capgrp, const char **names, const gid_t *gids, + size_t ngroups) +{ + char buf[1024]; + struct group *grp; + struct group st; + unsigned int i, got; + + (void)cap_setgrent(capgrp); + got = 0; + for (;;) { + grp = cap_getgrent(capgrp); + if (grp == NULL) + break; + got++; + for (i = 0; i < ngroups; i++) { + if (strcmp(names[i], grp->gr_name) == 0 && + gids[i] == grp->gr_gid) { + break; + } + } + if (i == ngroups) + return (false); + } + if (got != ngroups) + return (false); + + (void)cap_setgrent(capgrp); + got = 0; + for (;;) { + cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp); + if (grp == NULL) + break; + got++; + for (i = 0; i < ngroups; i++) { + if (strcmp(names[i], grp->gr_name) == 0 && + gids[i] == grp->gr_gid) { + break; + } + } + if (i == ngroups) + return (false); + } + if (got != ngroups) + return (false); + + for (i = 0; i < ngroups; i++) { + grp = cap_getgrnam(capgrp, names[i]); + if (grp == NULL) + return (false); + } + + for (i = 0; i < ngroups; i++) { + cap_getgrnam_r(capgrp, names[i], &st, buf, sizeof(buf), &grp); + if (grp == NULL) + return (false); + } + + for (i = 0; i < ngroups; i++) { + grp = cap_getgrgid(capgrp, gids[i]); + if (grp == NULL) + return (false); + } + + for (i = 0; i < ngroups; i++) { + cap_getgrgid_r(capgrp, gids[i], &st, buf, sizeof(buf), &grp); + if (grp == NULL) + return (false); + } + + return (true); +} + +static void +test_groups(cap_channel_t *origcapgrp) +{ + cap_channel_t *capgrp; + const char *names[5]; + gid_t gids[5]; + + /* + * Allow: + * groups: + * names: wheel, daemon, kmem, sys, tty + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "wheel"; + names[1] = "daemon"; + names[2] = "kmem"; + names[3] = "sys"; + names[4] = "tty"; + CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); + gids[0] = 0; + gids[1] = 1; + gids[2] = 2; + gids[3] = 3; + gids[4] = 4; + + CHECK(runtest_groups(capgrp, names, gids, 5)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: kmem, sys, tty + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "kmem"; + names[1] = "sys"; + names[2] = "tty"; + CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0); + names[3] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "kmem"; + gids[0] = 2; + gids[1] = 3; + gids[2] = 4; + + CHECK(runtest_groups(capgrp, names, gids, 3)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: wheel, kmem, tty + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "wheel"; + names[1] = "kmem"; + names[2] = "tty"; + CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0); + names[3] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "wheel"; + gids[0] = 0; + gids[1] = 2; + gids[2] = 4; + + CHECK(runtest_groups(capgrp, names, gids, 3)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: + * gids: 2, 3, 4 + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "kmem"; + names[1] = "sys"; + names[2] = "tty"; + gids[0] = 2; + gids[1] = 3; + gids[2] = 4; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0); + gids[3] = 0; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 && + errno == ENOTCAPABLE); + gids[0] = 0; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && + errno == ENOTCAPABLE); + gids[0] = 2; + + CHECK(runtest_groups(capgrp, names, gids, 3)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: + * gids: 0, 2, 4 + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "wheel"; + names[1] = "kmem"; + names[2] = "tty"; + gids[0] = 0; + gids[1] = 2; + gids[2] = 4; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0); + gids[3] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 && + errno == ENOTCAPABLE); + gids[0] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && + errno == ENOTCAPABLE); + gids[0] = 0; + + CHECK(runtest_groups(capgrp, names, gids, 3)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: kmem + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "kmem"; + CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == 0); + names[1] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "kmem"; + gids[0] = 2; + + CHECK(runtest_groups(capgrp, names, gids, 1)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: wheel, tty + * gids: + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "wheel"; + names[1] = "tty"; + CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == 0); + names[2] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "wheel"; + gids[0] = 0; + gids[1] = 4; + + CHECK(runtest_groups(capgrp, names, gids, 2)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: + * gids: 2 + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "kmem"; + gids[0] = 2; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == 0); + gids[1] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == -1 && + errno == ENOTCAPABLE); + gids[0] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && + errno == ENOTCAPABLE); + gids[0] = 2; + + CHECK(runtest_groups(capgrp, names, gids, 1)); + + cap_close(capgrp); + + /* + * Allow: + * groups: + * names: + * gids: 0, 4 + */ + capgrp = cap_clone(origcapgrp); + CHECK(capgrp != NULL); + + names[0] = "wheel"; + names[1] = "tty"; + gids[0] = 0; + gids[1] = 4; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == 0); + gids[2] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == -1 && + errno == ENOTCAPABLE); + gids[0] = 1; + CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && + errno == ENOTCAPABLE); + gids[0] = 0; + + CHECK(runtest_groups(capgrp, names, gids, 2)); + + cap_close(capgrp); +} + +int +main(void) +{ + cap_channel_t *capcas, *capgrp; + + printf("1..199\n"); + + capcas = cap_init(); + CHECKX(capcas != NULL); + + capgrp = cap_service_open(capcas, "system.grp"); + CHECKX(capgrp != NULL); + + cap_close(capcas); + + /* No limits. */ + + CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | + GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); + + test_cmds(capgrp); + + test_fields(capgrp); + + test_groups(capgrp); + + cap_close(capgrp); + + exit(0); +} Index: head/lib/libcasper/services/cap_pwd/Makefile =================================================================== --- head/lib/libcasper/services/cap_pwd/Makefile +++ head/lib/libcasper/services/cap_pwd/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PACKAGE=libcasper LIB= cap_pwd @@ -15,4 +17,8 @@ CFLAGS+=-I${.CURDIR} +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include Index: head/lib/libcasper/services/cap_pwd/tests/Makefile =================================================================== --- head/lib/libcasper/services/cap_pwd/tests/Makefile +++ head/lib/libcasper/services/cap_pwd/tests/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TAP_TESTS_C= pwd_test + +LIBADD+= casper +LIBADD+= cap_pwd +LIBADD+= nv + +WARNS?= 3 + +.include Index: head/lib/libcasper/services/cap_pwd/tests/pwd_test.c =================================================================== --- head/lib/libcasper/services/cap_pwd/tests/pwd_test.c +++ head/lib/libcasper/services/cap_pwd/tests/pwd_test.c @@ -0,0 +1,1536 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) +#define CHECKX(expr) do { \ + if ((expr)) { \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + } else { \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__);\ + exit(1); \ + } \ + ntest++; \ +} while (0) + +#define UID_ROOT 0 +#define UID_OPERATOR 2 + +#define GETPWENT0 0x0001 +#define GETPWENT1 0x0002 +#define GETPWENT2 0x0004 +#define GETPWENT (GETPWENT0 | GETPWENT1 | GETPWENT2) +#define GETPWENT_R0 0x0008 +#define GETPWENT_R1 0x0010 +#define GETPWENT_R2 0x0020 +#define GETPWENT_R (GETPWENT_R0 | GETPWENT_R1 | GETPWENT_R2) +#define GETPWNAM 0x0040 +#define GETPWNAM_R 0x0080 +#define GETPWUID 0x0100 +#define GETPWUID_R 0x0200 + +static bool +passwd_compare(const struct passwd *pwd0, const struct passwd *pwd1) +{ + + if (pwd0 == NULL && pwd1 == NULL) + return (true); + if (pwd0 == NULL || pwd1 == NULL) + return (false); + + if (strcmp(pwd0->pw_name, pwd1->pw_name) != 0) + return (false); + + if (pwd0->pw_passwd != NULL || pwd1->pw_passwd != NULL) { + if (pwd0->pw_passwd == NULL || pwd1->pw_passwd == NULL) + return (false); + if (strcmp(pwd0->pw_passwd, pwd1->pw_passwd) != 0) + return (false); + } + + if (pwd0->pw_uid != pwd1->pw_uid) + return (false); + + if (pwd0->pw_gid != pwd1->pw_gid) + return (false); + + if (pwd0->pw_change != pwd1->pw_change) + return (false); + + if (pwd0->pw_class != NULL || pwd1->pw_class != NULL) { + if (pwd0->pw_class == NULL || pwd1->pw_class == NULL) + return (false); + if (strcmp(pwd0->pw_class, pwd1->pw_class) != 0) + return (false); + } + + if (pwd0->pw_gecos != NULL || pwd1->pw_gecos != NULL) { + if (pwd0->pw_gecos == NULL || pwd1->pw_gecos == NULL) + return (false); + if (strcmp(pwd0->pw_gecos, pwd1->pw_gecos) != 0) + return (false); + } + + if (pwd0->pw_dir != NULL || pwd1->pw_dir != NULL) { + if (pwd0->pw_dir == NULL || pwd1->pw_dir == NULL) + return (false); + if (strcmp(pwd0->pw_dir, pwd1->pw_dir) != 0) + return (false); + } + + if (pwd0->pw_shell != NULL || pwd1->pw_shell != NULL) { + if (pwd0->pw_shell == NULL || pwd1->pw_shell == NULL) + return (false); + if (strcmp(pwd0->pw_shell, pwd1->pw_shell) != 0) + return (false); + } + + if (pwd0->pw_expire != pwd1->pw_expire) + return (false); + + if (pwd0->pw_fields != pwd1->pw_fields) + return (false); + + return (true); +} + +static unsigned int +runtest_cmds(cap_channel_t *cappwd) +{ + char bufs[1024], bufc[1024]; + unsigned int result; + struct passwd *pwds, *pwdc; + struct passwd sts, stc; + + result = 0; + + setpwent(); + cap_setpwent(cappwd); + + pwds = getpwent(); + pwdc = cap_getpwent(cappwd); + if (passwd_compare(pwds, pwdc)) { + result |= GETPWENT0; + pwds = getpwent(); + pwdc = cap_getpwent(cappwd); + if (passwd_compare(pwds, pwdc)) + result |= GETPWENT1; + } + + getpwent_r(&sts, bufs, sizeof(bufs), &pwds); + cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); + if (passwd_compare(pwds, pwdc)) { + result |= GETPWENT_R0; + getpwent_r(&sts, bufs, sizeof(bufs), &pwds); + cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); + if (passwd_compare(pwds, pwdc)) + result |= GETPWENT_R1; + } + + setpwent(); + cap_setpwent(cappwd); + + getpwent_r(&sts, bufs, sizeof(bufs), &pwds); + cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); + if (passwd_compare(pwds, pwdc)) + result |= GETPWENT_R2; + + pwds = getpwent(); + pwdc = cap_getpwent(cappwd); + if (passwd_compare(pwds, pwdc)) + result |= GETPWENT2; + + pwds = getpwnam("root"); + pwdc = cap_getpwnam(cappwd, "root"); + if (passwd_compare(pwds, pwdc)) { + pwds = getpwnam("operator"); + pwdc = cap_getpwnam(cappwd, "operator"); + if (passwd_compare(pwds, pwdc)) + result |= GETPWNAM; + } + + getpwnam_r("root", &sts, bufs, sizeof(bufs), &pwds); + cap_getpwnam_r(cappwd, "root", &stc, bufc, sizeof(bufc), &pwdc); + if (passwd_compare(pwds, pwdc)) { + getpwnam_r("operator", &sts, bufs, sizeof(bufs), &pwds); + cap_getpwnam_r(cappwd, "operator", &stc, bufc, sizeof(bufc), + &pwdc); + if (passwd_compare(pwds, pwdc)) + result |= GETPWNAM_R; + } + + pwds = getpwuid(UID_ROOT); + pwdc = cap_getpwuid(cappwd, UID_ROOT); + if (passwd_compare(pwds, pwdc)) { + pwds = getpwuid(UID_OPERATOR); + pwdc = cap_getpwuid(cappwd, UID_OPERATOR); + if (passwd_compare(pwds, pwdc)) + result |= GETPWUID; + } + + getpwuid_r(UID_ROOT, &sts, bufs, sizeof(bufs), &pwds); + cap_getpwuid_r(cappwd, UID_ROOT, &stc, bufc, sizeof(bufc), &pwdc); + if (passwd_compare(pwds, pwdc)) { + getpwuid_r(UID_OPERATOR, &sts, bufs, sizeof(bufs), &pwds); + cap_getpwuid_r(cappwd, UID_OPERATOR, &stc, bufc, sizeof(bufc), + &pwdc); + if (passwd_compare(pwds, pwdc)) + result |= GETPWUID_R; + } + + return (result); +} + +static void +test_cmds(cap_channel_t *origcappwd) +{ + cap_channel_t *cappwd; + const char *cmds[7], *fields[10], *names[6]; + uid_t uids[5]; + + fields[0] = "pw_name"; + fields[1] = "pw_passwd"; + fields[2] = "pw_uid"; + fields[3] = "pw_gid"; + fields[4] = "pw_change"; + fields[5] = "pw_class"; + fields[6] = "pw_gecos"; + fields[7] = "pw_dir"; + fields[8] = "pw_shell"; + fields[9] = "pw_expire"; + + names[0] = "root"; + names[1] = "toor"; + names[2] = "daemon"; + names[3] = "operator"; + names[4] = "bin"; + names[5] = "kmem"; + + uids[0] = 0; + uids[1] = 1; + uids[2] = 2; + uids[3] = 3; + uids[4] = 5; + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: setpwent + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cap_setpwent(cappwd); + + cmds[0] = "getpwent"; + cmds[1] = "getpwent_r"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "setpwent"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 | + GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: setpwent + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cap_setpwent(cappwd); + + cmds[0] = "getpwent"; + cmds[1] = "getpwent_r"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "setpwent"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 | + GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwent + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent_r"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwent"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwent + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent_r"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwent"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwent_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwent_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwnam, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwent_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwnam"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwent_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | + GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwnam + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwnam"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam_r, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwnam + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam_r"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwnam"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM_R | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, + * getpwuid, getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwnam_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwnam_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, + * getpwuid, getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwnam_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwuid"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwnam_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWUID | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid_r + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwuid + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwuid"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid_r + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwuid + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwuid"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID_R)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid + * users: + * names: root, toor, daemon, operator, bin, kmem + * uids: + * Disallow: + * cmds: getpwuid_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID)); + + cap_close(cappwd); + + /* + * Allow: + * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, + * getpwuid + * users: + * names: + * uids: 0, 1, 2, 3, 5 + * Disallow: + * cmds: getpwuid_r + * users: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); + cmds[0] = "setpwent"; + cmds[1] = "getpwent"; + cmds[2] = "getpwent_r"; + cmds[3] = "getpwnam"; + cmds[4] = "getpwnam_r"; + cmds[5] = "getpwuid"; + cmds[6] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); + cmds[0] = "getpwuid_r"; + CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | + GETPWNAM | GETPWNAM_R | GETPWUID)); + + cap_close(cappwd); +} + +#define PW_NAME _PWF_NAME +#define PW_PASSWD _PWF_PASSWD +#define PW_UID _PWF_UID +#define PW_GID _PWF_GID +#define PW_CHANGE _PWF_CHANGE +#define PW_CLASS _PWF_CLASS +#define PW_GECOS _PWF_GECOS +#define PW_DIR _PWF_DIR +#define PW_SHELL _PWF_SHELL +#define PW_EXPIRE _PWF_EXPIRE + +static unsigned int +passwd_fields(const struct passwd *pwd) +{ + unsigned int result; + + result = 0; + + if (pwd->pw_name != NULL && pwd->pw_name[0] != '\0') + result |= PW_NAME; +// else +// printf("No pw_name\n"); + + if (pwd->pw_passwd != NULL && pwd->pw_passwd[0] != '\0') + result |= PW_PASSWD; + else if ((pwd->pw_fields & _PWF_PASSWD) != 0) + result |= PW_PASSWD; +// else +// printf("No pw_passwd\n"); + + if (pwd->pw_uid != (uid_t)-1) + result |= PW_UID; +// else +// printf("No pw_uid\n"); + + if (pwd->pw_gid != (gid_t)-1) + result |= PW_GID; +// else +// printf("No pw_gid\n"); + + if (pwd->pw_change != 0 || (pwd->pw_fields & _PWF_CHANGE) != 0) + result |= PW_CHANGE; +// else +// printf("No pw_change\n"); + + if (pwd->pw_class != NULL && pwd->pw_class[0] != '\0') + result |= PW_CLASS; + else if ((pwd->pw_fields & _PWF_CLASS) != 0) + result |= PW_CLASS; +// else +// printf("No pw_class\n"); + + if (pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0') + result |= PW_GECOS; + else if ((pwd->pw_fields & _PWF_GECOS) != 0) + result |= PW_GECOS; +// else +// printf("No pw_gecos\n"); + + if (pwd->pw_dir != NULL && pwd->pw_dir[0] != '\0') + result |= PW_DIR; + else if ((pwd->pw_fields & _PWF_DIR) != 0) + result |= PW_DIR; +// else +// printf("No pw_dir\n"); + + if (pwd->pw_shell != NULL && pwd->pw_shell[0] != '\0') + result |= PW_SHELL; + else if ((pwd->pw_fields & _PWF_SHELL) != 0) + result |= PW_SHELL; +// else +// printf("No pw_shell\n"); + + if (pwd->pw_expire != 0 || (pwd->pw_fields & _PWF_EXPIRE) != 0) + result |= PW_EXPIRE; +// else +// printf("No pw_expire\n"); + +if (false && pwd->pw_fields != (int)result) { +printf("fields=0x%x != result=0x%x\n", (const unsigned int)pwd->pw_fields, result); +printf(" fields result\n"); +printf("PW_NAME %d %d\n", (pwd->pw_fields & PW_NAME) != 0, (result & PW_NAME) != 0); +printf("PW_PASSWD %d %d\n", (pwd->pw_fields & PW_PASSWD) != 0, (result & PW_PASSWD) != 0); +printf("PW_UID %d %d\n", (pwd->pw_fields & PW_UID) != 0, (result & PW_UID) != 0); +printf("PW_GID %d %d\n", (pwd->pw_fields & PW_GID) != 0, (result & PW_GID) != 0); +printf("PW_CHANGE %d %d\n", (pwd->pw_fields & PW_CHANGE) != 0, (result & PW_CHANGE) != 0); +printf("PW_CLASS %d %d\n", (pwd->pw_fields & PW_CLASS) != 0, (result & PW_CLASS) != 0); +printf("PW_GECOS %d %d\n", (pwd->pw_fields & PW_GECOS) != 0, (result & PW_GECOS) != 0); +printf("PW_DIR %d %d\n", (pwd->pw_fields & PW_DIR) != 0, (result & PW_DIR) != 0); +printf("PW_SHELL %d %d\n", (pwd->pw_fields & PW_SHELL) != 0, (result & PW_SHELL) != 0); +printf("PW_EXPIRE %d %d\n", (pwd->pw_fields & PW_EXPIRE) != 0, (result & PW_EXPIRE) != 0); +} + +//printf("result=0x%x\n", result); + return (result); +} + +static bool +runtest_fields(cap_channel_t *cappwd, unsigned int expected) +{ + char buf[1024]; + struct passwd *pwd; + struct passwd st; + +//printf("expected=0x%x\n", expected); + cap_setpwent(cappwd); + pwd = cap_getpwent(cappwd); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + cap_setpwent(cappwd); + cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + pwd = cap_getpwnam(cappwd, "root"); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + cap_getpwnam_r(cappwd, "root", &st, buf, sizeof(buf), &pwd); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + pwd = cap_getpwuid(cappwd, UID_ROOT); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + cap_getpwuid_r(cappwd, UID_ROOT, &st, buf, sizeof(buf), &pwd); + if ((passwd_fields(pwd) & ~expected) != 0) + return (false); + + return (true); +} + +static void +test_fields(cap_channel_t *origcappwd) +{ + cap_channel_t *cappwd; + const char *fields[10]; + + /* No limits. */ + + CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID | + PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL | + PW_EXPIRE)); + + /* + * Allow: + * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change, pw_class, + * pw_gecos, pw_dir, pw_shell, pw_expire + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_name"; + fields[1] = "pw_passwd"; + fields[2] = "pw_uid"; + fields[3] = "pw_gid"; + fields[4] = "pw_change"; + fields[5] = "pw_class"; + fields[6] = "pw_gecos"; + fields[7] = "pw_dir"; + fields[8] = "pw_shell"; + fields[9] = "pw_expire"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); + + CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID | + PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL | + PW_EXPIRE)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_name"; + fields[1] = "pw_passwd"; + fields[2] = "pw_uid"; + fields[3] = "pw_gid"; + fields[4] = "pw_change"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); + fields[5] = "pw_class"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_class"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_NAME | PW_PASSWD | PW_UID | + PW_GID | PW_CHANGE)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_class, pw_gecos, pw_dir, pw_shell, pw_expire + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_class"; + fields[1] = "pw_gecos"; + fields[2] = "pw_dir"; + fields[3] = "pw_shell"; + fields[4] = "pw_expire"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); + fields[5] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_CLASS | PW_GECOS | PW_DIR | + PW_SHELL | PW_EXPIRE)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_name, pw_uid, pw_change, pw_gecos, pw_shell + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_name"; + fields[1] = "pw_uid"; + fields[2] = "pw_change"; + fields[3] = "pw_gecos"; + fields[4] = "pw_shell"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); + fields[5] = "pw_class"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_class"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_NAME | PW_UID | PW_CHANGE | + PW_GECOS | PW_SHELL)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_passwd, pw_gid, pw_class, pw_dir, pw_expire + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_passwd"; + fields[1] = "pw_gid"; + fields[2] = "pw_class"; + fields[3] = "pw_dir"; + fields[4] = "pw_expire"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); + fields[5] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_PASSWD | PW_GID | PW_CLASS | + PW_DIR | PW_EXPIRE)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_uid, pw_class, pw_shell + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_uid"; + fields[1] = "pw_class"; + fields[2] = "pw_shell"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 3) == 0); + fields[3] = "pw_change"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 4) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_change"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_UID | PW_CLASS | PW_SHELL)); + + cap_close(cappwd); + + /* + * Allow: + * fields: pw_change + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + fields[0] = "pw_change"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == 0); + fields[1] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 2) == -1 && + errno == ENOTCAPABLE); + fields[0] = "pw_uid"; + CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && + errno == ENOTCAPABLE); + + CHECK(runtest_fields(cappwd, PW_CHANGE)); + + cap_close(cappwd); +} + +static bool +runtest_users(cap_channel_t *cappwd, const char **names, const uid_t *uids, + size_t nusers) +{ + char buf[1024]; + struct passwd *pwd; + struct passwd st; + unsigned int i, got; + + cap_setpwent(cappwd); + got = 0; + for (;;) { + pwd = cap_getpwent(cappwd); + if (pwd == NULL) + break; + got++; + for (i = 0; i < nusers; i++) { + if (strcmp(names[i], pwd->pw_name) == 0 && + uids[i] == pwd->pw_uid) { + break; + } + } + if (i == nusers) + return (false); + } + if (got != nusers) + return (false); + + cap_setpwent(cappwd); + got = 0; + for (;;) { + cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd); + if (pwd == NULL) + break; + got++; + for (i = 0; i < nusers; i++) { + if (strcmp(names[i], pwd->pw_name) == 0 && + uids[i] == pwd->pw_uid) { + break; + } + } + if (i == nusers) + return (false); + } + if (got != nusers) + return (false); + + for (i = 0; i < nusers; i++) { + pwd = cap_getpwnam(cappwd, names[i]); + if (pwd == NULL) + return (false); + } + + for (i = 0; i < nusers; i++) { + cap_getpwnam_r(cappwd, names[i], &st, buf, sizeof(buf), &pwd); + if (pwd == NULL) + return (false); + } + + for (i = 0; i < nusers; i++) { + pwd = cap_getpwuid(cappwd, uids[i]); + if (pwd == NULL) + return (false); + } + + for (i = 0; i < nusers; i++) { + cap_getpwuid_r(cappwd, uids[i], &st, buf, sizeof(buf), &pwd); + if (pwd == NULL) + return (false); + } + + return (true); +} + +static void +test_users(cap_channel_t *origcappwd) +{ + cap_channel_t *cappwd; + const char *names[6]; + uid_t uids[6]; + + /* + * Allow: + * users: + * names: root, toor, daemon, operator, bin, tty + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "root"; + names[1] = "toor"; + names[2] = "daemon"; + names[3] = "operator"; + names[4] = "bin"; + names[5] = "tty"; + CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); + uids[0] = 0; + uids[1] = 0; + uids[2] = 1; + uids[3] = 2; + uids[4] = 3; + uids[5] = 4; + + CHECK(runtest_users(cappwd, names, uids, 6)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: daemon, operator, bin + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "operator"; + names[2] = "bin"; + CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0); + names[3] = "tty"; + CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "tty"; + CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + uids[0] = 1; + uids[1] = 2; + uids[2] = 3; + + CHECK(runtest_users(cappwd, names, uids, 3)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: daemon, bin, tty + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "bin"; + names[2] = "tty"; + CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0); + names[3] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + uids[0] = 1; + uids[1] = 3; + uids[2] = 4; + + CHECK(runtest_users(cappwd, names, uids, 3)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: + * uids: 1, 2, 3 + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "operator"; + names[2] = "bin"; + uids[0] = 1; + uids[1] = 2; + uids[2] = 3; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0); + uids[3] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 && + errno == ENOTCAPABLE); + uids[0] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && + errno == ENOTCAPABLE); + uids[0] = 1; + + CHECK(runtest_users(cappwd, names, uids, 3)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: + * uids: 1, 3, 4 + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "bin"; + names[2] = "tty"; + uids[0] = 1; + uids[1] = 3; + uids[2] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0); + uids[3] = 5; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 && + errno == ENOTCAPABLE); + uids[0] = 5; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && + errno == ENOTCAPABLE); + uids[0] = 1; + + CHECK(runtest_users(cappwd, names, uids, 3)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: bin + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "bin"; + CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == 0); + names[1] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "bin"; + uids[0] = 3; + + CHECK(runtest_users(cappwd, names, uids, 1)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: daemon, tty + * uids: + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "tty"; + CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == 0); + names[2] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "operator"; + CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && + errno == ENOTCAPABLE); + names[0] = "daemon"; + uids[0] = 1; + uids[1] = 4; + + CHECK(runtest_users(cappwd, names, uids, 2)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: + * uids: 3 + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "bin"; + uids[0] = 3; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == 0); + uids[1] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == -1 && + errno == ENOTCAPABLE); + uids[0] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && + errno == ENOTCAPABLE); + uids[0] = 3; + + CHECK(runtest_users(cappwd, names, uids, 1)); + + cap_close(cappwd); + + /* + * Allow: + * users: + * names: + * uids: 1, 4 + */ + cappwd = cap_clone(origcappwd); + CHECK(cappwd != NULL); + + names[0] = "daemon"; + names[1] = "tty"; + uids[0] = 1; + uids[1] = 4; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == 0); + uids[2] = 3; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == -1 && + errno == ENOTCAPABLE); + uids[0] = 3; + CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && + errno == ENOTCAPABLE); + uids[0] = 1; + + CHECK(runtest_users(cappwd, names, uids, 2)); + + cap_close(cappwd); +} + +int +main(void) +{ + cap_channel_t *capcas, *cappwd; + + printf("1..188\n"); + + capcas = cap_init(); + CHECKX(capcas != NULL); + + cappwd = cap_service_open(capcas, "system.pwd"); + CHECKX(cappwd != NULL); + + cap_close(capcas); + + /* No limits. */ + + CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | GETPWNAM | + GETPWNAM_R | GETPWUID | GETPWUID_R)); + + test_cmds(cappwd); + + test_fields(cappwd); + + test_users(cappwd); + + cap_close(cappwd); + + exit(0); +} Index: head/lib/libcasper/services/cap_sysctl/Makefile =================================================================== --- head/lib/libcasper/services/cap_sysctl/Makefile +++ head/lib/libcasper/services/cap_sysctl/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PACKAGE=libcasper LIB= cap_sysctl @@ -15,4 +17,8 @@ CFLAGS+=-I${.CURDIR} +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include Index: head/lib/libcasper/services/cap_sysctl/tests/Makefile =================================================================== --- head/lib/libcasper/services/cap_sysctl/tests/Makefile +++ head/lib/libcasper/services/cap_sysctl/tests/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +TAP_TESTS_C= sysctl_test + +LIBADD+= casper +LIBADD+= cap_sysctl +LIBADD+= nv + +WARNS?= 3 + +.include Index: head/lib/libcasper/services/cap_sysctl/tests/sysctl_test.c =================================================================== --- head/lib/libcasper/services/cap_sysctl/tests/sysctl_test.c +++ head/lib/libcasper/services/cap_sysctl/tests/sysctl_test.c @@ -0,0 +1,1510 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* + * We need some sysctls to perform the tests on. + * We remember their values and restore them afer the test is done. + */ +#define SYSCTL0_PARENT "kern" +#define SYSCTL0_NAME "kern.sync_on_panic" +#define SYSCTL1_PARENT "debug" +#define SYSCTL1_NAME "debug.minidump" + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + ntest++; \ +} while (0) +#define CHECKX(expr) do { \ + if ((expr)) { \ + printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + } else { \ + printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ + exit(1); \ + } \ + ntest++; \ +} while (0) + +#define SYSCTL0_READ0 0x0001 +#define SYSCTL0_READ1 0x0002 +#define SYSCTL0_READ2 0x0004 +#define SYSCTL0_WRITE 0x0008 +#define SYSCTL0_READ_WRITE 0x0010 +#define SYSCTL1_READ0 0x0020 +#define SYSCTL1_READ1 0x0040 +#define SYSCTL1_READ2 0x0080 +#define SYSCTL1_WRITE 0x0100 +#define SYSCTL1_READ_WRITE 0x0200 + +static unsigned int +runtest(cap_channel_t *capsysctl) +{ + unsigned int result; + int oldvalue, newvalue; + size_t oldsize; + + result = 0; + + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize, + NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue)) + result |= SYSCTL0_READ0; + } + + newvalue = 123; + if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, NULL, NULL, &newvalue, + sizeof(newvalue)) == 0) { + result |= SYSCTL0_WRITE; + } + + if ((result & SYSCTL0_WRITE) != 0) { + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, + &oldsize, NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 123) + result |= SYSCTL0_READ1; + } + } + + oldsize = sizeof(oldvalue); + newvalue = 4567; + if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize, + &newvalue, sizeof(newvalue)) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 123) + result |= SYSCTL0_READ_WRITE; + } + + if ((result & SYSCTL0_READ_WRITE) != 0) { + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, + &oldsize, NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 4567) + result |= SYSCTL0_READ2; + } + } + + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize, + NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue)) + result |= SYSCTL1_READ0; + } + + newvalue = 506; + if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, NULL, NULL, &newvalue, + sizeof(newvalue)) == 0) { + result |= SYSCTL1_WRITE; + } + + if ((result & SYSCTL1_WRITE) != 0) { + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, + &oldsize, NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 506) + result |= SYSCTL1_READ1; + } + } + + oldsize = sizeof(oldvalue); + newvalue = 7008; + if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize, + &newvalue, sizeof(newvalue)) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 506) + result |= SYSCTL1_READ_WRITE; + } + + if ((result & SYSCTL1_READ_WRITE) != 0) { + oldsize = sizeof(oldvalue); + if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, + &oldsize, NULL, 0) == 0) { + if (oldsize == sizeof(oldvalue) && oldvalue == 7008) + result |= SYSCTL1_READ2; + } + } + + return (result); +} + +static void +test_operation(cap_channel_t *origcapsysctl) +{ + cap_channel_t *capsysctl; + nvlist_t *limits; + + /* + * Allow: + * SYSCTL0_PARENT/RDWR/RECURSIVE + * SYSCTL1_PARENT/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, "foo.bar", + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, "foo.bar", + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == SYSCTL0_READ0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/RDWR/RECURSIVE + * SYSCTL1_NAME/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/RDWR + * SYSCTL1_PARENT/RDWR + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/RDWR + * SYSCTL1_NAME/RDWR + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/RDWR + * SYSCTL1_PARENT/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | + SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/RDWR + * SYSCTL1_NAME/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ/RECURSIVE + * SYSCTL1_PARENT/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ/RECURSIVE + * SYSCTL1_NAME/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ + * SYSCTL1_PARENT/READ + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ + * SYSCTL1_NAME/READ + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ + * SYSCTL1_PARENT/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_READ0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ + * SYSCTL1_NAME/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/WRITE/RECURSIVE + * SYSCTL1_PARENT/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/WRITE/RECURSIVE + * SYSCTL1_NAME/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/WRITE + * SYSCTL1_PARENT/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/WRITE + * SYSCTL1_NAME/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/WRITE + * SYSCTL1_PARENT/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_WRITE); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/WRITE + * SYSCTL1_NAME/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ/RECURSIVE + * SYSCTL1_PARENT/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ/RECURSIVE + * SYSCTL1_NAME/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ + * SYSCTL1_PARENT/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ + * SYSCTL1_NAME/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ + * SYSCTL1_PARENT/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == SYSCTL1_WRITE); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_NAME/READ + * SYSCTL1_NAME/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); + + cap_close(capsysctl); +} + +static void +test_names(cap_channel_t *origcapsysctl) +{ + cap_channel_t *capsysctl; + nvlist_t *limits; + + /* + * Allow: + * SYSCTL0_PARENT/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL0_READ0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/READ/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_READ0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL0_WRITE); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/WRITE/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_WRITE); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/RDWR/RECURSIVE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + nvlist_add_number(limits, SYSCTL1_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, + CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | + SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/READ + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/READ + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_READ0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/WRITE + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == SYSCTL1_WRITE); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL0_PARENT/RDWR + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == 0); + + cap_close(capsysctl); + + /* + * Allow: + * SYSCTL1_NAME/RDWR + */ + + capsysctl = cap_clone(origcapsysctl); + CHECK(capsysctl != NULL); + + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == 0); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + limits = nvlist_create(0); + nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); + CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); + + CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | + SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); + + cap_close(capsysctl); +} + +int +main(void) +{ + cap_channel_t *capcas, *capsysctl; + int scvalue0, scvalue1; + size_t scsize; + + printf("1..256\n"); + + scsize = sizeof(scvalue0); + CHECKX(sysctlbyname(SYSCTL0_NAME, &scvalue0, &scsize, NULL, 0) == 0); + CHECKX(scsize == sizeof(scvalue0)); + scsize = sizeof(scvalue1); + CHECKX(sysctlbyname(SYSCTL1_NAME, &scvalue1, &scsize, NULL, 0) == 0); + CHECKX(scsize == sizeof(scvalue1)); + + capcas = cap_init(); + CHECKX(capcas != NULL); + + capsysctl = cap_service_open(capcas, "system.sysctl"); + CHECKX(capsysctl != NULL); + + cap_close(capcas); + + /* No limits set. */ + + CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | + SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | + SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | + SYSCTL1_READ_WRITE)); + + test_operation(capsysctl); + + test_names(capsysctl); + + cap_close(capsysctl); + + CHECK(sysctlbyname(SYSCTL0_NAME, NULL, NULL, &scvalue0, + sizeof(scvalue0)) == 0); + CHECK(sysctlbyname(SYSCTL1_NAME, NULL, NULL, &scvalue1, + sizeof(scvalue1)) == 0); + + exit(0); +} Index: head/tools/regression/capsicum/libcasper/Makefile =================================================================== --- head/tools/regression/capsicum/libcasper/Makefile +++ head/tools/regression/capsicum/libcasper/Makefile @@ -1,32 +0,0 @@ -# $FreeBSD$ - -SERVICES= dns -SERVICES+= grp -SERVICES+= pwd -SERVICES+= sysctl - -CFLAGS= -O2 -pipe -std=gnu99 -fstack-protector -CFLAGS+= -Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter -CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -CFLAGS+= -Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter -CFLAGS+= -Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -CFLAGS+= -Wold-style-definition -Wno-pointer-sign - -CFLAGS+= -ggdb - -SERVTEST= ${SERVICES:=.t} - -all: ${SERVTEST} - -.for SERVICE in ${SERVICES} - -${SERVICE}.t: ${SERVICE}.c - ${CC} ${CFLAGS} ${@:.t=.c} -o $@ -lnv -lcasper -lcap_${@:.t=} - -.endfor - -test: all - @prove -r ${.CURDIR} - -clean: - rm -f ${SERVTEST} Index: head/tools/regression/capsicum/libcasper/dns.c =================================================================== --- head/tools/regression/capsicum/libcasper/dns.c +++ head/tools/regression/capsicum/libcasper/dns.c @@ -1,702 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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 -__FBSDID("$FreeBSD$"); - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - ntest++; \ -} while (0) -#define CHECKX(expr) do { \ - if ((expr)) { \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - } else { \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - exit(1); \ - } \ - ntest++; \ -} while (0) - -#define GETHOSTBYNAME 0x01 -#define GETHOSTBYNAME2_AF_INET 0x02 -#define GETHOSTBYNAME2_AF_INET6 0x04 -#define GETHOSTBYADDR_AF_INET 0x08 -#define GETHOSTBYADDR_AF_INET6 0x10 -#define GETADDRINFO_AF_UNSPEC 0x20 -#define GETADDRINFO_AF_INET 0x40 -#define GETADDRINFO_AF_INET6 0x80 - -static bool -addrinfo_compare(struct addrinfo *ai0, struct addrinfo *ai1) -{ - struct addrinfo *at0, *at1; - - if (ai0 == NULL && ai1 == NULL) - return (true); - if (ai0 == NULL || ai1 == NULL) - return (false); - - at0 = ai0; - at1 = ai1; - while (true) { - if ((at0->ai_flags == at1->ai_flags) && - (at0->ai_family == at1->ai_family) && - (at0->ai_socktype == at1->ai_socktype) && - (at0->ai_protocol == at1->ai_protocol) && - (at0->ai_addrlen == at1->ai_addrlen) && - (memcmp(at0->ai_addr, at1->ai_addr, - at0->ai_addrlen) == 0)) { - if (at0->ai_canonname != NULL && - at1->ai_canonname != NULL) { - if (strcmp(at0->ai_canonname, - at1->ai_canonname) != 0) { - return (false); - } - } - - if (at0->ai_canonname == NULL && - at1->ai_canonname != NULL) { - return (false); - } - if (at0->ai_canonname != NULL && - at1->ai_canonname == NULL) { - return (false); - } - - if (at0->ai_next == NULL && at1->ai_next == NULL) - return (true); - if (at0->ai_next == NULL || at1->ai_next == NULL) - return (false); - - at0 = at0->ai_next; - at1 = at1->ai_next; - } else { - return (false); - } - } - - /* NOTREACHED */ - fprintf(stderr, "Dead code reached in addrinfo_compare()\n"); - exit(1); -} - -static bool -hostent_aliases_compare(char **aliases0, char **aliases1) -{ - int i0, i1; - - if (aliases0 == NULL && aliases1 == NULL) - return (true); - if (aliases0 == NULL || aliases1 == NULL) - return (false); - - for (i0 = 0; aliases0[i0] != NULL; i0++) { - for (i1 = 0; aliases1[i1] != NULL; i1++) { - if (strcmp(aliases0[i0], aliases1[i1]) == 0) - break; - } - if (aliases1[i1] == NULL) - return (false); - } - - return (true); -} - -static bool -hostent_addr_list_compare(char **addr_list0, char **addr_list1, int length) -{ - int i0, i1; - - if (addr_list0 == NULL && addr_list1 == NULL) - return (true); - if (addr_list0 == NULL || addr_list1 == NULL) - return (false); - - for (i0 = 0; addr_list0[i0] != NULL; i0++) { - for (i1 = 0; addr_list1[i1] != NULL; i1++) { - if (memcmp(addr_list0[i0], addr_list1[i1], length) == 0) - break; - } - if (addr_list1[i1] == NULL) - return (false); - } - - return (true); -} - -static bool -hostent_compare(const struct hostent *hp0, const struct hostent *hp1) -{ - - if (hp0 == NULL && hp1 != NULL) - return (true); - - if (hp0 == NULL || hp1 == NULL) - return (false); - - if (hp0->h_name != NULL || hp1->h_name != NULL) { - if (hp0->h_name == NULL || hp1->h_name == NULL) - return (false); - if (strcmp(hp0->h_name, hp1->h_name) != 0) - return (false); - } - - if (!hostent_aliases_compare(hp0->h_aliases, hp1->h_aliases)) - return (false); - if (!hostent_aliases_compare(hp1->h_aliases, hp0->h_aliases)) - return (false); - - if (hp0->h_addrtype != hp1->h_addrtype) - return (false); - - if (hp0->h_length != hp1->h_length) - return (false); - - if (!hostent_addr_list_compare(hp0->h_addr_list, hp1->h_addr_list, - hp0->h_length)) { - return (false); - } - if (!hostent_addr_list_compare(hp1->h_addr_list, hp0->h_addr_list, - hp0->h_length)) { - return (false); - } - - return (true); -} - -static unsigned int -runtest(cap_channel_t *capdns) -{ - unsigned int result; - struct addrinfo *ais, *aic, hints, *hintsp; - struct hostent *hps, *hpc; - struct in_addr ip4; - struct in6_addr ip6; - - result = 0; - - hps = gethostbyname("example.com"); - if (hps == NULL) - fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); - hpc = cap_gethostbyname(capdns, "example.com"); - if (hostent_compare(hps, hpc)) - result |= GETHOSTBYNAME; - - hps = gethostbyname2("example.com", AF_INET); - if (hps == NULL) - fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); - hpc = cap_gethostbyname2(capdns, "example.com", AF_INET); - if (hostent_compare(hps, hpc)) - result |= GETHOSTBYNAME2_AF_INET; - - hps = gethostbyname2("example.com", AF_INET6); - if (hps == NULL) - fprintf(stderr, "Unable to resolve %s IPv6.\n", "example.com"); - hpc = cap_gethostbyname2(capdns, "example.com", AF_INET6); - if (hostent_compare(hps, hpc)) - result |= GETHOSTBYNAME2_AF_INET6; - - hints.ai_flags = 0; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = 0; - hints.ai_protocol = 0; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - hintsp = &hints; - - if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { - fprintf(stderr, - "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", - gai_strerror(errno)); - } - if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { - if (addrinfo_compare(ais, aic)) - result |= GETADDRINFO_AF_UNSPEC; - freeaddrinfo(ais); - freeaddrinfo(aic); - } - - hints.ai_family = AF_INET; - if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { - fprintf(stderr, - "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", - gai_strerror(errno)); - } - if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { - if (addrinfo_compare(ais, aic)) - result |= GETADDRINFO_AF_INET; - freeaddrinfo(ais); - freeaddrinfo(aic); - } - - hints.ai_family = AF_INET6; - if (getaddrinfo("freebsd.org", "25", hintsp, &ais) != 0) { - fprintf(stderr, - "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", - gai_strerror(errno)); - } - if (cap_getaddrinfo(capdns, "freebsd.org", "25", hintsp, &aic) == 0) { - if (addrinfo_compare(ais, aic)) - result |= GETADDRINFO_AF_INET6; - freeaddrinfo(ais); - freeaddrinfo(aic); - } - - /* - * 8.8.178.135 is IPv4 address of freefall.freebsd.org - * as of 27 October 2013. - */ - inet_pton(AF_INET, "8.8.178.135", &ip4); - hps = gethostbyaddr(&ip4, sizeof(ip4), AF_INET); - if (hps == NULL) - fprintf(stderr, "Unable to resolve %s.\n", "8.8.178.135"); - hpc = cap_gethostbyaddr(capdns, &ip4, sizeof(ip4), AF_INET); - if (hostent_compare(hps, hpc)) - result |= GETHOSTBYADDR_AF_INET; - - /* - * 2001:1900:2254:206c::16:87 is IPv6 address of freefall.freebsd.org - * as of 27 October 2013. - */ - inet_pton(AF_INET6, "2001:1900:2254:206c::16:87", &ip6); - hps = gethostbyaddr(&ip6, sizeof(ip6), AF_INET6); - if (hps == NULL) { - fprintf(stderr, "Unable to resolve %s.\n", - "2001:1900:2254:206c::16:87"); - } - hpc = cap_gethostbyaddr(capdns, &ip6, sizeof(ip6), AF_INET6); - if (hostent_compare(hps, hpc)) - result |= GETHOSTBYADDR_AF_INET6; - - return (result); -} - -int -main(void) -{ - cap_channel_t *capcas, *capdns, *origcapdns; - const char *types[2]; - int families[2]; - - printf("1..91\n"); - - capcas = cap_init(); - CHECKX(capcas != NULL); - - origcapdns = capdns = cap_service_open(capcas, "system.dns"); - CHECKX(capdns != NULL); - - cap_close(capcas); - - /* No limits set. */ - - CHECK(runtest(capdns) == - (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 | - GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_UNSPEC | GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); - - /* - * Allow: - * type: NAME, ADDR - * family: AF_INET, AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - - CHECK(runtest(capdns) == - (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 | - GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); - - cap_close(capdns); - - /* - * Allow: - * type: NAME - * family: AF_INET, AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - - CHECK(runtest(capdns) == - (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6)); - - cap_close(capdns); - - /* - * Allow: - * type: ADDR - * family: AF_INET, AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - - CHECK(runtest(capdns) == - (GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_INET | GETADDRINFO_AF_INET6)); - - cap_close(capdns); - - /* - * Allow: - * type: NAME, ADDR - * family: AF_INET - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == - (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET | GETHOSTBYADDR_AF_INET | - GETADDRINFO_AF_INET)); - - cap_close(capdns); - - /* - * Allow: - * type: NAME, ADDR - * family: AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == - (GETHOSTBYNAME2_AF_INET6 | GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_INET6)); - - cap_close(capdns); - - /* Below we also test further limiting capability. */ - - /* - * Allow: - * type: NAME - * family: AF_INET - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET)); - - cap_close(capdns); - - /* - * Allow: - * type: NAME - * family: AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == GETHOSTBYNAME2_AF_INET6); - - cap_close(capdns); - - /* - * Allow: - * type: ADDR - * family: AF_INET - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET | GETADDRINFO_AF_INET)); - - cap_close(capdns); - - /* - * Allow: - * type: ADDR - * family: AF_INET6 - */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == 0); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == 0); - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - types[1] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - families[1] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_INET6)); - - cap_close(capdns); - - /* Trying to rise the limits. */ - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 && - errno == ENOTCAPABLE); - CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 && - errno == ENOTCAPABLE); - - /* Do the limits still hold? */ - CHECK(runtest(capdns) == (GETHOSTBYNAME | GETHOSTBYNAME2_AF_INET)); - - cap_close(capdns); - - capdns = cap_clone(origcapdns); - CHECK(capdns != NULL); - - types[0] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 1) == 0); - families[0] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 1) == 0); - - types[0] = "NAME"; - types[1] = "ADDR"; - CHECK(cap_dns_type_limit(capdns, types, 2) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - families[1] = AF_INET6; - CHECK(cap_dns_family_limit(capdns, families, 2) == -1 && - errno == ENOTCAPABLE); - - types[0] = "NAME"; - CHECK(cap_dns_type_limit(capdns, types, 1) == -1 && - errno == ENOTCAPABLE); - families[0] = AF_INET; - CHECK(cap_dns_family_limit(capdns, families, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(cap_dns_type_limit(capdns, NULL, 0) == -1 && - errno == ENOTCAPABLE); - CHECK(cap_dns_family_limit(capdns, NULL, 0) == -1 && - errno == ENOTCAPABLE); - - /* Do the limits still hold? */ - CHECK(runtest(capdns) == (GETHOSTBYADDR_AF_INET6 | - GETADDRINFO_AF_INET6)); - - cap_close(capdns); - - cap_close(origcapdns); - - exit(0); -} Index: head/tools/regression/capsicum/libcasper/grp.c =================================================================== --- head/tools/regression/capsicum/libcasper/grp.c +++ head/tools/regression/capsicum/libcasper/grp.c @@ -1,1550 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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 -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - ntest++; \ -} while (0) -#define CHECKX(expr) do { \ - if ((expr)) { \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - } else { \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - exit(1); \ - } \ - ntest++; \ -} while (0) - -#define GID_WHEEL 0 -#define GID_OPERATOR 5 - -#define GETGRENT0 0x0001 -#define GETGRENT1 0x0002 -#define GETGRENT2 0x0004 -#define GETGRENT (GETGRENT0 | GETGRENT1 | GETGRENT2) -#define GETGRENT_R0 0x0008 -#define GETGRENT_R1 0x0010 -#define GETGRENT_R2 0x0020 -#define GETGRENT_R (GETGRENT_R0 | GETGRENT_R1 | GETGRENT_R2) -#define GETGRNAM 0x0040 -#define GETGRNAM_R 0x0080 -#define GETGRGID 0x0100 -#define GETGRGID_R 0x0200 -#define SETGRENT 0x0400 - -static bool -group_mem_compare(char **mem0, char **mem1) -{ - int i0, i1; - - if (mem0 == NULL && mem1 == NULL) - return (true); - if (mem0 == NULL || mem1 == NULL) - return (false); - - for (i0 = 0; mem0[i0] != NULL; i0++) { - for (i1 = 0; mem1[i1] != NULL; i1++) { - if (strcmp(mem0[i0], mem1[i1]) == 0) - break; - } - if (mem1[i1] == NULL) - return (false); - } - - return (true); -} - -static bool -group_compare(const struct group *grp0, const struct group *grp1) -{ - - if (grp0 == NULL && grp1 == NULL) - return (true); - if (grp0 == NULL || grp1 == NULL) - return (false); - - if (strcmp(grp0->gr_name, grp1->gr_name) != 0) - return (false); - - if (grp0->gr_passwd != NULL || grp1->gr_passwd != NULL) { - if (grp0->gr_passwd == NULL || grp1->gr_passwd == NULL) - return (false); - if (strcmp(grp0->gr_passwd, grp1->gr_passwd) != 0) - return (false); - } - - if (grp0->gr_gid != grp1->gr_gid) - return (false); - - if (!group_mem_compare(grp0->gr_mem, grp1->gr_mem)) - return (false); - - return (true); -} - -static unsigned int -runtest_cmds(cap_channel_t *capgrp) -{ - char bufs[1024], bufc[1024]; - unsigned int result; - struct group *grps, *grpc; - struct group sts, stc; - - result = 0; - - (void)setgrent(); - if (cap_setgrent(capgrp) == 1) - result |= SETGRENT; - - grps = getgrent(); - grpc = cap_getgrent(capgrp); - if (group_compare(grps, grpc)) { - result |= GETGRENT0; - grps = getgrent(); - grpc = cap_getgrent(capgrp); - if (group_compare(grps, grpc)) - result |= GETGRENT1; - } - - getgrent_r(&sts, bufs, sizeof(bufs), &grps); - cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); - if (group_compare(grps, grpc)) { - result |= GETGRENT_R0; - getgrent_r(&sts, bufs, sizeof(bufs), &grps); - cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); - if (group_compare(grps, grpc)) - result |= GETGRENT_R1; - } - - (void)setgrent(); - if (cap_setgrent(capgrp) == 1) - result |= SETGRENT; - - getgrent_r(&sts, bufs, sizeof(bufs), &grps); - cap_getgrent_r(capgrp, &stc, bufc, sizeof(bufc), &grpc); - if (group_compare(grps, grpc)) - result |= GETGRENT_R2; - - grps = getgrent(); - grpc = cap_getgrent(capgrp); - if (group_compare(grps, grpc)) - result |= GETGRENT2; - - grps = getgrnam("wheel"); - grpc = cap_getgrnam(capgrp, "wheel"); - if (group_compare(grps, grpc)) { - grps = getgrnam("operator"); - grpc = cap_getgrnam(capgrp, "operator"); - if (group_compare(grps, grpc)) - result |= GETGRNAM; - } - - getgrnam_r("wheel", &sts, bufs, sizeof(bufs), &grps); - cap_getgrnam_r(capgrp, "wheel", &stc, bufc, sizeof(bufc), &grpc); - if (group_compare(grps, grpc)) { - getgrnam_r("operator", &sts, bufs, sizeof(bufs), &grps); - cap_getgrnam_r(capgrp, "operator", &stc, bufc, sizeof(bufc), - &grpc); - if (group_compare(grps, grpc)) - result |= GETGRNAM_R; - } - - grps = getgrgid(GID_WHEEL); - grpc = cap_getgrgid(capgrp, GID_WHEEL); - if (group_compare(grps, grpc)) { - grps = getgrgid(GID_OPERATOR); - grpc = cap_getgrgid(capgrp, GID_OPERATOR); - if (group_compare(grps, grpc)) - result |= GETGRGID; - } - - getgrgid_r(GID_WHEEL, &sts, bufs, sizeof(bufs), &grps); - cap_getgrgid_r(capgrp, GID_WHEEL, &stc, bufc, sizeof(bufc), &grpc); - if (group_compare(grps, grpc)) { - getgrgid_r(GID_OPERATOR, &sts, bufs, sizeof(bufs), &grps); - cap_getgrgid_r(capgrp, GID_OPERATOR, &stc, bufc, sizeof(bufc), - &grpc); - if (group_compare(grps, grpc)) - result |= GETGRGID_R; - } - - return (result); -} - -static void -test_cmds(cap_channel_t *origcapgrp) -{ - cap_channel_t *capgrp; - const char *cmds[7], *fields[4], *names[5]; - gid_t gids[5]; - - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - - names[0] = "wheel"; - names[1] = "daemon"; - names[2] = "kmem"; - names[3] = "sys"; - names[4] = "operator"; - - gids[0] = 0; - gids[1] = 1; - gids[2] = 2; - gids[3] = 3; - gids[4] = 5; - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == 0); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: setgrent - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "getgrent"; - cmds[1] = "getgrent_r"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "setgrent"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 | - GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: setgrent - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "getgrent"; - cmds[1] = "getgrent_r"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "setgrent"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (GETGRENT0 | GETGRENT1 | GETGRENT_R0 | - GETGRENT_R1 | GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrent - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent_r"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrent"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrent - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent_r"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrent"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT_R2 | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrent_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrent_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrnam, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrent_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrnam"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrent_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT0 | GETGRENT1 | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrnam - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrnam"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam_r, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrnam - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam_r"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrnam"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM_R | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrnam_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrnam_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, - * getgrgid, getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrnam_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrgid"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrnam_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRGID | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrgid - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrgid"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid_r - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrgid - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrgid"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID_R)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: wheel, daemon, kmem, sys, operator - * gids: - * Disallow: - * cmds: getgrgid_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID)); - - cap_close(capgrp); - - /* - * Allow: - * cmds: setgrent, getgrent, getgrent_r, getgrnam, getgrnam_r, - * getgrgid - * fields: gr_name, gr_passwd, gr_gid, gr_mem - * groups: - * names: - * gids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getgrgid_r - * fields: - * groups: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 6) == 0); - cmds[0] = "setgrent"; - cmds[1] = "getgrent"; - cmds[2] = "getgrent_r"; - cmds[3] = "getgrnam"; - cmds[4] = "getgrnam_r"; - cmds[5] = "getgrgid"; - cmds[6] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getgrgid_r"; - CHECK(cap_grp_limit_cmds(capgrp, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 5) == 0); - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID)); - - cap_close(capgrp); -} - -#define GR_NAME 0x01 -#define GR_PASSWD 0x02 -#define GR_GID 0x04 -#define GR_MEM 0x08 - -static unsigned int -group_fields(const struct group *grp) -{ - unsigned int result; - - result = 0; - - if (grp->gr_name != NULL && grp->gr_name[0] != '\0') - result |= GR_NAME; - - if (grp->gr_passwd != NULL && grp->gr_passwd[0] != '\0') - result |= GR_PASSWD; - - if (grp->gr_gid != (gid_t)-1) - result |= GR_GID; - - if (grp->gr_mem != NULL && grp->gr_mem[0] != NULL) - result |= GR_MEM; - - return (result); -} - -static bool -runtest_fields(cap_channel_t *capgrp, unsigned int expected) -{ - char buf[1024]; - struct group *grp; - struct group st; - - (void)cap_setgrent(capgrp); - grp = cap_getgrent(capgrp); - if (group_fields(grp) != expected) - return (false); - - (void)cap_setgrent(capgrp); - cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp); - if (group_fields(grp) != expected) - return (false); - - grp = cap_getgrnam(capgrp, "wheel"); - if (group_fields(grp) != expected) - return (false); - - cap_getgrnam_r(capgrp, "wheel", &st, buf, sizeof(buf), &grp); - if (group_fields(grp) != expected) - return (false); - - grp = cap_getgrgid(capgrp, GID_WHEEL); - if (group_fields(grp) != expected) - return (false); - - cap_getgrgid_r(capgrp, GID_WHEEL, &st, buf, sizeof(buf), &grp); - if (group_fields(grp) != expected) - return (false); - - return (true); -} - -static void -test_fields(cap_channel_t *origcapgrp) -{ - cap_channel_t *capgrp; - const char *fields[4]; - - /* No limits. */ - - CHECK(runtest_fields(origcapgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM)); - - /* - * Allow: - * fields: gr_name, gr_passwd, gr_gid, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == 0); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_passwd, gr_gid, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_passwd"; - fields[1] = "gr_gid"; - fields[2] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_gid, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_gid"; - fields[2] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_passwd"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_GID | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_passwd, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_passwd, gr_gid - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 3) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD | GR_GID)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_passwd - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_PASSWD)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_gid - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_GID)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_name, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_name"; - fields[1] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_passwd"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_NAME | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_passwd, gr_gid - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_passwd"; - fields[1] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_PASSWD | GR_GID)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_passwd, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_passwd"; - fields[1] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_gid"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_PASSWD | GR_MEM)); - - cap_close(capgrp); - - /* - * Allow: - * fields: gr_gid, gr_mem - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - fields[0] = "gr_gid"; - fields[1] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 2) == 0); - fields[0] = "gr_name"; - fields[1] = "gr_passwd"; - fields[2] = "gr_gid"; - fields[3] = "gr_mem"; - CHECK(cap_grp_limit_fields(capgrp, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "gr_passwd"; - CHECK(cap_grp_limit_fields(capgrp, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(capgrp, GR_GID | GR_MEM)); - - cap_close(capgrp); -} - -static bool -runtest_groups(cap_channel_t *capgrp, const char **names, const gid_t *gids, - size_t ngroups) -{ - char buf[1024]; - struct group *grp; - struct group st; - unsigned int i, got; - - (void)cap_setgrent(capgrp); - got = 0; - for (;;) { - grp = cap_getgrent(capgrp); - if (grp == NULL) - break; - got++; - for (i = 0; i < ngroups; i++) { - if (strcmp(names[i], grp->gr_name) == 0 && - gids[i] == grp->gr_gid) { - break; - } - } - if (i == ngroups) - return (false); - } - if (got != ngroups) - return (false); - - (void)cap_setgrent(capgrp); - got = 0; - for (;;) { - cap_getgrent_r(capgrp, &st, buf, sizeof(buf), &grp); - if (grp == NULL) - break; - got++; - for (i = 0; i < ngroups; i++) { - if (strcmp(names[i], grp->gr_name) == 0 && - gids[i] == grp->gr_gid) { - break; - } - } - if (i == ngroups) - return (false); - } - if (got != ngroups) - return (false); - - for (i = 0; i < ngroups; i++) { - grp = cap_getgrnam(capgrp, names[i]); - if (grp == NULL) - return (false); - } - - for (i = 0; i < ngroups; i++) { - cap_getgrnam_r(capgrp, names[i], &st, buf, sizeof(buf), &grp); - if (grp == NULL) - return (false); - } - - for (i = 0; i < ngroups; i++) { - grp = cap_getgrgid(capgrp, gids[i]); - if (grp == NULL) - return (false); - } - - for (i = 0; i < ngroups; i++) { - cap_getgrgid_r(capgrp, gids[i], &st, buf, sizeof(buf), &grp); - if (grp == NULL) - return (false); - } - - return (true); -} - -static void -test_groups(cap_channel_t *origcapgrp) -{ - cap_channel_t *capgrp; - const char *names[5]; - gid_t gids[5]; - - /* - * Allow: - * groups: - * names: wheel, daemon, kmem, sys, tty - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "wheel"; - names[1] = "daemon"; - names[2] = "kmem"; - names[3] = "sys"; - names[4] = "tty"; - CHECK(cap_grp_limit_groups(capgrp, names, 5, NULL, 0) == 0); - gids[0] = 0; - gids[1] = 1; - gids[2] = 2; - gids[3] = 3; - gids[4] = 4; - - CHECK(runtest_groups(capgrp, names, gids, 5)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: kmem, sys, tty - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "kmem"; - names[1] = "sys"; - names[2] = "tty"; - CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0); - names[3] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "kmem"; - gids[0] = 2; - gids[1] = 3; - gids[2] = 4; - - CHECK(runtest_groups(capgrp, names, gids, 3)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: wheel, kmem, tty - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "wheel"; - names[1] = "kmem"; - names[2] = "tty"; - CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == 0); - names[3] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 4, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "wheel"; - gids[0] = 0; - gids[1] = 2; - gids[2] = 4; - - CHECK(runtest_groups(capgrp, names, gids, 3)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: - * gids: 2, 3, 4 - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "kmem"; - names[1] = "sys"; - names[2] = "tty"; - gids[0] = 2; - gids[1] = 3; - gids[2] = 4; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0); - gids[3] = 0; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 && - errno == ENOTCAPABLE); - gids[0] = 0; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && - errno == ENOTCAPABLE); - gids[0] = 2; - - CHECK(runtest_groups(capgrp, names, gids, 3)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: - * gids: 0, 2, 4 - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "wheel"; - names[1] = "kmem"; - names[2] = "tty"; - gids[0] = 0; - gids[1] = 2; - gids[2] = 4; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == 0); - gids[3] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 4) == -1 && - errno == ENOTCAPABLE); - gids[0] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && - errno == ENOTCAPABLE); - gids[0] = 0; - - CHECK(runtest_groups(capgrp, names, gids, 3)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: kmem - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "kmem"; - CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == 0); - names[1] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "kmem"; - gids[0] = 2; - - CHECK(runtest_groups(capgrp, names, gids, 1)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: wheel, tty - * gids: - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "wheel"; - names[1] = "tty"; - CHECK(cap_grp_limit_groups(capgrp, names, 2, NULL, 0) == 0); - names[2] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 3, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - CHECK(cap_grp_limit_groups(capgrp, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "wheel"; - gids[0] = 0; - gids[1] = 4; - - CHECK(runtest_groups(capgrp, names, gids, 2)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: - * gids: 2 - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "kmem"; - gids[0] = 2; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == 0); - gids[1] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == -1 && - errno == ENOTCAPABLE); - gids[0] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && - errno == ENOTCAPABLE); - gids[0] = 2; - - CHECK(runtest_groups(capgrp, names, gids, 1)); - - cap_close(capgrp); - - /* - * Allow: - * groups: - * names: - * gids: 0, 4 - */ - capgrp = cap_clone(origcapgrp); - CHECK(capgrp != NULL); - - names[0] = "wheel"; - names[1] = "tty"; - gids[0] = 0; - gids[1] = 4; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 2) == 0); - gids[2] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 3) == -1 && - errno == ENOTCAPABLE); - gids[0] = 1; - CHECK(cap_grp_limit_groups(capgrp, NULL, 0, gids, 1) == -1 && - errno == ENOTCAPABLE); - gids[0] = 0; - - CHECK(runtest_groups(capgrp, names, gids, 2)); - - cap_close(capgrp); -} - -int -main(void) -{ - cap_channel_t *capcas, *capgrp; - - printf("1..199\n"); - - capcas = cap_init(); - CHECKX(capcas != NULL); - - capgrp = cap_service_open(capcas, "system.grp"); - CHECKX(capgrp != NULL); - - cap_close(capcas); - - /* No limits. */ - - CHECK(runtest_cmds(capgrp) == (SETGRENT | GETGRENT | GETGRENT_R | - GETGRNAM | GETGRNAM_R | GETGRGID | GETGRGID_R)); - - test_cmds(capgrp); - - test_fields(capgrp); - - test_groups(capgrp); - - cap_close(capgrp); - - exit(0); -} Index: head/tools/regression/capsicum/libcasper/pwd.c =================================================================== --- head/tools/regression/capsicum/libcasper/pwd.c +++ head/tools/regression/capsicum/libcasper/pwd.c @@ -1,1536 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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 -__FBSDID("$FreeBSD$"); - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) -#define CHECKX(expr) do { \ - if ((expr)) { \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - } else { \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__);\ - exit(1); \ - } \ - ntest++; \ -} while (0) - -#define UID_ROOT 0 -#define UID_OPERATOR 2 - -#define GETPWENT0 0x0001 -#define GETPWENT1 0x0002 -#define GETPWENT2 0x0004 -#define GETPWENT (GETPWENT0 | GETPWENT1 | GETPWENT2) -#define GETPWENT_R0 0x0008 -#define GETPWENT_R1 0x0010 -#define GETPWENT_R2 0x0020 -#define GETPWENT_R (GETPWENT_R0 | GETPWENT_R1 | GETPWENT_R2) -#define GETPWNAM 0x0040 -#define GETPWNAM_R 0x0080 -#define GETPWUID 0x0100 -#define GETPWUID_R 0x0200 - -static bool -passwd_compare(const struct passwd *pwd0, const struct passwd *pwd1) -{ - - if (pwd0 == NULL && pwd1 == NULL) - return (true); - if (pwd0 == NULL || pwd1 == NULL) - return (false); - - if (strcmp(pwd0->pw_name, pwd1->pw_name) != 0) - return (false); - - if (pwd0->pw_passwd != NULL || pwd1->pw_passwd != NULL) { - if (pwd0->pw_passwd == NULL || pwd1->pw_passwd == NULL) - return (false); - if (strcmp(pwd0->pw_passwd, pwd1->pw_passwd) != 0) - return (false); - } - - if (pwd0->pw_uid != pwd1->pw_uid) - return (false); - - if (pwd0->pw_gid != pwd1->pw_gid) - return (false); - - if (pwd0->pw_change != pwd1->pw_change) - return (false); - - if (pwd0->pw_class != NULL || pwd1->pw_class != NULL) { - if (pwd0->pw_class == NULL || pwd1->pw_class == NULL) - return (false); - if (strcmp(pwd0->pw_class, pwd1->pw_class) != 0) - return (false); - } - - if (pwd0->pw_gecos != NULL || pwd1->pw_gecos != NULL) { - if (pwd0->pw_gecos == NULL || pwd1->pw_gecos == NULL) - return (false); - if (strcmp(pwd0->pw_gecos, pwd1->pw_gecos) != 0) - return (false); - } - - if (pwd0->pw_dir != NULL || pwd1->pw_dir != NULL) { - if (pwd0->pw_dir == NULL || pwd1->pw_dir == NULL) - return (false); - if (strcmp(pwd0->pw_dir, pwd1->pw_dir) != 0) - return (false); - } - - if (pwd0->pw_shell != NULL || pwd1->pw_shell != NULL) { - if (pwd0->pw_shell == NULL || pwd1->pw_shell == NULL) - return (false); - if (strcmp(pwd0->pw_shell, pwd1->pw_shell) != 0) - return (false); - } - - if (pwd0->pw_expire != pwd1->pw_expire) - return (false); - - if (pwd0->pw_fields != pwd1->pw_fields) - return (false); - - return (true); -} - -static unsigned int -runtest_cmds(cap_channel_t *cappwd) -{ - char bufs[1024], bufc[1024]; - unsigned int result; - struct passwd *pwds, *pwdc; - struct passwd sts, stc; - - result = 0; - - setpwent(); - cap_setpwent(cappwd); - - pwds = getpwent(); - pwdc = cap_getpwent(cappwd); - if (passwd_compare(pwds, pwdc)) { - result |= GETPWENT0; - pwds = getpwent(); - pwdc = cap_getpwent(cappwd); - if (passwd_compare(pwds, pwdc)) - result |= GETPWENT1; - } - - getpwent_r(&sts, bufs, sizeof(bufs), &pwds); - cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); - if (passwd_compare(pwds, pwdc)) { - result |= GETPWENT_R0; - getpwent_r(&sts, bufs, sizeof(bufs), &pwds); - cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); - if (passwd_compare(pwds, pwdc)) - result |= GETPWENT_R1; - } - - setpwent(); - cap_setpwent(cappwd); - - getpwent_r(&sts, bufs, sizeof(bufs), &pwds); - cap_getpwent_r(cappwd, &stc, bufc, sizeof(bufc), &pwdc); - if (passwd_compare(pwds, pwdc)) - result |= GETPWENT_R2; - - pwds = getpwent(); - pwdc = cap_getpwent(cappwd); - if (passwd_compare(pwds, pwdc)) - result |= GETPWENT2; - - pwds = getpwnam("root"); - pwdc = cap_getpwnam(cappwd, "root"); - if (passwd_compare(pwds, pwdc)) { - pwds = getpwnam("operator"); - pwdc = cap_getpwnam(cappwd, "operator"); - if (passwd_compare(pwds, pwdc)) - result |= GETPWNAM; - } - - getpwnam_r("root", &sts, bufs, sizeof(bufs), &pwds); - cap_getpwnam_r(cappwd, "root", &stc, bufc, sizeof(bufc), &pwdc); - if (passwd_compare(pwds, pwdc)) { - getpwnam_r("operator", &sts, bufs, sizeof(bufs), &pwds); - cap_getpwnam_r(cappwd, "operator", &stc, bufc, sizeof(bufc), - &pwdc); - if (passwd_compare(pwds, pwdc)) - result |= GETPWNAM_R; - } - - pwds = getpwuid(UID_ROOT); - pwdc = cap_getpwuid(cappwd, UID_ROOT); - if (passwd_compare(pwds, pwdc)) { - pwds = getpwuid(UID_OPERATOR); - pwdc = cap_getpwuid(cappwd, UID_OPERATOR); - if (passwd_compare(pwds, pwdc)) - result |= GETPWUID; - } - - getpwuid_r(UID_ROOT, &sts, bufs, sizeof(bufs), &pwds); - cap_getpwuid_r(cappwd, UID_ROOT, &stc, bufc, sizeof(bufc), &pwdc); - if (passwd_compare(pwds, pwdc)) { - getpwuid_r(UID_OPERATOR, &sts, bufs, sizeof(bufs), &pwds); - cap_getpwuid_r(cappwd, UID_OPERATOR, &stc, bufc, sizeof(bufc), - &pwdc); - if (passwd_compare(pwds, pwdc)) - result |= GETPWUID_R; - } - - return (result); -} - -static void -test_cmds(cap_channel_t *origcappwd) -{ - cap_channel_t *cappwd; - const char *cmds[7], *fields[10], *names[6]; - uid_t uids[5]; - - fields[0] = "pw_name"; - fields[1] = "pw_passwd"; - fields[2] = "pw_uid"; - fields[3] = "pw_gid"; - fields[4] = "pw_change"; - fields[5] = "pw_class"; - fields[6] = "pw_gecos"; - fields[7] = "pw_dir"; - fields[8] = "pw_shell"; - fields[9] = "pw_expire"; - - names[0] = "root"; - names[1] = "toor"; - names[2] = "daemon"; - names[3] = "operator"; - names[4] = "bin"; - names[5] = "kmem"; - - uids[0] = 0; - uids[1] = 1; - uids[2] = 2; - uids[3] = 3; - uids[4] = 5; - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == 0); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: setpwent - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cap_setpwent(cappwd); - - cmds[0] = "getpwent"; - cmds[1] = "getpwent_r"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "setpwent"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 | - GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: setpwent - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cap_setpwent(cappwd); - - cmds[0] = "getpwent"; - cmds[1] = "getpwent_r"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "setpwent"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | GETPWENT_R0 | - GETPWENT_R1 | GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwent - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent_r"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwent"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwent - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent_r"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwent"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT_R2 | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwent_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwent_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwnam, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwent_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwnam"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwent_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT0 | GETPWENT1 | - GETPWNAM | GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwnam - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwnam"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam_r, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwnam - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam_r"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwnam"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM_R | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, - * getpwuid, getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwnam_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwnam_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, - * getpwuid, getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwnam_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwuid"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwnam_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWUID | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid_r - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwuid - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwuid"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid_r - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwuid - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwuid"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID_R)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid - * users: - * names: root, toor, daemon, operator, bin, kmem - * uids: - * Disallow: - * cmds: getpwuid_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID)); - - cap_close(cappwd); - - /* - * Allow: - * cmds: setpwent, getpwent, getpwent_r, getpwnam, getpwnam_r, - * getpwuid - * users: - * names: - * uids: 0, 1, 2, 3, 5 - * Disallow: - * cmds: getpwuid_r - * users: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 6) == 0); - cmds[0] = "setpwent"; - cmds[1] = "getpwent"; - cmds[2] = "getpwent_r"; - cmds[3] = "getpwnam"; - cmds[4] = "getpwnam_r"; - cmds[5] = "getpwuid"; - cmds[6] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 7) == -1 && errno == ENOTCAPABLE); - cmds[0] = "getpwuid_r"; - CHECK(cap_pwd_limit_cmds(cappwd, cmds, 1) == -1 && errno == ENOTCAPABLE); - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 5) == 0); - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | - GETPWNAM | GETPWNAM_R | GETPWUID)); - - cap_close(cappwd); -} - -#define PW_NAME _PWF_NAME -#define PW_PASSWD _PWF_PASSWD -#define PW_UID _PWF_UID -#define PW_GID _PWF_GID -#define PW_CHANGE _PWF_CHANGE -#define PW_CLASS _PWF_CLASS -#define PW_GECOS _PWF_GECOS -#define PW_DIR _PWF_DIR -#define PW_SHELL _PWF_SHELL -#define PW_EXPIRE _PWF_EXPIRE - -static unsigned int -passwd_fields(const struct passwd *pwd) -{ - unsigned int result; - - result = 0; - - if (pwd->pw_name != NULL && pwd->pw_name[0] != '\0') - result |= PW_NAME; -// else -// printf("No pw_name\n"); - - if (pwd->pw_passwd != NULL && pwd->pw_passwd[0] != '\0') - result |= PW_PASSWD; - else if ((pwd->pw_fields & _PWF_PASSWD) != 0) - result |= PW_PASSWD; -// else -// printf("No pw_passwd\n"); - - if (pwd->pw_uid != (uid_t)-1) - result |= PW_UID; -// else -// printf("No pw_uid\n"); - - if (pwd->pw_gid != (gid_t)-1) - result |= PW_GID; -// else -// printf("No pw_gid\n"); - - if (pwd->pw_change != 0 || (pwd->pw_fields & _PWF_CHANGE) != 0) - result |= PW_CHANGE; -// else -// printf("No pw_change\n"); - - if (pwd->pw_class != NULL && pwd->pw_class[0] != '\0') - result |= PW_CLASS; - else if ((pwd->pw_fields & _PWF_CLASS) != 0) - result |= PW_CLASS; -// else -// printf("No pw_class\n"); - - if (pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0') - result |= PW_GECOS; - else if ((pwd->pw_fields & _PWF_GECOS) != 0) - result |= PW_GECOS; -// else -// printf("No pw_gecos\n"); - - if (pwd->pw_dir != NULL && pwd->pw_dir[0] != '\0') - result |= PW_DIR; - else if ((pwd->pw_fields & _PWF_DIR) != 0) - result |= PW_DIR; -// else -// printf("No pw_dir\n"); - - if (pwd->pw_shell != NULL && pwd->pw_shell[0] != '\0') - result |= PW_SHELL; - else if ((pwd->pw_fields & _PWF_SHELL) != 0) - result |= PW_SHELL; -// else -// printf("No pw_shell\n"); - - if (pwd->pw_expire != 0 || (pwd->pw_fields & _PWF_EXPIRE) != 0) - result |= PW_EXPIRE; -// else -// printf("No pw_expire\n"); - -if (false && pwd->pw_fields != (int)result) { -printf("fields=0x%x != result=0x%x\n", (const unsigned int)pwd->pw_fields, result); -printf(" fields result\n"); -printf("PW_NAME %d %d\n", (pwd->pw_fields & PW_NAME) != 0, (result & PW_NAME) != 0); -printf("PW_PASSWD %d %d\n", (pwd->pw_fields & PW_PASSWD) != 0, (result & PW_PASSWD) != 0); -printf("PW_UID %d %d\n", (pwd->pw_fields & PW_UID) != 0, (result & PW_UID) != 0); -printf("PW_GID %d %d\n", (pwd->pw_fields & PW_GID) != 0, (result & PW_GID) != 0); -printf("PW_CHANGE %d %d\n", (pwd->pw_fields & PW_CHANGE) != 0, (result & PW_CHANGE) != 0); -printf("PW_CLASS %d %d\n", (pwd->pw_fields & PW_CLASS) != 0, (result & PW_CLASS) != 0); -printf("PW_GECOS %d %d\n", (pwd->pw_fields & PW_GECOS) != 0, (result & PW_GECOS) != 0); -printf("PW_DIR %d %d\n", (pwd->pw_fields & PW_DIR) != 0, (result & PW_DIR) != 0); -printf("PW_SHELL %d %d\n", (pwd->pw_fields & PW_SHELL) != 0, (result & PW_SHELL) != 0); -printf("PW_EXPIRE %d %d\n", (pwd->pw_fields & PW_EXPIRE) != 0, (result & PW_EXPIRE) != 0); -} - -//printf("result=0x%x\n", result); - return (result); -} - -static bool -runtest_fields(cap_channel_t *cappwd, unsigned int expected) -{ - char buf[1024]; - struct passwd *pwd; - struct passwd st; - -//printf("expected=0x%x\n", expected); - cap_setpwent(cappwd); - pwd = cap_getpwent(cappwd); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - cap_setpwent(cappwd); - cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - pwd = cap_getpwnam(cappwd, "root"); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - cap_getpwnam_r(cappwd, "root", &st, buf, sizeof(buf), &pwd); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - pwd = cap_getpwuid(cappwd, UID_ROOT); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - cap_getpwuid_r(cappwd, UID_ROOT, &st, buf, sizeof(buf), &pwd); - if ((passwd_fields(pwd) & ~expected) != 0) - return (false); - - return (true); -} - -static void -test_fields(cap_channel_t *origcappwd) -{ - cap_channel_t *cappwd; - const char *fields[10]; - - /* No limits. */ - - CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID | - PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL | - PW_EXPIRE)); - - /* - * Allow: - * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change, pw_class, - * pw_gecos, pw_dir, pw_shell, pw_expire - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_name"; - fields[1] = "pw_passwd"; - fields[2] = "pw_uid"; - fields[3] = "pw_gid"; - fields[4] = "pw_change"; - fields[5] = "pw_class"; - fields[6] = "pw_gecos"; - fields[7] = "pw_dir"; - fields[8] = "pw_shell"; - fields[9] = "pw_expire"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 10) == 0); - - CHECK(runtest_fields(origcappwd, PW_NAME | PW_PASSWD | PW_UID | - PW_GID | PW_CHANGE | PW_CLASS | PW_GECOS | PW_DIR | PW_SHELL | - PW_EXPIRE)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_name, pw_passwd, pw_uid, pw_gid, pw_change - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_name"; - fields[1] = "pw_passwd"; - fields[2] = "pw_uid"; - fields[3] = "pw_gid"; - fields[4] = "pw_change"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); - fields[5] = "pw_class"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_class"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_NAME | PW_PASSWD | PW_UID | - PW_GID | PW_CHANGE)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_class, pw_gecos, pw_dir, pw_shell, pw_expire - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_class"; - fields[1] = "pw_gecos"; - fields[2] = "pw_dir"; - fields[3] = "pw_shell"; - fields[4] = "pw_expire"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); - fields[5] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_CLASS | PW_GECOS | PW_DIR | - PW_SHELL | PW_EXPIRE)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_name, pw_uid, pw_change, pw_gecos, pw_shell - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_name"; - fields[1] = "pw_uid"; - fields[2] = "pw_change"; - fields[3] = "pw_gecos"; - fields[4] = "pw_shell"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); - fields[5] = "pw_class"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_class"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_NAME | PW_UID | PW_CHANGE | - PW_GECOS | PW_SHELL)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_passwd, pw_gid, pw_class, pw_dir, pw_expire - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_passwd"; - fields[1] = "pw_gid"; - fields[2] = "pw_class"; - fields[3] = "pw_dir"; - fields[4] = "pw_expire"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 5) == 0); - fields[5] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 6) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_PASSWD | PW_GID | PW_CLASS | - PW_DIR | PW_EXPIRE)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_uid, pw_class, pw_shell - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_uid"; - fields[1] = "pw_class"; - fields[2] = "pw_shell"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 3) == 0); - fields[3] = "pw_change"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 4) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_change"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_UID | PW_CLASS | PW_SHELL)); - - cap_close(cappwd); - - /* - * Allow: - * fields: pw_change - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - fields[0] = "pw_change"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == 0); - fields[1] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 2) == -1 && - errno == ENOTCAPABLE); - fields[0] = "pw_uid"; - CHECK(cap_pwd_limit_fields(cappwd, fields, 1) == -1 && - errno == ENOTCAPABLE); - - CHECK(runtest_fields(cappwd, PW_CHANGE)); - - cap_close(cappwd); -} - -static bool -runtest_users(cap_channel_t *cappwd, const char **names, const uid_t *uids, - size_t nusers) -{ - char buf[1024]; - struct passwd *pwd; - struct passwd st; - unsigned int i, got; - - cap_setpwent(cappwd); - got = 0; - for (;;) { - pwd = cap_getpwent(cappwd); - if (pwd == NULL) - break; - got++; - for (i = 0; i < nusers; i++) { - if (strcmp(names[i], pwd->pw_name) == 0 && - uids[i] == pwd->pw_uid) { - break; - } - } - if (i == nusers) - return (false); - } - if (got != nusers) - return (false); - - cap_setpwent(cappwd); - got = 0; - for (;;) { - cap_getpwent_r(cappwd, &st, buf, sizeof(buf), &pwd); - if (pwd == NULL) - break; - got++; - for (i = 0; i < nusers; i++) { - if (strcmp(names[i], pwd->pw_name) == 0 && - uids[i] == pwd->pw_uid) { - break; - } - } - if (i == nusers) - return (false); - } - if (got != nusers) - return (false); - - for (i = 0; i < nusers; i++) { - pwd = cap_getpwnam(cappwd, names[i]); - if (pwd == NULL) - return (false); - } - - for (i = 0; i < nusers; i++) { - cap_getpwnam_r(cappwd, names[i], &st, buf, sizeof(buf), &pwd); - if (pwd == NULL) - return (false); - } - - for (i = 0; i < nusers; i++) { - pwd = cap_getpwuid(cappwd, uids[i]); - if (pwd == NULL) - return (false); - } - - for (i = 0; i < nusers; i++) { - cap_getpwuid_r(cappwd, uids[i], &st, buf, sizeof(buf), &pwd); - if (pwd == NULL) - return (false); - } - - return (true); -} - -static void -test_users(cap_channel_t *origcappwd) -{ - cap_channel_t *cappwd; - const char *names[6]; - uid_t uids[6]; - - /* - * Allow: - * users: - * names: root, toor, daemon, operator, bin, tty - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "root"; - names[1] = "toor"; - names[2] = "daemon"; - names[3] = "operator"; - names[4] = "bin"; - names[5] = "tty"; - CHECK(cap_pwd_limit_users(cappwd, names, 6, NULL, 0) == 0); - uids[0] = 0; - uids[1] = 0; - uids[2] = 1; - uids[3] = 2; - uids[4] = 3; - uids[5] = 4; - - CHECK(runtest_users(cappwd, names, uids, 6)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: daemon, operator, bin - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "operator"; - names[2] = "bin"; - CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0); - names[3] = "tty"; - CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "tty"; - CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - uids[0] = 1; - uids[1] = 2; - uids[2] = 3; - - CHECK(runtest_users(cappwd, names, uids, 3)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: daemon, bin, tty - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "bin"; - names[2] = "tty"; - CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == 0); - names[3] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 4, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - uids[0] = 1; - uids[1] = 3; - uids[2] = 4; - - CHECK(runtest_users(cappwd, names, uids, 3)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: - * uids: 1, 2, 3 - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "operator"; - names[2] = "bin"; - uids[0] = 1; - uids[1] = 2; - uids[2] = 3; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0); - uids[3] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 && - errno == ENOTCAPABLE); - uids[0] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && - errno == ENOTCAPABLE); - uids[0] = 1; - - CHECK(runtest_users(cappwd, names, uids, 3)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: - * uids: 1, 3, 4 - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "bin"; - names[2] = "tty"; - uids[0] = 1; - uids[1] = 3; - uids[2] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == 0); - uids[3] = 5; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 4) == -1 && - errno == ENOTCAPABLE); - uids[0] = 5; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && - errno == ENOTCAPABLE); - uids[0] = 1; - - CHECK(runtest_users(cappwd, names, uids, 3)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: bin - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "bin"; - CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == 0); - names[1] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "bin"; - uids[0] = 3; - - CHECK(runtest_users(cappwd, names, uids, 1)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: daemon, tty - * uids: - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "tty"; - CHECK(cap_pwd_limit_users(cappwd, names, 2, NULL, 0) == 0); - names[2] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 3, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "operator"; - CHECK(cap_pwd_limit_users(cappwd, names, 1, NULL, 0) == -1 && - errno == ENOTCAPABLE); - names[0] = "daemon"; - uids[0] = 1; - uids[1] = 4; - - CHECK(runtest_users(cappwd, names, uids, 2)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: - * uids: 3 - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "bin"; - uids[0] = 3; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == 0); - uids[1] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == -1 && - errno == ENOTCAPABLE); - uids[0] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && - errno == ENOTCAPABLE); - uids[0] = 3; - - CHECK(runtest_users(cappwd, names, uids, 1)); - - cap_close(cappwd); - - /* - * Allow: - * users: - * names: - * uids: 1, 4 - */ - cappwd = cap_clone(origcappwd); - CHECK(cappwd != NULL); - - names[0] = "daemon"; - names[1] = "tty"; - uids[0] = 1; - uids[1] = 4; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 2) == 0); - uids[2] = 3; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 3) == -1 && - errno == ENOTCAPABLE); - uids[0] = 3; - CHECK(cap_pwd_limit_users(cappwd, NULL, 0, uids, 1) == -1 && - errno == ENOTCAPABLE); - uids[0] = 1; - - CHECK(runtest_users(cappwd, names, uids, 2)); - - cap_close(cappwd); -} - -int -main(void) -{ - cap_channel_t *capcas, *cappwd; - - printf("1..188\n"); - - capcas = cap_init(); - CHECKX(capcas != NULL); - - cappwd = cap_service_open(capcas, "system.pwd"); - CHECKX(cappwd != NULL); - - cap_close(capcas); - - /* No limits. */ - - CHECK(runtest_cmds(cappwd) == (GETPWENT | GETPWENT_R | GETPWNAM | - GETPWNAM_R | GETPWUID | GETPWUID_R)); - - test_cmds(cappwd); - - test_fields(cappwd); - - test_users(cappwd); - - cap_close(cappwd); - - exit(0); -} Index: head/tools/regression/capsicum/libcasper/sysctl.c =================================================================== --- head/tools/regression/capsicum/libcasper/sysctl.c +++ head/tools/regression/capsicum/libcasper/sysctl.c @@ -1,1510 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -/* - * We need some sysctls to perform the tests on. - * We remember their values and restore them afer the test is done. - */ -#define SYSCTL0_PARENT "kern" -#define SYSCTL0_NAME "kern.sync_on_panic" -#define SYSCTL1_PARENT "debug" -#define SYSCTL1_NAME "debug.minidump" - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - ntest++; \ -} while (0) -#define CHECKX(expr) do { \ - if ((expr)) { \ - printf("ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - } else { \ - printf("not ok %d %s:%u\n", ntest, __FILE__, __LINE__); \ - exit(1); \ - } \ - ntest++; \ -} while (0) - -#define SYSCTL0_READ0 0x0001 -#define SYSCTL0_READ1 0x0002 -#define SYSCTL0_READ2 0x0004 -#define SYSCTL0_WRITE 0x0008 -#define SYSCTL0_READ_WRITE 0x0010 -#define SYSCTL1_READ0 0x0020 -#define SYSCTL1_READ1 0x0040 -#define SYSCTL1_READ2 0x0080 -#define SYSCTL1_WRITE 0x0100 -#define SYSCTL1_READ_WRITE 0x0200 - -static unsigned int -runtest(cap_channel_t *capsysctl) -{ - unsigned int result; - int oldvalue, newvalue; - size_t oldsize; - - result = 0; - - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize, - NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue)) - result |= SYSCTL0_READ0; - } - - newvalue = 123; - if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, NULL, NULL, &newvalue, - sizeof(newvalue)) == 0) { - result |= SYSCTL0_WRITE; - } - - if ((result & SYSCTL0_WRITE) != 0) { - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, - &oldsize, NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 123) - result |= SYSCTL0_READ1; - } - } - - oldsize = sizeof(oldvalue); - newvalue = 4567; - if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, &oldsize, - &newvalue, sizeof(newvalue)) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 123) - result |= SYSCTL0_READ_WRITE; - } - - if ((result & SYSCTL0_READ_WRITE) != 0) { - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL0_NAME, &oldvalue, - &oldsize, NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 4567) - result |= SYSCTL0_READ2; - } - } - - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize, - NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue)) - result |= SYSCTL1_READ0; - } - - newvalue = 506; - if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, NULL, NULL, &newvalue, - sizeof(newvalue)) == 0) { - result |= SYSCTL1_WRITE; - } - - if ((result & SYSCTL1_WRITE) != 0) { - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, - &oldsize, NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 506) - result |= SYSCTL1_READ1; - } - } - - oldsize = sizeof(oldvalue); - newvalue = 7008; - if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, &oldsize, - &newvalue, sizeof(newvalue)) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 506) - result |= SYSCTL1_READ_WRITE; - } - - if ((result & SYSCTL1_READ_WRITE) != 0) { - oldsize = sizeof(oldvalue); - if (cap_sysctlbyname(capsysctl, SYSCTL1_NAME, &oldvalue, - &oldsize, NULL, 0) == 0) { - if (oldsize == sizeof(oldvalue) && oldvalue == 7008) - result |= SYSCTL1_READ2; - } - } - - return (result); -} - -static void -test_operation(cap_channel_t *origcapsysctl) -{ - cap_channel_t *capsysctl; - nvlist_t *limits; - - /* - * Allow: - * SYSCTL0_PARENT/RDWR/RECURSIVE - * SYSCTL1_PARENT/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, "foo.bar", - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, "foo.bar", - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == SYSCTL0_READ0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/RDWR/RECURSIVE - * SYSCTL1_NAME/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/RDWR - * SYSCTL1_PARENT/RDWR - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/RDWR - * SYSCTL1_NAME/RDWR - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/RDWR - * SYSCTL1_PARENT/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | - SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/RDWR - * SYSCTL1_NAME/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ/RECURSIVE - * SYSCTL1_PARENT/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ/RECURSIVE - * SYSCTL1_NAME/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ - * SYSCTL1_PARENT/READ - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ - * SYSCTL1_NAME/READ - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ - * SYSCTL1_PARENT/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_READ0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ - * SYSCTL1_NAME/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_READ0)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/WRITE/RECURSIVE - * SYSCTL1_PARENT/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/WRITE/RECURSIVE - * SYSCTL1_NAME/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/WRITE - * SYSCTL1_PARENT/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/WRITE - * SYSCTL1_NAME/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/WRITE - * SYSCTL1_PARENT/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_WRITE); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/WRITE - * SYSCTL1_NAME/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_WRITE | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ/RECURSIVE - * SYSCTL1_PARENT/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ/RECURSIVE - * SYSCTL1_NAME/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ - * SYSCTL1_PARENT/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ - * SYSCTL1_NAME/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ - * SYSCTL1_PARENT/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == SYSCTL1_WRITE); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_NAME/READ - * SYSCTL1_NAME/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL1_WRITE)); - - cap_close(capsysctl); -} - -static void -test_names(cap_channel_t *origcapsysctl) -{ - cap_channel_t *capsysctl; - nvlist_t *limits; - - /* - * Allow: - * SYSCTL0_PARENT/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL0_READ0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/READ/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_READ | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_READ0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL0_WRITE); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/WRITE/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_WRITE | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_WRITE); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/RDWR/RECURSIVE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - nvlist_add_number(limits, SYSCTL1_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, - CAP_SYSCTL_RDWR | CAP_SYSCTL_RECURSIVE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | - SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/READ - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/READ - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_READ); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_READ0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/WRITE - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_WRITE); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == SYSCTL1_WRITE); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL0_PARENT/RDWR - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_PARENT, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_PARENT, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == 0); - - cap_close(capsysctl); - - /* - * Allow: - * SYSCTL1_NAME/RDWR - */ - - capsysctl = cap_clone(origcapsysctl); - CHECK(capsysctl != NULL); - - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == 0); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - nvlist_add_number(limits, SYSCTL1_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - limits = nvlist_create(0); - nvlist_add_number(limits, SYSCTL0_NAME, CAP_SYSCTL_RDWR); - CHECK(cap_limit_set(capsysctl, limits) == -1 && errno == ENOTCAPABLE); - - CHECK(runtest(capsysctl) == (SYSCTL1_READ0 | SYSCTL1_READ1 | - SYSCTL1_READ2 | SYSCTL1_WRITE | SYSCTL1_READ_WRITE)); - - cap_close(capsysctl); -} - -int -main(void) -{ - cap_channel_t *capcas, *capsysctl; - int scvalue0, scvalue1; - size_t scsize; - - printf("1..256\n"); - - scsize = sizeof(scvalue0); - CHECKX(sysctlbyname(SYSCTL0_NAME, &scvalue0, &scsize, NULL, 0) == 0); - CHECKX(scsize == sizeof(scvalue0)); - scsize = sizeof(scvalue1); - CHECKX(sysctlbyname(SYSCTL1_NAME, &scvalue1, &scsize, NULL, 0) == 0); - CHECKX(scsize == sizeof(scvalue1)); - - capcas = cap_init(); - CHECKX(capcas != NULL); - - capsysctl = cap_service_open(capcas, "system.sysctl"); - CHECKX(capsysctl != NULL); - - cap_close(capcas); - - /* No limits set. */ - - CHECK(runtest(capsysctl) == (SYSCTL0_READ0 | SYSCTL0_READ1 | - SYSCTL0_READ2 | SYSCTL0_WRITE | SYSCTL0_READ_WRITE | - SYSCTL1_READ0 | SYSCTL1_READ1 | SYSCTL1_READ2 | SYSCTL1_WRITE | - SYSCTL1_READ_WRITE)); - - test_operation(capsysctl); - - test_names(capsysctl); - - cap_close(capsysctl); - - CHECK(sysctlbyname(SYSCTL0_NAME, NULL, NULL, &scvalue0, - sizeof(scvalue0)) == 0); - CHECK(sysctlbyname(SYSCTL1_NAME, NULL, NULL, &scvalue1, - sizeof(scvalue1)) == 0); - - exit(0); -}