1*870c2f7aSEnji Cooper /*- 2*870c2f7aSEnji Cooper * Copyright (c) 2005 McAfee, Inc. 3*870c2f7aSEnji Cooper * All rights reserved. 4*870c2f7aSEnji Cooper * 5*870c2f7aSEnji Cooper * Redistribution and use in source and binary forms, with or without 6*870c2f7aSEnji Cooper * modification, are permitted provided that the following conditions 7*870c2f7aSEnji Cooper * are met: 8*870c2f7aSEnji Cooper * 1. Redistributions of source code must retain the above copyright 9*870c2f7aSEnji Cooper * notice, this list of conditions and the following disclaimer. 10*870c2f7aSEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 11*870c2f7aSEnji Cooper * notice, this list of conditions and the following disclaimer in the 12*870c2f7aSEnji Cooper * documentation and/or other materials provided with the distribution. 13*870c2f7aSEnji Cooper * 14*870c2f7aSEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*870c2f7aSEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*870c2f7aSEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*870c2f7aSEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*870c2f7aSEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*870c2f7aSEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*870c2f7aSEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*870c2f7aSEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*870c2f7aSEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*870c2f7aSEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*870c2f7aSEnji Cooper * SUCH DAMAGE. 25*870c2f7aSEnji Cooper * 26*870c2f7aSEnji Cooper * $FreeBSD$ 27*870c2f7aSEnji Cooper */ 28*870c2f7aSEnji Cooper 29*870c2f7aSEnji Cooper #include <sys/param.h> 30*870c2f7aSEnji Cooper #include <sys/mac.h> 31*870c2f7aSEnji Cooper #include <sys/mount.h> 32*870c2f7aSEnji Cooper 33*870c2f7aSEnji Cooper #include <security/mac_bsdextended/mac_bsdextended.h> 34*870c2f7aSEnji Cooper 35*870c2f7aSEnji Cooper #include <err.h> 36*870c2f7aSEnji Cooper #include <errno.h> 37*870c2f7aSEnji Cooper #include <grp.h> 38*870c2f7aSEnji Cooper #include <pwd.h> 39*870c2f7aSEnji Cooper #include <stdio.h> 40*870c2f7aSEnji Cooper #include <stdlib.h> 41*870c2f7aSEnji Cooper #include <string.h> 42*870c2f7aSEnji Cooper #include <ugidfw.h> 43*870c2f7aSEnji Cooper #include <unistd.h> 44*870c2f7aSEnji Cooper 45*870c2f7aSEnji Cooper /* 46*870c2f7aSEnji Cooper * Starting point for a regression test for mac_bsdextended(4) and the 47*870c2f7aSEnji Cooper * supporting libugidfw(3). 48*870c2f7aSEnji Cooper */ 49*870c2f7aSEnji Cooper 50*870c2f7aSEnji Cooper /* 51*870c2f7aSEnji Cooper * This section of the regression test passes some test cases through the 52*870c2f7aSEnji Cooper * rule<->string routines to confirm they work approximately as desired. 53*870c2f7aSEnji Cooper */ 54*870c2f7aSEnji Cooper 55*870c2f7aSEnji Cooper /* 56*870c2f7aSEnji Cooper * List of users and groups we must check exists before we can begin, since 57*870c2f7aSEnji Cooper * they are used in the string test rules. We use users and groups that will 58*870c2f7aSEnji Cooper * always exist in a default install used for regression testing. 59*870c2f7aSEnji Cooper */ 60*870c2f7aSEnji Cooper static const char *test_users[] = { 61*870c2f7aSEnji Cooper "root", 62*870c2f7aSEnji Cooper "daemon", 63*870c2f7aSEnji Cooper "operator", 64*870c2f7aSEnji Cooper "bin", 65*870c2f7aSEnji Cooper }; 66*870c2f7aSEnji Cooper 67*870c2f7aSEnji Cooper static const char *test_groups[] = { 68*870c2f7aSEnji Cooper "wheel", 69*870c2f7aSEnji Cooper "daemon", 70*870c2f7aSEnji Cooper "operator", 71*870c2f7aSEnji Cooper "bin", 72*870c2f7aSEnji Cooper }; 73*870c2f7aSEnji Cooper 74*870c2f7aSEnji Cooper int test_num; 75*870c2f7aSEnji Cooper 76*870c2f7aSEnji Cooper /* 77*870c2f7aSEnji Cooper * List of test strings that must go in (and come out) of libugidfw intact. 78*870c2f7aSEnji Cooper */ 79*870c2f7aSEnji Cooper static const char *test_strings[] = { 80*870c2f7aSEnji Cooper /* Variations on subject and object uids. */ 81*870c2f7aSEnji Cooper "subject uid root object uid root mode n", 82*870c2f7aSEnji Cooper "subject uid root object uid daemon mode n", 83*870c2f7aSEnji Cooper "subject uid daemon object uid root mode n", 84*870c2f7aSEnji Cooper "subject uid daemon object uid daemon mode n", 85*870c2f7aSEnji Cooper /* Variations on mode. */ 86*870c2f7aSEnji Cooper "subject uid root object uid root mode a", 87*870c2f7aSEnji Cooper "subject uid root object uid root mode r", 88*870c2f7aSEnji Cooper "subject uid root object uid root mode s", 89*870c2f7aSEnji Cooper "subject uid root object uid root mode w", 90*870c2f7aSEnji Cooper "subject uid root object uid root mode x", 91*870c2f7aSEnji Cooper "subject uid root object uid root mode arswx", 92*870c2f7aSEnji Cooper /* Variations on subject and object gids. */ 93*870c2f7aSEnji Cooper "subject gid wheel object gid wheel mode n", 94*870c2f7aSEnji Cooper "subject gid wheel object gid daemon mode n", 95*870c2f7aSEnji Cooper "subject gid daemon object gid wheel mode n", 96*870c2f7aSEnji Cooper "subject gid daemon object gid daemon mode n", 97*870c2f7aSEnji Cooper /* Subject uids and subject gids. */ 98*870c2f7aSEnji Cooper "subject uid bin gid daemon object uid operator gid wheel mode n", 99*870c2f7aSEnji Cooper /* Not */ 100*870c2f7aSEnji Cooper "subject not uid operator object uid bin mode n", 101*870c2f7aSEnji Cooper "subject uid bin object not uid operator mode n", 102*870c2f7aSEnji Cooper "subject not uid daemon object not uid operator mode n", 103*870c2f7aSEnji Cooper /* Ranges */ 104*870c2f7aSEnji Cooper "subject uid root:operator object gid wheel:bin mode n", 105*870c2f7aSEnji Cooper /* Jail ID */ 106*870c2f7aSEnji Cooper "subject jailid 1 object uid root mode n", 107*870c2f7aSEnji Cooper /* Filesys */ 108*870c2f7aSEnji Cooper "subject uid root object filesys / mode n", 109*870c2f7aSEnji Cooper "subject uid root object filesys /dev mode n", 110*870c2f7aSEnji Cooper /* S/UGID */ 111*870c2f7aSEnji Cooper "subject not uid root object sgid mode n", 112*870c2f7aSEnji Cooper "subject not uid root object sgid mode n", 113*870c2f7aSEnji Cooper /* Matching uid/gid */ 114*870c2f7aSEnji Cooper "subject not uid root:operator object not uid_of_subject mode n", 115*870c2f7aSEnji Cooper "subject not gid wheel:bin object not gid_of_subject mode n", 116*870c2f7aSEnji Cooper /* Object types */ 117*870c2f7aSEnji Cooper "subject uid root object type a mode a", 118*870c2f7aSEnji Cooper "subject uid root object type r mode a", 119*870c2f7aSEnji Cooper "subject uid root object type d mode a", 120*870c2f7aSEnji Cooper "subject uid root object type b mode a", 121*870c2f7aSEnji Cooper "subject uid root object type c mode a", 122*870c2f7aSEnji Cooper "subject uid root object type l mode a", 123*870c2f7aSEnji Cooper "subject uid root object type s mode a", 124*870c2f7aSEnji Cooper "subject uid root object type rbc mode a", 125*870c2f7aSEnji Cooper "subject uid root object type dls mode a", 126*870c2f7aSEnji Cooper /* Empty rules always match */ 127*870c2f7aSEnji Cooper "subject object mode a", 128*870c2f7aSEnji Cooper /* Partial negations */ 129*870c2f7aSEnji Cooper "subject ! uid root object mode n", 130*870c2f7aSEnji Cooper "subject ! gid wheel object mode n", 131*870c2f7aSEnji Cooper "subject ! jailid 2 object mode n", 132*870c2f7aSEnji Cooper "subject object ! uid root mode n", 133*870c2f7aSEnji Cooper "subject object ! gid wheel mode n", 134*870c2f7aSEnji Cooper "subject object ! filesys / mode n", 135*870c2f7aSEnji Cooper "subject object ! suid mode n", 136*870c2f7aSEnji Cooper "subject object ! sgid mode n", 137*870c2f7aSEnji Cooper "subject object ! uid_of_subject mode n", 138*870c2f7aSEnji Cooper "subject object ! gid_of_subject mode n", 139*870c2f7aSEnji Cooper "subject object ! type d mode n", 140*870c2f7aSEnji Cooper /* All out nonsense */ 141*870c2f7aSEnji Cooper "subject uid root ! gid wheel:bin ! jailid 1 " 142*870c2f7aSEnji Cooper "object ! uid root:daemon gid daemon filesys / suid sgid uid_of_subject gid_of_subject ! type r " 143*870c2f7aSEnji Cooper "mode rsx", 144*870c2f7aSEnji Cooper }; 145*870c2f7aSEnji Cooper 146*870c2f7aSEnji Cooper static void 147*870c2f7aSEnji Cooper test_libugidfw_strings(void) 148*870c2f7aSEnji Cooper { 149*870c2f7aSEnji Cooper struct mac_bsdextended_rule rule; 150*870c2f7aSEnji Cooper char errorstr[256]; 151*870c2f7aSEnji Cooper char rulestr[256]; 152*870c2f7aSEnji Cooper int error, i; 153*870c2f7aSEnji Cooper 154*870c2f7aSEnji Cooper for (i = 0; i < nitems(test_users); i++, test_num++) { 155*870c2f7aSEnji Cooper if (getpwnam(test_users[i]) == NULL) 156*870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getpwnam(%s) " 157*870c2f7aSEnji Cooper "failed: %s\n", test_num, test_users[i], strerror(errno)); 158*870c2f7aSEnji Cooper else 159*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 160*870c2f7aSEnji Cooper } 161*870c2f7aSEnji Cooper 162*870c2f7aSEnji Cooper for (i = 0; i < nitems(test_groups); i++, test_num++) { 163*870c2f7aSEnji Cooper if (getgrnam(test_groups[i]) == NULL) 164*870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getgrnam(%s) " 165*870c2f7aSEnji Cooper "failed: %s\n", test_num, test_groups[i], strerror(errno)); 166*870c2f7aSEnji Cooper else 167*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 168*870c2f7aSEnji Cooper } 169*870c2f7aSEnji Cooper 170*870c2f7aSEnji Cooper for (i = 0; i < nitems(test_strings); i++) { 171*870c2f7aSEnji Cooper error = bsde_parse_rule_string(test_strings[i], &rule, 172*870c2f7aSEnji Cooper sizeof(errorstr), errorstr); 173*870c2f7aSEnji Cooper if (error == -1) 174*870c2f7aSEnji Cooper printf("not ok %d # bsde_parse_rule_string: '%s' (%d) " 175*870c2f7aSEnji Cooper "failed: %s\n", test_num, test_strings[i], i, errorstr); 176*870c2f7aSEnji Cooper else 177*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 178*870c2f7aSEnji Cooper test_num++; 179*870c2f7aSEnji Cooper 180*870c2f7aSEnji Cooper error = bsde_rule_to_string(&rule, rulestr, sizeof(rulestr)); 181*870c2f7aSEnji Cooper if (error < 0) 182*870c2f7aSEnji Cooper printf("not ok %d # bsde_rule_to_string: rule for '%s' " 183*870c2f7aSEnji Cooper "returned %d\n", test_num, test_strings[i], error); 184*870c2f7aSEnji Cooper else 185*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 186*870c2f7aSEnji Cooper test_num++; 187*870c2f7aSEnji Cooper 188*870c2f7aSEnji Cooper if (strcmp(test_strings[i], rulestr) != 0) 189*870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw: '%s' in, '%s' " 190*870c2f7aSEnji Cooper "out\n", test_num, test_strings[i], rulestr); 191*870c2f7aSEnji Cooper else 192*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 193*870c2f7aSEnji Cooper test_num++; 194*870c2f7aSEnji Cooper } 195*870c2f7aSEnji Cooper } 196*870c2f7aSEnji Cooper 197*870c2f7aSEnji Cooper int 198*870c2f7aSEnji Cooper main(void) 199*870c2f7aSEnji Cooper { 200*870c2f7aSEnji Cooper char errorstr[256]; 201*870c2f7aSEnji Cooper int count, slots; 202*870c2f7aSEnji Cooper 203*870c2f7aSEnji Cooper test_num = 1; 204*870c2f7aSEnji Cooper 205*870c2f7aSEnji Cooper /* Print an error if a non-root user attemps to run the tests. */ 206*870c2f7aSEnji Cooper if (getuid() != 0) { 207*870c2f7aSEnji Cooper printf("1..0 # SKIP you must be root\n"); 208*870c2f7aSEnji Cooper return (0); 209*870c2f7aSEnji Cooper } 210*870c2f7aSEnji Cooper 211*870c2f7aSEnji Cooper printf("1..%lu\n", nitems(test_users) + nitems(test_groups) + 212*870c2f7aSEnji Cooper 3 * nitems(test_strings) + 2); 213*870c2f7aSEnji Cooper 214*870c2f7aSEnji Cooper /* 215*870c2f7aSEnji Cooper * We can test some parts of the library without the MAC Framework 216*870c2f7aSEnji Cooper * and policy loaded, so run those tests before calling 217*870c2f7aSEnji Cooper * mac_is_present(). 218*870c2f7aSEnji Cooper */ 219*870c2f7aSEnji Cooper test_libugidfw_strings(); 220*870c2f7aSEnji Cooper 221*870c2f7aSEnji Cooper switch (mac_is_present("bsdextended")) { 222*870c2f7aSEnji Cooper case -1: 223*870c2f7aSEnji Cooper printf("1..0 # SKIP mac_is_present failed: %s\n", 224*870c2f7aSEnji Cooper strerror(errno)); 225*870c2f7aSEnji Cooper return (0); 226*870c2f7aSEnji Cooper case 1: 227*870c2f7aSEnji Cooper break; 228*870c2f7aSEnji Cooper case 0: 229*870c2f7aSEnji Cooper default: 230*870c2f7aSEnji Cooper printf("1..0 # SKIP mac_bsdextended not loaded\n"); 231*870c2f7aSEnji Cooper return (0); 232*870c2f7aSEnji Cooper } 233*870c2f7aSEnji Cooper 234*870c2f7aSEnji Cooper /* 235*870c2f7aSEnji Cooper * Some simple up-front checks to see if we're able to query the 236*870c2f7aSEnji Cooper * policy for basic state. We want the rule count to be 0 before 237*870c2f7aSEnji Cooper * starting, but "slots" is a property of prior runs and so we ignore 238*870c2f7aSEnji Cooper * the return value. 239*870c2f7aSEnji Cooper */ 240*870c2f7aSEnji Cooper count = bsde_get_rule_count(sizeof(errorstr), errorstr); 241*870c2f7aSEnji Cooper if (count == -1) 242*870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_count: %s\n", test_num, 243*870c2f7aSEnji Cooper errorstr); 244*870c2f7aSEnji Cooper else 245*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 246*870c2f7aSEnji Cooper 247*870c2f7aSEnji Cooper test_num++; 248*870c2f7aSEnji Cooper 249*870c2f7aSEnji Cooper slots = bsde_get_rule_slots(sizeof(errorstr), errorstr); 250*870c2f7aSEnji Cooper if (slots == -1) 251*870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_slots: %s\n", test_num, 252*870c2f7aSEnji Cooper errorstr); 253*870c2f7aSEnji Cooper else 254*870c2f7aSEnji Cooper printf("ok %d\n", test_num); 255*870c2f7aSEnji Cooper 256*870c2f7aSEnji Cooper return (0); 257*870c2f7aSEnji Cooper } 258