1d903306aSRobert Watson /*-
2d903306aSRobert Watson * Copyright (c) 2006 nCircle Network Security, Inc.
3d903306aSRobert Watson * Copyright (c) 2007 Robert N. M. Watson
4d903306aSRobert Watson * All rights reserved.
5d903306aSRobert Watson *
6d903306aSRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD
7d903306aSRobert Watson * Project under contract to nCircle Network Security, Inc.
8d903306aSRobert Watson *
9d903306aSRobert Watson * Redistribution and use in source and binary forms, with or without
10d903306aSRobert Watson * modification, are permitted provided that the following conditions
11d903306aSRobert Watson * are met:
12d903306aSRobert Watson * 1. Redistributions of source code must retain the above copyright
13d903306aSRobert Watson * notice, this list of conditions and the following disclaimer.
14d903306aSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
15d903306aSRobert Watson * notice, this list of conditions and the following disclaimer in the
16d903306aSRobert Watson * documentation and/or other materials provided with the distribution.
17d903306aSRobert Watson *
18d903306aSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19d903306aSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20d903306aSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21d903306aSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22d903306aSRobert Watson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23d903306aSRobert Watson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24d903306aSRobert Watson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25d903306aSRobert Watson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26d903306aSRobert Watson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27d903306aSRobert Watson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28d903306aSRobert Watson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29d903306aSRobert Watson */
30d903306aSRobert Watson
31d903306aSRobert Watson /*
32d903306aSRobert Watson * Test privileges associated with setting file flags on files; whether or
33d903306aSRobert Watson * not it requires privilege depends on the flag, and some flags cannot be
34d903306aSRobert Watson * set in jail at all.
35d903306aSRobert Watson */
36d903306aSRobert Watson
37d903306aSRobert Watson #include <sys/types.h>
38d903306aSRobert Watson #include <sys/stat.h>
39d903306aSRobert Watson
40d903306aSRobert Watson #include <err.h>
41d903306aSRobert Watson #include <errno.h>
42d903306aSRobert Watson #include <stdlib.h>
43d903306aSRobert Watson #include <string.h>
44d903306aSRobert Watson #include <unistd.h>
45d903306aSRobert Watson
46d903306aSRobert Watson #include "main.h"
47d903306aSRobert Watson
48d903306aSRobert Watson static char fpath[1024];
49d903306aSRobert Watson static int fpath_initialized;
50d903306aSRobert Watson
51d903306aSRobert Watson /*
52d903306aSRobert Watson * For chflags, we consider three dimmensions: process owner, file owner, and
53d903306aSRobert Watson * flag type. The calling framework handles variations in process owner; the
54d903306aSRobert Watson * rest are handled via multiple tests. One cleanup function is used.
55d903306aSRobert Watson */
56d903306aSRobert Watson static u_long
getflags(char * fpathp)57d903306aSRobert Watson getflags(char *fpathp)
58d903306aSRobert Watson {
59d903306aSRobert Watson struct stat sb;
60d903306aSRobert Watson
61d903306aSRobert Watson if (stat(fpathp, &sb) < 0)
62d903306aSRobert Watson err(-1, "stat(%s)", fpathp);
63d903306aSRobert Watson
64d903306aSRobert Watson return (sb.st_flags);
65d903306aSRobert Watson }
66d903306aSRobert Watson
67d903306aSRobert Watson int
priv_vfs_chflags_froot_setup(int asroot,int injail,struct test * test)68d903306aSRobert Watson priv_vfs_chflags_froot_setup(int asroot, int injail, struct test *test)
69d903306aSRobert Watson {
70d903306aSRobert Watson
71d903306aSRobert Watson setup_file("priv_vfs_chflags_froot_setup: fpath", fpath, UID_ROOT,
72d903306aSRobert Watson GID_WHEEL, 0600);
73d903306aSRobert Watson fpath_initialized = 1;
74d903306aSRobert Watson return (0);
75d903306aSRobert Watson }
76d903306aSRobert Watson
77d903306aSRobert Watson int
priv_vfs_chflags_fowner_setup(int asroot,int injail,struct test * test)78d903306aSRobert Watson priv_vfs_chflags_fowner_setup(int asroot, int injail,
79d903306aSRobert Watson struct test *test)
80d903306aSRobert Watson {
81d903306aSRobert Watson
82d903306aSRobert Watson setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OWNER,
83d903306aSRobert Watson GID_OWNER, 0600);
84d903306aSRobert Watson fpath_initialized = 1;
85d903306aSRobert Watson return (0);
86d903306aSRobert Watson }
87d903306aSRobert Watson
88d903306aSRobert Watson int
priv_vfs_chflags_fother_setup(int asroot,int injail,struct test * test)89d903306aSRobert Watson priv_vfs_chflags_fother_setup(int asroot, int injail,
90d903306aSRobert Watson struct test *test)
91d903306aSRobert Watson {
92d903306aSRobert Watson
93d903306aSRobert Watson setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OTHER,
94d903306aSRobert Watson GID_OTHER, 0600);
95d903306aSRobert Watson fpath_initialized = 1;
96d903306aSRobert Watson return (0);
97d903306aSRobert Watson }
98d903306aSRobert Watson
99d903306aSRobert Watson void
priv_vfs_chflags_froot_uflags(int asroot,int injail,struct test * test)100d903306aSRobert Watson priv_vfs_chflags_froot_uflags(int asroot, int injail,
101d903306aSRobert Watson struct test *test)
102d903306aSRobert Watson {
103d903306aSRobert Watson u_long flags;
104d903306aSRobert Watson int error;
105d903306aSRobert Watson
106d903306aSRobert Watson flags = getflags(fpath);
107d903306aSRobert Watson flags |= UF_NODUMP;
108d903306aSRobert Watson error = chflags(fpath, flags);
109d903306aSRobert Watson if (asroot && injail)
110d903306aSRobert Watson expect("priv_vfs_chflags_froot_uflags(asroot, injail)",
111d903306aSRobert Watson error, 0, 0);
112d903306aSRobert Watson if (asroot && !injail)
113d903306aSRobert Watson expect("priv_vfs_chflags_froot_uflags(asroot, !injail)",
114d903306aSRobert Watson error, 0, 0);
115d903306aSRobert Watson if (!asroot && injail)
116d903306aSRobert Watson expect("priv_vfs_chflags_froot_uflags(!asroot, injail)",
117d903306aSRobert Watson error, -1, EPERM);
118d903306aSRobert Watson if (!asroot && !injail)
119d903306aSRobert Watson expect("priv_vfs_chflags_froot_uflags(!asroot, !injail)",
120d903306aSRobert Watson error, -1, EPERM);
121d903306aSRobert Watson }
122d903306aSRobert Watson
123d903306aSRobert Watson void
priv_vfs_chflags_fowner_uflags(int asroot,int injail,struct test * test)124d903306aSRobert Watson priv_vfs_chflags_fowner_uflags(int asroot, int injail,
125d903306aSRobert Watson struct test *test)
126d903306aSRobert Watson {
127d903306aSRobert Watson u_long flags;
128d903306aSRobert Watson int error;
129d903306aSRobert Watson
130d903306aSRobert Watson flags = getflags(fpath);
131d903306aSRobert Watson flags |= UF_NODUMP;
132d903306aSRobert Watson error = chflags(fpath, flags);
133d903306aSRobert Watson if (asroot && injail)
134d903306aSRobert Watson expect("priv_vfs_chflags_fowner_uflags(asroot, injail)",
135d903306aSRobert Watson error, 0, 0);
136d903306aSRobert Watson if (asroot && !injail)
137d903306aSRobert Watson expect("priv_vfs_chflags_fowner_uflags(asroot, !injail)",
138d903306aSRobert Watson error, 0, 0);
139d903306aSRobert Watson if (!asroot && injail)
140d903306aSRobert Watson expect("priv_vfs_chflags_fowner_uflags(!asroot, injail)",
141d903306aSRobert Watson error, 0, 0);
142d903306aSRobert Watson if (!asroot && !injail)
143d903306aSRobert Watson expect("priv_vfs_chflags_fowner_uflags(!asroot, !injail)",
144d903306aSRobert Watson error, 0, 0);
145d903306aSRobert Watson }
146d903306aSRobert Watson
147d903306aSRobert Watson void
priv_vfs_chflags_fother_uflags(int asroot,int injail,struct test * test)148d903306aSRobert Watson priv_vfs_chflags_fother_uflags(int asroot, int injail,
149d903306aSRobert Watson struct test *test)
150d903306aSRobert Watson {
151d903306aSRobert Watson u_long flags;
152d903306aSRobert Watson int error;
153d903306aSRobert Watson
154d903306aSRobert Watson flags = getflags(fpath);
155d903306aSRobert Watson flags |= UF_NODUMP;
156d903306aSRobert Watson error = chflags(fpath, flags);
157d903306aSRobert Watson if (asroot && injail)
158d903306aSRobert Watson expect("priv_vfs_chflags_fother_uflags(asroot, injail)",
159d903306aSRobert Watson error, 0, 0);
160d903306aSRobert Watson if (asroot && !injail)
161d903306aSRobert Watson expect("priv_vfs_chflags_fother_uflags(asroot, !injail)",
162d903306aSRobert Watson error, 0, 0);
163d903306aSRobert Watson if (!asroot && injail)
164d903306aSRobert Watson expect("priv_vfs_chflags_fother_uflags(!asroot, injail)",
165d903306aSRobert Watson error, -1, EPERM);
166d903306aSRobert Watson if (!asroot && !injail)
167d903306aSRobert Watson expect("priv_vfs_chflags_fother_uflags(!asroot, !injail)",
168d903306aSRobert Watson error, -1, EPERM);
169d903306aSRobert Watson }
170d903306aSRobert Watson
171d903306aSRobert Watson void
priv_vfs_chflags_froot_sflags(int asroot,int injail,struct test * test)172d903306aSRobert Watson priv_vfs_chflags_froot_sflags(int asroot, int injail,
173d903306aSRobert Watson struct test *test)
174d903306aSRobert Watson {
175d903306aSRobert Watson u_long flags;
176d903306aSRobert Watson int error;
177d903306aSRobert Watson
178d903306aSRobert Watson flags = getflags(fpath);
179d903306aSRobert Watson flags |= SF_ARCHIVED;
180d903306aSRobert Watson error = chflags(fpath, flags);
181d903306aSRobert Watson if (asroot && injail)
182d903306aSRobert Watson expect("priv_vfs_chflags_froot_sflags(asroot, injail)",
183d903306aSRobert Watson error, -1, EPERM);
184d903306aSRobert Watson if (asroot && !injail)
185d903306aSRobert Watson expect("priv_vfs_chflags_froot_sflags(asroot, !injail)",
186d903306aSRobert Watson error, 0, 0);
187d903306aSRobert Watson if (!asroot && injail)
188d903306aSRobert Watson expect("priv_vfs_chflags_froot_sflags(!asroot, injail)",
189d903306aSRobert Watson error, -1, EPERM);
190d903306aSRobert Watson if (!asroot && !injail)
191d903306aSRobert Watson expect("priv_vfs_chflags_froot_sflags(!asroot, !injail)",
192d903306aSRobert Watson error, -1, EPERM);
193d903306aSRobert Watson }
194d903306aSRobert Watson
195d903306aSRobert Watson void
priv_vfs_chflags_fowner_sflags(int asroot,int injail,struct test * test)196d903306aSRobert Watson priv_vfs_chflags_fowner_sflags(int asroot, int injail,
197d903306aSRobert Watson struct test *test)
198d903306aSRobert Watson {
199d903306aSRobert Watson u_long flags;
200d903306aSRobert Watson int error;
201d903306aSRobert Watson
202d903306aSRobert Watson flags = getflags(fpath);
203d903306aSRobert Watson flags |= SF_ARCHIVED;
204d903306aSRobert Watson error = chflags(fpath, flags);
205d903306aSRobert Watson if (asroot && injail)
206d903306aSRobert Watson expect("priv_vfs_chflags_fowner_sflags(asroot, injail)",
207d903306aSRobert Watson error, -1, EPERM);
208d903306aSRobert Watson if (asroot && !injail)
209d903306aSRobert Watson expect("priv_vfs_chflags_fowner_sflags(asroot, !injail)",
210d903306aSRobert Watson error, 0, 0);
211d903306aSRobert Watson if (!asroot && injail)
212d903306aSRobert Watson expect("priv_vfs_chflags_fowner_sflags(!asroot, injail)",
213d903306aSRobert Watson error, -1, EPERM);
214d903306aSRobert Watson if (!asroot && !injail)
215d903306aSRobert Watson expect("priv_vfs_chflags_fowner_sflags(!asroot, !injail)",
216d903306aSRobert Watson error, -1, EPERM);
217d903306aSRobert Watson }
218d903306aSRobert Watson
219d903306aSRobert Watson void
priv_vfs_chflags_fother_sflags(int asroot,int injail,struct test * test)220d903306aSRobert Watson priv_vfs_chflags_fother_sflags(int asroot, int injail,
221d903306aSRobert Watson struct test *test)
222d903306aSRobert Watson {
223d903306aSRobert Watson u_long flags;
224d903306aSRobert Watson int error;
225d903306aSRobert Watson
226d903306aSRobert Watson flags = getflags(fpath);
227d903306aSRobert Watson flags |= SF_ARCHIVED;
228d903306aSRobert Watson error = chflags(fpath, flags);
229d903306aSRobert Watson if (asroot && injail)
230d903306aSRobert Watson expect("priv_vfs_chflags_fother_sflags(asroot, injail)",
231d903306aSRobert Watson error, -1, EPERM);
232d903306aSRobert Watson if (asroot && !injail)
233d903306aSRobert Watson expect("priv_vfs_chflags_fother_sflags(asroot, !injail)",
234d903306aSRobert Watson error, 0, 0);
235d903306aSRobert Watson if (!asroot && injail)
236d903306aSRobert Watson expect("priv_vfs_chflags_fother_sflags(!asroot, injail)",
237d903306aSRobert Watson error, -1, EPERM);
238d903306aSRobert Watson if (!asroot && !injail)
239d903306aSRobert Watson expect("priv_vfs_chflags_fother_sflags(!asroot, !injail)",
240d903306aSRobert Watson error, -1, EPERM);
241d903306aSRobert Watson }
242d903306aSRobert Watson
243d903306aSRobert Watson void
priv_vfs_chflags_cleanup(int asroot,int injail,struct test * test)244d903306aSRobert Watson priv_vfs_chflags_cleanup(int asroot, int injail, struct test *test)
245d903306aSRobert Watson {
246d903306aSRobert Watson
247d903306aSRobert Watson if (fpath_initialized) {
248d903306aSRobert Watson (void)chflags(fpath, 0);
249d903306aSRobert Watson (void)unlink(fpath);
250d903306aSRobert Watson fpath_initialized = 0;
251d903306aSRobert Watson }
252d903306aSRobert Watson }
253