1870c2f7aSEnji Cooper /*- 2870c2f7aSEnji Cooper * Copyright (c) 2005 McAfee, Inc. 3870c2f7aSEnji Cooper * All rights reserved. 4870c2f7aSEnji Cooper * 5870c2f7aSEnji Cooper * Redistribution and use in source and binary forms, with or without 6870c2f7aSEnji Cooper * modification, are permitted provided that the following conditions 7870c2f7aSEnji Cooper * are met: 8870c2f7aSEnji Cooper * 1. Redistributions of source code must retain the above copyright 9870c2f7aSEnji Cooper * notice, this list of conditions and the following disclaimer. 10870c2f7aSEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 11870c2f7aSEnji Cooper * notice, this list of conditions and the following disclaimer in the 12870c2f7aSEnji Cooper * documentation and/or other materials provided with the distribution. 13870c2f7aSEnji Cooper * 14870c2f7aSEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15870c2f7aSEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16870c2f7aSEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17870c2f7aSEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18870c2f7aSEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19870c2f7aSEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20870c2f7aSEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21870c2f7aSEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22870c2f7aSEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23870c2f7aSEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24870c2f7aSEnji Cooper * SUCH DAMAGE. 25870c2f7aSEnji Cooper * 26870c2f7aSEnji Cooper * $FreeBSD$ 27870c2f7aSEnji Cooper */ 28870c2f7aSEnji Cooper 29870c2f7aSEnji Cooper #include <sys/param.h> 30870c2f7aSEnji Cooper #include <sys/mac.h> 31870c2f7aSEnji Cooper #include <sys/mount.h> 32870c2f7aSEnji Cooper 33870c2f7aSEnji Cooper #include <security/mac_bsdextended/mac_bsdextended.h> 34870c2f7aSEnji Cooper 35870c2f7aSEnji Cooper #include <err.h> 36870c2f7aSEnji Cooper #include <errno.h> 37870c2f7aSEnji Cooper #include <grp.h> 38870c2f7aSEnji Cooper #include <pwd.h> 39870c2f7aSEnji Cooper #include <stdio.h> 40870c2f7aSEnji Cooper #include <stdlib.h> 41870c2f7aSEnji Cooper #include <string.h> 42870c2f7aSEnji Cooper #include <ugidfw.h> 43870c2f7aSEnji Cooper #include <unistd.h> 44870c2f7aSEnji Cooper 45870c2f7aSEnji Cooper /* 46870c2f7aSEnji Cooper * Starting point for a regression test for mac_bsdextended(4) and the 47870c2f7aSEnji Cooper * supporting libugidfw(3). 48870c2f7aSEnji Cooper */ 49870c2f7aSEnji Cooper 50870c2f7aSEnji Cooper /* 51870c2f7aSEnji Cooper * This section of the regression test passes some test cases through the 52870c2f7aSEnji Cooper * rule<->string routines to confirm they work approximately as desired. 53870c2f7aSEnji Cooper */ 54870c2f7aSEnji Cooper 55870c2f7aSEnji Cooper /* 56870c2f7aSEnji Cooper * List of users and groups we must check exists before we can begin, since 57870c2f7aSEnji Cooper * they are used in the string test rules. We use users and groups that will 58870c2f7aSEnji Cooper * always exist in a default install used for regression testing. 59870c2f7aSEnji Cooper */ 60870c2f7aSEnji Cooper static const char *test_users[] = { 61870c2f7aSEnji Cooper "root", 62870c2f7aSEnji Cooper "daemon", 63870c2f7aSEnji Cooper "operator", 64870c2f7aSEnji Cooper "bin", 65870c2f7aSEnji Cooper }; 66870c2f7aSEnji Cooper 67870c2f7aSEnji Cooper static const char *test_groups[] = { 68870c2f7aSEnji Cooper "wheel", 69870c2f7aSEnji Cooper "daemon", 70870c2f7aSEnji Cooper "operator", 71870c2f7aSEnji Cooper "bin", 72870c2f7aSEnji Cooper }; 73870c2f7aSEnji Cooper 74*f614ceafSEnji Cooper static int test_num; 75870c2f7aSEnji Cooper 76870c2f7aSEnji Cooper /* 77870c2f7aSEnji Cooper * List of test strings that must go in (and come out) of libugidfw intact. 78870c2f7aSEnji Cooper */ 79870c2f7aSEnji Cooper static const char *test_strings[] = { 80870c2f7aSEnji Cooper /* Variations on subject and object uids. */ 81870c2f7aSEnji Cooper "subject uid root object uid root mode n", 82870c2f7aSEnji Cooper "subject uid root object uid daemon mode n", 83870c2f7aSEnji Cooper "subject uid daemon object uid root mode n", 84870c2f7aSEnji Cooper "subject uid daemon object uid daemon mode n", 85870c2f7aSEnji Cooper /* Variations on mode. */ 86870c2f7aSEnji Cooper "subject uid root object uid root mode a", 87870c2f7aSEnji Cooper "subject uid root object uid root mode r", 88870c2f7aSEnji Cooper "subject uid root object uid root mode s", 89870c2f7aSEnji Cooper "subject uid root object uid root mode w", 90870c2f7aSEnji Cooper "subject uid root object uid root mode x", 91870c2f7aSEnji Cooper "subject uid root object uid root mode arswx", 92870c2f7aSEnji Cooper /* Variations on subject and object gids. */ 93870c2f7aSEnji Cooper "subject gid wheel object gid wheel mode n", 94870c2f7aSEnji Cooper "subject gid wheel object gid daemon mode n", 95870c2f7aSEnji Cooper "subject gid daemon object gid wheel mode n", 96870c2f7aSEnji Cooper "subject gid daemon object gid daemon mode n", 97870c2f7aSEnji Cooper /* Subject uids and subject gids. */ 98870c2f7aSEnji Cooper "subject uid bin gid daemon object uid operator gid wheel mode n", 99870c2f7aSEnji Cooper /* Not */ 100870c2f7aSEnji Cooper "subject not uid operator object uid bin mode n", 101870c2f7aSEnji Cooper "subject uid bin object not uid operator mode n", 102870c2f7aSEnji Cooper "subject not uid daemon object not uid operator mode n", 103870c2f7aSEnji Cooper /* Ranges */ 104870c2f7aSEnji Cooper "subject uid root:operator object gid wheel:bin mode n", 105870c2f7aSEnji Cooper /* Jail ID */ 106870c2f7aSEnji Cooper "subject jailid 1 object uid root mode n", 107870c2f7aSEnji Cooper /* Filesys */ 108870c2f7aSEnji Cooper "subject uid root object filesys / mode n", 109870c2f7aSEnji Cooper "subject uid root object filesys /dev mode n", 110870c2f7aSEnji Cooper /* S/UGID */ 111870c2f7aSEnji Cooper "subject not uid root object sgid mode n", 112870c2f7aSEnji Cooper "subject not uid root object sgid mode n", 113870c2f7aSEnji Cooper /* Matching uid/gid */ 114870c2f7aSEnji Cooper "subject not uid root:operator object not uid_of_subject mode n", 115870c2f7aSEnji Cooper "subject not gid wheel:bin object not gid_of_subject mode n", 116870c2f7aSEnji Cooper /* Object types */ 117870c2f7aSEnji Cooper "subject uid root object type a mode a", 118870c2f7aSEnji Cooper "subject uid root object type r mode a", 119870c2f7aSEnji Cooper "subject uid root object type d mode a", 120870c2f7aSEnji Cooper "subject uid root object type b mode a", 121870c2f7aSEnji Cooper "subject uid root object type c mode a", 122870c2f7aSEnji Cooper "subject uid root object type l mode a", 123870c2f7aSEnji Cooper "subject uid root object type s mode a", 124870c2f7aSEnji Cooper "subject uid root object type rbc mode a", 125870c2f7aSEnji Cooper "subject uid root object type dls mode a", 126870c2f7aSEnji Cooper /* Empty rules always match */ 127870c2f7aSEnji Cooper "subject object mode a", 128870c2f7aSEnji Cooper /* Partial negations */ 129870c2f7aSEnji Cooper "subject ! uid root object mode n", 130870c2f7aSEnji Cooper "subject ! gid wheel object mode n", 131870c2f7aSEnji Cooper "subject ! jailid 2 object mode n", 132870c2f7aSEnji Cooper "subject object ! uid root mode n", 133870c2f7aSEnji Cooper "subject object ! gid wheel mode n", 134870c2f7aSEnji Cooper "subject object ! filesys / mode n", 135870c2f7aSEnji Cooper "subject object ! suid mode n", 136870c2f7aSEnji Cooper "subject object ! sgid mode n", 137870c2f7aSEnji Cooper "subject object ! uid_of_subject mode n", 138870c2f7aSEnji Cooper "subject object ! gid_of_subject mode n", 139870c2f7aSEnji Cooper "subject object ! type d mode n", 140870c2f7aSEnji Cooper /* All out nonsense */ 141870c2f7aSEnji Cooper "subject uid root ! gid wheel:bin ! jailid 1 " 142870c2f7aSEnji Cooper "object ! uid root:daemon gid daemon filesys / suid sgid uid_of_subject gid_of_subject ! type r " 143870c2f7aSEnji Cooper "mode rsx", 144870c2f7aSEnji Cooper }; 145870c2f7aSEnji Cooper 146870c2f7aSEnji Cooper static void 147870c2f7aSEnji Cooper test_libugidfw_strings(void) 148870c2f7aSEnji Cooper { 149870c2f7aSEnji Cooper struct mac_bsdextended_rule rule; 150870c2f7aSEnji Cooper char errorstr[256]; 151870c2f7aSEnji Cooper char rulestr[256]; 152*f614ceafSEnji Cooper size_t i; 153*f614ceafSEnji Cooper int error; 154870c2f7aSEnji Cooper 155870c2f7aSEnji Cooper for (i = 0; i < nitems(test_users); i++, test_num++) { 156870c2f7aSEnji Cooper if (getpwnam(test_users[i]) == NULL) 157870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getpwnam(%s) " 158870c2f7aSEnji Cooper "failed: %s\n", test_num, test_users[i], strerror(errno)); 159870c2f7aSEnji Cooper else 160870c2f7aSEnji Cooper printf("ok %d\n", test_num); 161870c2f7aSEnji Cooper } 162870c2f7aSEnji Cooper 163870c2f7aSEnji Cooper for (i = 0; i < nitems(test_groups); i++, test_num++) { 164870c2f7aSEnji Cooper if (getgrnam(test_groups[i]) == NULL) 165870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getgrnam(%s) " 166870c2f7aSEnji Cooper "failed: %s\n", test_num, test_groups[i], strerror(errno)); 167870c2f7aSEnji Cooper else 168870c2f7aSEnji Cooper printf("ok %d\n", test_num); 169870c2f7aSEnji Cooper } 170870c2f7aSEnji Cooper 171870c2f7aSEnji Cooper for (i = 0; i < nitems(test_strings); i++) { 172870c2f7aSEnji Cooper error = bsde_parse_rule_string(test_strings[i], &rule, 173870c2f7aSEnji Cooper sizeof(errorstr), errorstr); 174870c2f7aSEnji Cooper if (error == -1) 175*f614ceafSEnji Cooper printf("not ok %d # bsde_parse_rule_string: '%s' (%zu) " 176870c2f7aSEnji Cooper "failed: %s\n", test_num, test_strings[i], i, errorstr); 177870c2f7aSEnji Cooper else 178870c2f7aSEnji Cooper printf("ok %d\n", test_num); 179870c2f7aSEnji Cooper test_num++; 180870c2f7aSEnji Cooper 181870c2f7aSEnji Cooper error = bsde_rule_to_string(&rule, rulestr, sizeof(rulestr)); 182870c2f7aSEnji Cooper if (error < 0) 183870c2f7aSEnji Cooper printf("not ok %d # bsde_rule_to_string: rule for '%s' " 184870c2f7aSEnji Cooper "returned %d\n", test_num, test_strings[i], error); 185870c2f7aSEnji Cooper else 186870c2f7aSEnji Cooper printf("ok %d\n", test_num); 187870c2f7aSEnji Cooper test_num++; 188870c2f7aSEnji Cooper 189870c2f7aSEnji Cooper if (strcmp(test_strings[i], rulestr) != 0) 190870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw: '%s' in, '%s' " 191870c2f7aSEnji Cooper "out\n", test_num, test_strings[i], rulestr); 192870c2f7aSEnji Cooper else 193870c2f7aSEnji Cooper printf("ok %d\n", test_num); 194870c2f7aSEnji Cooper test_num++; 195870c2f7aSEnji Cooper } 196870c2f7aSEnji Cooper } 197870c2f7aSEnji Cooper 198870c2f7aSEnji Cooper int 199870c2f7aSEnji Cooper main(void) 200870c2f7aSEnji Cooper { 201870c2f7aSEnji Cooper char errorstr[256]; 202870c2f7aSEnji Cooper int count, slots; 203870c2f7aSEnji Cooper 204870c2f7aSEnji Cooper test_num = 1; 205870c2f7aSEnji Cooper 206870c2f7aSEnji Cooper /* Print an error if a non-root user attemps to run the tests. */ 207870c2f7aSEnji Cooper if (getuid() != 0) { 208870c2f7aSEnji Cooper printf("1..0 # SKIP you must be root\n"); 209870c2f7aSEnji Cooper return (0); 210870c2f7aSEnji Cooper } 211870c2f7aSEnji Cooper 212870c2f7aSEnji Cooper switch (mac_is_present("bsdextended")) { 213870c2f7aSEnji Cooper case -1: 214870c2f7aSEnji Cooper printf("1..0 # SKIP mac_is_present failed: %s\n", 215870c2f7aSEnji Cooper strerror(errno)); 216870c2f7aSEnji Cooper return (0); 217870c2f7aSEnji Cooper case 1: 218870c2f7aSEnji Cooper break; 219870c2f7aSEnji Cooper case 0: 220870c2f7aSEnji Cooper default: 221870c2f7aSEnji Cooper printf("1..0 # SKIP mac_bsdextended not loaded\n"); 222870c2f7aSEnji Cooper return (0); 223870c2f7aSEnji Cooper } 224870c2f7aSEnji Cooper 225ad25988fSEnji Cooper printf("1..%lu\n", nitems(test_users) + nitems(test_groups) + 226ad25988fSEnji Cooper 3 * nitems(test_strings) + 2); 227ad25988fSEnji Cooper 228ad25988fSEnji Cooper test_libugidfw_strings(); 229ad25988fSEnji Cooper 230870c2f7aSEnji Cooper /* 231870c2f7aSEnji Cooper * Some simple up-front checks to see if we're able to query the 232870c2f7aSEnji Cooper * policy for basic state. We want the rule count to be 0 before 233870c2f7aSEnji Cooper * starting, but "slots" is a property of prior runs and so we ignore 234870c2f7aSEnji Cooper * the return value. 235870c2f7aSEnji Cooper */ 236870c2f7aSEnji Cooper count = bsde_get_rule_count(sizeof(errorstr), errorstr); 237870c2f7aSEnji Cooper if (count == -1) 238870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_count: %s\n", test_num, 239870c2f7aSEnji Cooper errorstr); 240870c2f7aSEnji Cooper else 241870c2f7aSEnji Cooper printf("ok %d\n", test_num); 242870c2f7aSEnji Cooper 243870c2f7aSEnji Cooper test_num++; 244870c2f7aSEnji Cooper 245870c2f7aSEnji Cooper slots = bsde_get_rule_slots(sizeof(errorstr), errorstr); 246870c2f7aSEnji Cooper if (slots == -1) 247870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_slots: %s\n", test_num, 248870c2f7aSEnji Cooper errorstr); 249870c2f7aSEnji Cooper else 250870c2f7aSEnji Cooper printf("ok %d\n", test_num); 251870c2f7aSEnji Cooper 252870c2f7aSEnji Cooper return (0); 253870c2f7aSEnji Cooper } 254