1/*-
2 * Copyright (c) 2006 nCircle Network Security, Inc.
3 * Copyright (c) 2007 Robert N. M. Watson
4 * All rights reserved.
5 *
6 * This software was developed by Robert N. M. Watson for the TrustedBSD
7 * Project under contract to nCircle Network Security, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33/*
34 * This is a joint test of both the read and write privileges with respect to
35 * discretionary file system access control (permissions).  Only permissions,
36 * not ACL semantics, and only privilege-related checks are performed.
37 */
38
39#include <sys/types.h>
40#include <sys/stat.h>
41
42#include <err.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
49#include "main.h"
50
51static char fpath_none[1024];
52static char fpath_read[1024];
53static char fpath_write[1024];
54static char fpath_readwrite[1024];
55
56static int fpath_none_initialized;
57static int fpath_read_initialized;
58static int fpath_write_initialized;
59static int fpath_readwrite_initialized;
60
61static void
62try_io(const char *label, const char *fpathp, int asroot, int injail,
63    int flags, int expected_error, int expected_errno)
64{
65	int fd;
66
67	fd = open(fpathp, flags);
68	if (fd < 0) {
69		if (expected_error != -1)
70			warnx("%s(%s, %s): expected (%d, %d) got (-1, %d)",
71			    label, asroot ? "root" : "!root", injail ? "jail"
72			    : "!jail", expected_error, expected_errno, errno);
73	} else {
74		if (expected_error == -1)
75			warnx("%s(%s, %s): expected (%d, %d) got 0", label,
76			    asroot ? "root" : "!root", injail ? "jail" :
77			    "!jail", expected_error, expected_errno);
78		(void)close(fd);
79	}
80}
81
82int
83priv_vfs_readwrite_fowner_setup(int asroot, int injail, struct test *test)
84{
85
86	setup_file("priv_vfs_readwrite_fowner_setup: fpath_none", fpath_none,
87	    asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0000);
88	fpath_none_initialized = 1;
89	setup_file("priv_vfs_readwrite_fowner_setup: fpath_read", fpath_read,
90	    asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0400);
91	fpath_read_initialized = 1;
92	setup_file("priv_vfs_readwrite_fowner_setup: fpath_write",
93	    fpath_write, asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0200);
94	fpath_write_initialized = 1;
95	setup_file("priv_vfs_readwrite_fowner_setup: fpath_readwrite",
96	    fpath_readwrite, asroot ? UID_ROOT : UID_OWNER, GID_OTHER, 0600);
97	fpath_readwrite_initialized = 1;
98	return (0);
99}
100
101int
102priv_vfs_readwrite_fgroup_setup(int asroot, int injail, struct test *test)
103{
104
105	setup_file("priv_vfs_readwrite_fgroup_setup: fpath_none", fpath_none,
106	    UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0000);
107	fpath_none_initialized = 1;
108	setup_file("priv_vfs_readwrite_fgroup_setup: fpath_read", fpath_read,
109	    UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0040);
110	fpath_read_initialized = 1;
111	setup_file("priv_vfs_readwrite_fgroup_setup: fpath_write",
112	    fpath_write, UID_OTHER, asroot ? GID_WHEEL : GID_OWNER, 0020);
113	fpath_write_initialized = 1;
114	setup_file("priv_vfs_readwrite_fgroup_setup: fpath_readwrite",
115	    fpath_readwrite, UID_OTHER, asroot ? GID_WHEEL : GID_OWNER,
116	    0060);
117	fpath_readwrite_initialized = 1;
118	return (0);
119}
120
121int
122priv_vfs_readwrite_fother_setup(int asroot, int injail, struct test *test)
123{
124
125	setup_file("priv_vfs_readwrite_fother_setup: fpath_none", fpath_none,
126	    UID_OTHER, GID_OTHER, 0000);
127	fpath_none_initialized = 1;
128	setup_file("priv_vfs_readwrite_fother_setup: fpath_read", fpath_read,
129	    UID_OTHER, GID_OTHER, 0004);
130	fpath_read_initialized = 1;
131	setup_file("priv_vfs_readwrite_fother_setup: fpath_write",
132	    fpath_write, UID_OTHER, GID_OTHER, 0002);
133	fpath_write_initialized = 1;
134	setup_file("priv_vfs_readwrite_fother_setup: fpath_readwrite",
135	    fpath_readwrite, UID_OTHER, GID_OTHER, 0006);
136	fpath_readwrite_initialized = 1;
137	return (0);
138}
139
140void
141priv_vfs_readwrite_fowner(int asroot, int injail, struct test *test)
142{
143
144	try_io("priv_vfs_readwrite_fowner(none, O_RDONLY)", fpath_none,
145	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
146	try_io("priv_vfs_readwrite_fowner(none, O_WRONLY)", fpath_none,
147	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
148	try_io("priv_vfs_readwrite_fowner(none, O_RDWR)", fpath_none,
149	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
150
151	try_io("priv_vfs_readwrite_fowner(read, O_RDONLY)", fpath_read,
152	    asroot, injail, O_RDONLY, 0, 0);
153	try_io("priv_vfs_readwrite_fowner(read, O_WRONLY)", fpath_read,
154	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
155	try_io("priv_vfs_readwrite_fowner(read, O_RDWR)", fpath_read,
156	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
157
158	try_io("priv_vfs_readwrite_fowner(write, O_RDONLY)", fpath_write,
159	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
160	try_io("priv_vfs_readwrite_fowner(write, O_WRONLY)", fpath_write,
161	    asroot, injail, O_WRONLY, 0, 0);
162	try_io("priv_vfs_readwrite_fowner(write, O_RDWR)", fpath_write,
163	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
164
165	try_io("priv_vfs_readwrite_fowner(write, O_RDONLY)", fpath_readwrite,
166	    asroot, injail, O_RDONLY, 0, 0);
167	try_io("priv_vfs_readwrite_fowner(write, O_WRONLY)", fpath_readwrite,
168	    asroot, injail, O_WRONLY, 0, 0);
169	try_io("priv_vfs_readwrite_fowner(write, O_RDWR)", fpath_readwrite,
170	    asroot, injail, O_RDWR, 0, 0);
171}
172
173void
174priv_vfs_readwrite_fgroup(int asroot, int injail, struct test *test)
175{
176
177	try_io("priv_vfs_readwrite_fgroup(none, O_RDONLY)", fpath_none,
178	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
179	try_io("priv_vfs_readwrite_fgroup(none, O_WRONLY)", fpath_none,
180	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
181	try_io("priv_vfs_readwrite_fgroup(none, O_RDWR)", fpath_none,
182	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
183
184	try_io("priv_vfs_readwrite_fgroup(read, O_RDONLY)", fpath_read,
185	    asroot, injail, O_RDONLY, 0, 0);
186	try_io("priv_vfs_readwrite_fgroup(read, O_WRONLY)", fpath_read,
187	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
188	try_io("priv_vfs_readwrite_fgroup(read, O_RDWR)", fpath_read,
189	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
190
191	try_io("priv_vfs_readwrite_fgroup(write, O_RDONLY)", fpath_write,
192	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
193	try_io("priv_vfs_readwrite_fgroup(write, O_WRONLY)", fpath_write,
194	    asroot, injail, O_WRONLY, 0, 0);
195	try_io("priv_vfs_readwrite_fgroup(write, O_RDWR)", fpath_write,
196	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
197
198	try_io("priv_vfs_readwrite_fgroup(write, O_RDONLY)", fpath_readwrite,
199	    asroot, injail, O_RDONLY, 0, 0);
200	try_io("priv_vfs_readwrite_fgroup(write, O_WRONLY)", fpath_readwrite,
201	    asroot, injail, O_WRONLY, 0, 0);
202	try_io("priv_vfs_readwrite_fgroup(write, O_RDWR)", fpath_readwrite,
203	    asroot, injail, O_RDWR, 0, 0);
204}
205
206void
207priv_vfs_readwrite_fother(int asroot, int injail, struct test *test)
208{
209
210	try_io("priv_vfs_readwrite_fother(none, O_RDONLY)", fpath_none,
211	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
212	try_io("priv_vfs_readwrite_fother(none, O_WRONLY)", fpath_none,
213	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
214	try_io("priv_vfs_readwrite_fother(none, O_RDWR)", fpath_none,
215	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
216
217	try_io("priv_vfs_readwrite_fother(read, O_RDONLY)", fpath_read,
218	    asroot, injail, O_RDONLY, 0, 0);
219	try_io("priv_vfs_readwrite_fother(read, O_WRONLY)", fpath_read,
220	    asroot, injail, O_WRONLY, asroot ? 0 : -1, EACCES);
221	try_io("priv_vfs_readwrite_fother(read, O_RDWR)", fpath_read,
222	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
223
224	try_io("priv_vfs_readwrite_fother(write, O_RDONLY)", fpath_write,
225	    asroot, injail, O_RDONLY, asroot ? 0 : -1, EACCES);
226	try_io("priv_vfs_readwrite_fother(write, O_WRONLY)", fpath_write,
227	    asroot, injail, O_WRONLY, 0, 0);
228	try_io("priv_vfs_readwrite_fother(write, O_RDWR)", fpath_write,
229	    asroot, injail, O_RDWR, asroot ? 0 : -1, EACCES);
230
231	try_io("priv_vfs_readwrite_fother(write, O_RDONLY)", fpath_readwrite,
232	    asroot, injail, O_RDONLY, 0, 0);
233	try_io("priv_vfs_readwrite_fother(write, O_WRONLY)", fpath_readwrite,
234	    asroot, injail, O_WRONLY, 0, 0);
235	try_io("priv_vfs_readwrite_fother(write, O_RDWR)", fpath_readwrite,
236	    asroot, injail, O_RDWR, 0, 0);
237}
238
239void
240priv_vfs_readwrite_cleanup(int asroot, int injail, struct test *test)
241{
242
243	if (fpath_none_initialized) {
244		(void)unlink(fpath_none);
245		fpath_none_initialized = 0;
246	}
247	if (fpath_read_initialized) {
248		(void)unlink(fpath_read);
249		fpath_read_initialized = 0;
250	}
251	if (fpath_write_initialized) {
252		(void)unlink(fpath_write);
253		fpath_write_initialized = 0;
254	}
255	if (fpath_readwrite_initialized) {
256		(void)unlink(fpath_readwrite);
257		fpath_readwrite_initialized = 0;
258	}
259}
260