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
27870c2f7aSEnji Cooper #include <sys/param.h>
28870c2f7aSEnji Cooper #include <sys/mac.h>
29870c2f7aSEnji Cooper #include <sys/mount.h>
30870c2f7aSEnji Cooper
31870c2f7aSEnji Cooper #include <security/mac_bsdextended/mac_bsdextended.h>
32870c2f7aSEnji Cooper
33870c2f7aSEnji Cooper #include <err.h>
34870c2f7aSEnji Cooper #include <errno.h>
35870c2f7aSEnji Cooper #include <grp.h>
36870c2f7aSEnji Cooper #include <pwd.h>
37870c2f7aSEnji Cooper #include <stdio.h>
38870c2f7aSEnji Cooper #include <stdlib.h>
39870c2f7aSEnji Cooper #include <string.h>
40870c2f7aSEnji Cooper #include <ugidfw.h>
41870c2f7aSEnji Cooper #include <unistd.h>
42870c2f7aSEnji Cooper
43870c2f7aSEnji Cooper /*
44870c2f7aSEnji Cooper * Starting point for a regression test for mac_bsdextended(4) and the
45870c2f7aSEnji Cooper * supporting libugidfw(3).
46870c2f7aSEnji Cooper */
47870c2f7aSEnji Cooper
48870c2f7aSEnji Cooper /*
49870c2f7aSEnji Cooper * This section of the regression test passes some test cases through the
50870c2f7aSEnji Cooper * rule<->string routines to confirm they work approximately as desired.
51870c2f7aSEnji Cooper */
52870c2f7aSEnji Cooper
53870c2f7aSEnji Cooper /*
54870c2f7aSEnji Cooper * List of users and groups we must check exists before we can begin, since
55870c2f7aSEnji Cooper * they are used in the string test rules. We use users and groups that will
56870c2f7aSEnji Cooper * always exist in a default install used for regression testing.
57870c2f7aSEnji Cooper */
58870c2f7aSEnji Cooper static const char *test_users[] = {
59870c2f7aSEnji Cooper "root",
60870c2f7aSEnji Cooper "daemon",
61870c2f7aSEnji Cooper "operator",
62870c2f7aSEnji Cooper "bin",
63870c2f7aSEnji Cooper };
64870c2f7aSEnji Cooper
65870c2f7aSEnji Cooper static const char *test_groups[] = {
66870c2f7aSEnji Cooper "wheel",
67870c2f7aSEnji Cooper "daemon",
68870c2f7aSEnji Cooper "operator",
69870c2f7aSEnji Cooper "bin",
70870c2f7aSEnji Cooper };
71870c2f7aSEnji Cooper
72f614ceafSEnji Cooper static int test_num;
73870c2f7aSEnji Cooper
74870c2f7aSEnji Cooper /*
75870c2f7aSEnji Cooper * List of test strings that must go in (and come out) of libugidfw intact.
76870c2f7aSEnji Cooper */
77870c2f7aSEnji Cooper static const char *test_strings[] = {
78870c2f7aSEnji Cooper /* Variations on subject and object uids. */
79870c2f7aSEnji Cooper "subject uid root object uid root mode n",
80870c2f7aSEnji Cooper "subject uid root object uid daemon mode n",
81870c2f7aSEnji Cooper "subject uid daemon object uid root mode n",
82870c2f7aSEnji Cooper "subject uid daemon object uid daemon mode n",
83870c2f7aSEnji Cooper /* Variations on mode. */
84870c2f7aSEnji Cooper "subject uid root object uid root mode a",
85870c2f7aSEnji Cooper "subject uid root object uid root mode r",
86870c2f7aSEnji Cooper "subject uid root object uid root mode s",
87870c2f7aSEnji Cooper "subject uid root object uid root mode w",
88870c2f7aSEnji Cooper "subject uid root object uid root mode x",
89870c2f7aSEnji Cooper "subject uid root object uid root mode arswx",
90870c2f7aSEnji Cooper /* Variations on subject and object gids. */
91870c2f7aSEnji Cooper "subject gid wheel object gid wheel mode n",
92870c2f7aSEnji Cooper "subject gid wheel object gid daemon mode n",
93870c2f7aSEnji Cooper "subject gid daemon object gid wheel mode n",
94870c2f7aSEnji Cooper "subject gid daemon object gid daemon mode n",
95870c2f7aSEnji Cooper /* Subject uids and subject gids. */
96870c2f7aSEnji Cooper "subject uid bin gid daemon object uid operator gid wheel mode n",
97870c2f7aSEnji Cooper /* Not */
98870c2f7aSEnji Cooper "subject not uid operator object uid bin mode n",
99870c2f7aSEnji Cooper "subject uid bin object not uid operator mode n",
100870c2f7aSEnji Cooper "subject not uid daemon object not uid operator mode n",
101870c2f7aSEnji Cooper /* Ranges */
102870c2f7aSEnji Cooper "subject uid root:operator object gid wheel:bin mode n",
103870c2f7aSEnji Cooper /* Jail ID */
104870c2f7aSEnji Cooper "subject jailid 1 object uid root mode n",
105870c2f7aSEnji Cooper /* Filesys */
106870c2f7aSEnji Cooper "subject uid root object filesys / mode n",
107870c2f7aSEnji Cooper "subject uid root object filesys /dev mode n",
108870c2f7aSEnji Cooper /* S/UGID */
109870c2f7aSEnji Cooper "subject not uid root object sgid mode n",
110870c2f7aSEnji Cooper "subject not uid root object sgid mode n",
111870c2f7aSEnji Cooper /* Matching uid/gid */
112870c2f7aSEnji Cooper "subject not uid root:operator object not uid_of_subject mode n",
113870c2f7aSEnji Cooper "subject not gid wheel:bin object not gid_of_subject mode n",
114870c2f7aSEnji Cooper /* Object types */
115870c2f7aSEnji Cooper "subject uid root object type a mode a",
116870c2f7aSEnji Cooper "subject uid root object type r mode a",
117870c2f7aSEnji Cooper "subject uid root object type d mode a",
118870c2f7aSEnji Cooper "subject uid root object type b mode a",
119870c2f7aSEnji Cooper "subject uid root object type c mode a",
120870c2f7aSEnji Cooper "subject uid root object type l mode a",
121870c2f7aSEnji Cooper "subject uid root object type s mode a",
122870c2f7aSEnji Cooper "subject uid root object type rbc mode a",
123870c2f7aSEnji Cooper "subject uid root object type dls mode a",
124870c2f7aSEnji Cooper /* Empty rules always match */
125870c2f7aSEnji Cooper "subject object mode a",
126870c2f7aSEnji Cooper /* Partial negations */
127870c2f7aSEnji Cooper "subject ! uid root object mode n",
128870c2f7aSEnji Cooper "subject ! gid wheel object mode n",
129870c2f7aSEnji Cooper "subject ! jailid 2 object mode n",
130870c2f7aSEnji Cooper "subject object ! uid root mode n",
131870c2f7aSEnji Cooper "subject object ! gid wheel mode n",
132870c2f7aSEnji Cooper "subject object ! filesys / mode n",
133870c2f7aSEnji Cooper "subject object ! suid mode n",
134870c2f7aSEnji Cooper "subject object ! sgid mode n",
135870c2f7aSEnji Cooper "subject object ! uid_of_subject mode n",
136870c2f7aSEnji Cooper "subject object ! gid_of_subject mode n",
137870c2f7aSEnji Cooper "subject object ! type d mode n",
138870c2f7aSEnji Cooper /* All out nonsense */
139870c2f7aSEnji Cooper "subject uid root ! gid wheel:bin ! jailid 1 "
140870c2f7aSEnji Cooper "object ! uid root:daemon gid daemon filesys / suid sgid uid_of_subject gid_of_subject ! type r "
141870c2f7aSEnji Cooper "mode rsx",
142870c2f7aSEnji Cooper };
143870c2f7aSEnji Cooper
144870c2f7aSEnji Cooper static void
test_libugidfw_strings(void)145870c2f7aSEnji Cooper test_libugidfw_strings(void)
146870c2f7aSEnji Cooper {
147870c2f7aSEnji Cooper struct mac_bsdextended_rule rule;
148870c2f7aSEnji Cooper char errorstr[256];
149870c2f7aSEnji Cooper char rulestr[256];
150f614ceafSEnji Cooper size_t i;
151f614ceafSEnji Cooper int error;
152870c2f7aSEnji Cooper
153870c2f7aSEnji Cooper for (i = 0; i < nitems(test_users); i++, test_num++) {
154870c2f7aSEnji Cooper if (getpwnam(test_users[i]) == NULL)
155870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getpwnam(%s) "
156870c2f7aSEnji Cooper "failed: %s\n", test_num, test_users[i], strerror(errno));
157870c2f7aSEnji Cooper else
158870c2f7aSEnji Cooper printf("ok %d\n", test_num);
159870c2f7aSEnji Cooper }
160870c2f7aSEnji Cooper
161870c2f7aSEnji Cooper for (i = 0; i < nitems(test_groups); i++, test_num++) {
162870c2f7aSEnji Cooper if (getgrnam(test_groups[i]) == NULL)
163870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw_strings: getgrnam(%s) "
164870c2f7aSEnji Cooper "failed: %s\n", test_num, test_groups[i], strerror(errno));
165870c2f7aSEnji Cooper else
166870c2f7aSEnji Cooper printf("ok %d\n", test_num);
167870c2f7aSEnji Cooper }
168870c2f7aSEnji Cooper
169870c2f7aSEnji Cooper for (i = 0; i < nitems(test_strings); i++) {
170870c2f7aSEnji Cooper error = bsde_parse_rule_string(test_strings[i], &rule,
171870c2f7aSEnji Cooper sizeof(errorstr), errorstr);
172870c2f7aSEnji Cooper if (error == -1)
173f614ceafSEnji Cooper printf("not ok %d # bsde_parse_rule_string: '%s' (%zu) "
174870c2f7aSEnji Cooper "failed: %s\n", test_num, test_strings[i], i, errorstr);
175870c2f7aSEnji Cooper else
176870c2f7aSEnji Cooper printf("ok %d\n", test_num);
177870c2f7aSEnji Cooper test_num++;
178870c2f7aSEnji Cooper
179870c2f7aSEnji Cooper error = bsde_rule_to_string(&rule, rulestr, sizeof(rulestr));
180870c2f7aSEnji Cooper if (error < 0)
181870c2f7aSEnji Cooper printf("not ok %d # bsde_rule_to_string: rule for '%s' "
182870c2f7aSEnji Cooper "returned %d\n", test_num, test_strings[i], error);
183870c2f7aSEnji Cooper else
184870c2f7aSEnji Cooper printf("ok %d\n", test_num);
185870c2f7aSEnji Cooper test_num++;
186870c2f7aSEnji Cooper
187870c2f7aSEnji Cooper if (strcmp(test_strings[i], rulestr) != 0)
188870c2f7aSEnji Cooper printf("not ok %d # test_libugidfw: '%s' in, '%s' "
189870c2f7aSEnji Cooper "out\n", test_num, test_strings[i], rulestr);
190870c2f7aSEnji Cooper else
191870c2f7aSEnji Cooper printf("ok %d\n", test_num);
192870c2f7aSEnji Cooper test_num++;
193870c2f7aSEnji Cooper }
194870c2f7aSEnji Cooper }
195870c2f7aSEnji Cooper
196870c2f7aSEnji Cooper int
main(void)197870c2f7aSEnji Cooper main(void)
198870c2f7aSEnji Cooper {
199870c2f7aSEnji Cooper char errorstr[256];
200870c2f7aSEnji Cooper int count, slots;
201870c2f7aSEnji Cooper
202870c2f7aSEnji Cooper test_num = 1;
203870c2f7aSEnji Cooper
204870c2f7aSEnji Cooper /* Print an error if a non-root user attemps to run the tests. */
205870c2f7aSEnji Cooper if (getuid() != 0) {
206870c2f7aSEnji Cooper printf("1..0 # SKIP you must be root\n");
207870c2f7aSEnji Cooper return (0);
208870c2f7aSEnji Cooper }
209870c2f7aSEnji Cooper
210870c2f7aSEnji Cooper switch (mac_is_present("bsdextended")) {
211870c2f7aSEnji Cooper case -1:
212870c2f7aSEnji Cooper printf("1..0 # SKIP mac_is_present failed: %s\n",
213870c2f7aSEnji Cooper strerror(errno));
214870c2f7aSEnji Cooper return (0);
215870c2f7aSEnji Cooper case 1:
216870c2f7aSEnji Cooper break;
217870c2f7aSEnji Cooper case 0:
218870c2f7aSEnji Cooper default:
219870c2f7aSEnji Cooper printf("1..0 # SKIP mac_bsdextended not loaded\n");
220870c2f7aSEnji Cooper return (0);
221870c2f7aSEnji Cooper }
222870c2f7aSEnji Cooper
223*00ea8a5fSEnji Cooper printf("1..%zu\n", nitems(test_users) + nitems(test_groups) +
224ad25988fSEnji Cooper 3 * nitems(test_strings) + 2);
225ad25988fSEnji Cooper
226ad25988fSEnji Cooper test_libugidfw_strings();
227ad25988fSEnji Cooper
228870c2f7aSEnji Cooper /*
229870c2f7aSEnji Cooper * Some simple up-front checks to see if we're able to query the
230870c2f7aSEnji Cooper * policy for basic state. We want the rule count to be 0 before
231870c2f7aSEnji Cooper * starting, but "slots" is a property of prior runs and so we ignore
232870c2f7aSEnji Cooper * the return value.
233870c2f7aSEnji Cooper */
234870c2f7aSEnji Cooper count = bsde_get_rule_count(sizeof(errorstr), errorstr);
235870c2f7aSEnji Cooper if (count == -1)
236870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_count: %s\n", test_num,
237870c2f7aSEnji Cooper errorstr);
238870c2f7aSEnji Cooper else
239870c2f7aSEnji Cooper printf("ok %d\n", test_num);
240870c2f7aSEnji Cooper
241870c2f7aSEnji Cooper test_num++;
242870c2f7aSEnji Cooper
243870c2f7aSEnji Cooper slots = bsde_get_rule_slots(sizeof(errorstr), errorstr);
244870c2f7aSEnji Cooper if (slots == -1)
245870c2f7aSEnji Cooper printf("not ok %d # bsde_get_rule_slots: %s\n", test_num,
246870c2f7aSEnji Cooper errorstr);
247870c2f7aSEnji Cooper else
248870c2f7aSEnji Cooper printf("ok %d\n", test_num);
249870c2f7aSEnji Cooper
250870c2f7aSEnji Cooper return (0);
251870c2f7aSEnji Cooper }
252