1172106Srwatson/*-
2172106Srwatson * Copyright (c) 2006 nCircle Network Security, Inc.
3172106Srwatson * Copyright (c) 2007 Robert N. M. Watson
4172106Srwatson * All rights reserved.
5172106Srwatson *
6172106Srwatson * This software was developed by Robert N. M. Watson for the TrustedBSD
7172106Srwatson * Project under contract to nCircle Network Security, Inc.
8172106Srwatson *
9172106Srwatson * Redistribution and use in source and binary forms, with or without
10172106Srwatson * modification, are permitted provided that the following conditions
11172106Srwatson * are met:
12172106Srwatson * 1. Redistributions of source code must retain the above copyright
13172106Srwatson *    notice, this list of conditions and the following disclaimer.
14172106Srwatson * 2. Redistributions in binary form must reproduce the above copyright
15172106Srwatson *    notice, this list of conditions and the following disclaimer in the
16172106Srwatson *    documentation and/or other materials provided with the distribution.
17172106Srwatson *
18172106Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19172106Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20172106Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21172106Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22172106Srwatson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23172106Srwatson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24172106Srwatson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25172106Srwatson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26172106Srwatson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27172106Srwatson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28172106Srwatson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29172106Srwatson *
30172106Srwatson * $FreeBSD$
31172106Srwatson */
32172106Srwatson
33172106Srwatson/*
34172106Srwatson * Test privileges associated with setting file flags on files; whether or
35172106Srwatson * not it requires privilege depends on the flag, and some flags cannot be
36172106Srwatson * set in jail at all.
37172106Srwatson */
38172106Srwatson
39172106Srwatson#include <sys/types.h>
40172106Srwatson#include <sys/stat.h>
41172106Srwatson
42172106Srwatson#include <err.h>
43172106Srwatson#include <errno.h>
44172106Srwatson#include <stdlib.h>
45172106Srwatson#include <string.h>
46172106Srwatson#include <unistd.h>
47172106Srwatson
48172106Srwatson#include "main.h"
49172106Srwatson
50172106Srwatsonstatic char fpath[1024];
51172106Srwatsonstatic int fpath_initialized;
52172106Srwatson
53172106Srwatson/*
54172106Srwatson * For chflags, we consider three dimmensions: process owner, file owner, and
55172106Srwatson * flag type.  The calling framework handles variations in process owner; the
56172106Srwatson * rest are handled via multiple tests.  One cleanup function is used.
57172106Srwatson */
58172106Srwatsonstatic u_long
59172106Srwatsongetflags(char *fpathp)
60172106Srwatson{
61172106Srwatson	struct stat sb;
62172106Srwatson
63172106Srwatson	if (stat(fpathp, &sb) < 0)
64172106Srwatson		err(-1, "stat(%s)", fpathp);
65172106Srwatson
66172106Srwatson	return (sb.st_flags);
67172106Srwatson}
68172106Srwatson
69172106Srwatsonint
70172106Srwatsonpriv_vfs_chflags_froot_setup(int asroot, int injail, struct test *test)
71172106Srwatson{
72172106Srwatson
73172106Srwatson	setup_file("priv_vfs_chflags_froot_setup: fpath", fpath, UID_ROOT,
74172106Srwatson	    GID_WHEEL, 0600);
75172106Srwatson	fpath_initialized = 1;
76172106Srwatson	return (0);
77172106Srwatson}
78172106Srwatson
79172106Srwatsonint
80172106Srwatsonpriv_vfs_chflags_fowner_setup(int asroot, int injail,
81172106Srwatson    struct test *test)
82172106Srwatson{
83172106Srwatson
84172106Srwatson	setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OWNER,
85172106Srwatson	    GID_OWNER, 0600);
86172106Srwatson	fpath_initialized = 1;
87172106Srwatson	return (0);
88172106Srwatson}
89172106Srwatson
90172106Srwatsonint
91172106Srwatsonpriv_vfs_chflags_fother_setup(int asroot, int injail,
92172106Srwatson    struct test *test)
93172106Srwatson{
94172106Srwatson
95172106Srwatson	setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OTHER,
96172106Srwatson	    GID_OTHER, 0600);
97172106Srwatson	fpath_initialized = 1;
98172106Srwatson	return (0);
99172106Srwatson}
100172106Srwatson
101172106Srwatsonvoid
102172106Srwatsonpriv_vfs_chflags_froot_uflags(int asroot, int injail,
103172106Srwatson    struct test *test)
104172106Srwatson{
105172106Srwatson	u_long flags;
106172106Srwatson	int error;
107172106Srwatson
108172106Srwatson	flags = getflags(fpath);
109172106Srwatson	flags |= UF_NODUMP;
110172106Srwatson	error = chflags(fpath, flags);
111172106Srwatson	if (asroot && injail)
112172106Srwatson		expect("priv_vfs_chflags_froot_uflags(asroot, injail)",
113172106Srwatson		    error, 0, 0);
114172106Srwatson	if (asroot && !injail)
115172106Srwatson		expect("priv_vfs_chflags_froot_uflags(asroot, !injail)",
116172106Srwatson		    error, 0, 0);
117172106Srwatson	if (!asroot && injail)
118172106Srwatson		expect("priv_vfs_chflags_froot_uflags(!asroot, injail)",
119172106Srwatson		    error, -1, EPERM);
120172106Srwatson	if (!asroot && !injail)
121172106Srwatson		expect("priv_vfs_chflags_froot_uflags(!asroot, !injail)",
122172106Srwatson		    error, -1, EPERM);
123172106Srwatson}
124172106Srwatson
125172106Srwatsonvoid
126172106Srwatsonpriv_vfs_chflags_fowner_uflags(int asroot, int injail,
127172106Srwatson    struct test *test)
128172106Srwatson{
129172106Srwatson	u_long flags;
130172106Srwatson	int error;
131172106Srwatson
132172106Srwatson	flags = getflags(fpath);
133172106Srwatson	flags |= UF_NODUMP;
134172106Srwatson	error = chflags(fpath, flags);
135172106Srwatson	if (asroot && injail)
136172106Srwatson		expect("priv_vfs_chflags_fowner_uflags(asroot, injail)",
137172106Srwatson		    error, 0, 0);
138172106Srwatson	if (asroot && !injail)
139172106Srwatson		expect("priv_vfs_chflags_fowner_uflags(asroot, !injail)",
140172106Srwatson		    error, 0, 0);
141172106Srwatson	if (!asroot && injail)
142172106Srwatson		expect("priv_vfs_chflags_fowner_uflags(!asroot, injail)",
143172106Srwatson		    error, 0, 0);
144172106Srwatson	if (!asroot && !injail)
145172106Srwatson		expect("priv_vfs_chflags_fowner_uflags(!asroot, !injail)",
146172106Srwatson		    error, 0, 0);
147172106Srwatson}
148172106Srwatson
149172106Srwatsonvoid
150172106Srwatsonpriv_vfs_chflags_fother_uflags(int asroot, int injail,
151172106Srwatson    struct test *test)
152172106Srwatson{
153172106Srwatson	u_long flags;
154172106Srwatson	int error;
155172106Srwatson
156172106Srwatson	flags = getflags(fpath);
157172106Srwatson	flags |= UF_NODUMP;
158172106Srwatson	error = chflags(fpath, flags);
159172106Srwatson	if (asroot && injail)
160172106Srwatson		expect("priv_vfs_chflags_fother_uflags(asroot, injail)",
161172106Srwatson		    error, 0, 0);
162172106Srwatson	if (asroot && !injail)
163172106Srwatson		expect("priv_vfs_chflags_fother_uflags(asroot, !injail)",
164172106Srwatson		    error, 0, 0);
165172106Srwatson	if (!asroot && injail)
166172106Srwatson		expect("priv_vfs_chflags_fother_uflags(!asroot, injail)",
167172106Srwatson		    error, -1, EPERM);
168172106Srwatson	if (!asroot && !injail)
169172106Srwatson		expect("priv_vfs_chflags_fother_uflags(!asroot, !injail)",
170172106Srwatson		    error, -1, EPERM);
171172106Srwatson}
172172106Srwatson
173172106Srwatsonvoid
174172106Srwatsonpriv_vfs_chflags_froot_sflags(int asroot, int injail,
175172106Srwatson    struct test *test)
176172106Srwatson{
177172106Srwatson	u_long flags;
178172106Srwatson	int error;
179172106Srwatson
180172106Srwatson	flags = getflags(fpath);
181172106Srwatson	flags |= SF_ARCHIVED;
182172106Srwatson	error = chflags(fpath, flags);
183172106Srwatson	if (asroot && injail)
184172106Srwatson		expect("priv_vfs_chflags_froot_sflags(asroot, injail)",
185172106Srwatson		    error, -1, EPERM);
186172106Srwatson	if (asroot && !injail)
187172106Srwatson		expect("priv_vfs_chflags_froot_sflags(asroot, !injail)",
188172106Srwatson		    error, 0, 0);
189172106Srwatson	if (!asroot && injail)
190172106Srwatson		expect("priv_vfs_chflags_froot_sflags(!asroot, injail)",
191172106Srwatson		    error, -1, EPERM);
192172106Srwatson	if (!asroot && !injail)
193172106Srwatson		expect("priv_vfs_chflags_froot_sflags(!asroot, !injail)",
194172106Srwatson		    error, -1, EPERM);
195172106Srwatson}
196172106Srwatson
197172106Srwatsonvoid
198172106Srwatsonpriv_vfs_chflags_fowner_sflags(int asroot, int injail,
199172106Srwatson    struct test *test)
200172106Srwatson{
201172106Srwatson	u_long flags;
202172106Srwatson	int error;
203172106Srwatson
204172106Srwatson	flags = getflags(fpath);
205172106Srwatson	flags |= SF_ARCHIVED;
206172106Srwatson	error = chflags(fpath, flags);
207172106Srwatson	if (asroot && injail)
208172106Srwatson		expect("priv_vfs_chflags_fowner_sflags(asroot, injail)",
209172106Srwatson		    error, -1, EPERM);
210172106Srwatson	if (asroot && !injail)
211172106Srwatson		expect("priv_vfs_chflags_fowner_sflags(asroot, !injail)",
212172106Srwatson		    error, 0, 0);
213172106Srwatson	if (!asroot && injail)
214172106Srwatson		expect("priv_vfs_chflags_fowner_sflags(!asroot, injail)",
215172106Srwatson		    error, -1, EPERM);
216172106Srwatson	if (!asroot && !injail)
217172106Srwatson		expect("priv_vfs_chflags_fowner_sflags(!asroot, !injail)",
218172106Srwatson		    error, -1, EPERM);
219172106Srwatson}
220172106Srwatson
221172106Srwatsonvoid
222172106Srwatsonpriv_vfs_chflags_fother_sflags(int asroot, int injail,
223172106Srwatson    struct test *test)
224172106Srwatson{
225172106Srwatson	u_long flags;
226172106Srwatson	int error;
227172106Srwatson
228172106Srwatson	flags = getflags(fpath);
229172106Srwatson	flags |= SF_ARCHIVED;
230172106Srwatson	error = chflags(fpath, flags);
231172106Srwatson	if (asroot && injail)
232172106Srwatson		expect("priv_vfs_chflags_fother_sflags(asroot, injail)",
233172106Srwatson		    error, -1, EPERM);
234172106Srwatson	if (asroot && !injail)
235172106Srwatson		expect("priv_vfs_chflags_fother_sflags(asroot, !injail)",
236172106Srwatson		    error, 0, 0);
237172106Srwatson	if (!asroot && injail)
238172106Srwatson		expect("priv_vfs_chflags_fother_sflags(!asroot, injail)",
239172106Srwatson		    error, -1, EPERM);
240172106Srwatson	if (!asroot && !injail)
241172106Srwatson		expect("priv_vfs_chflags_fother_sflags(!asroot, !injail)",
242172106Srwatson		    error, -1, EPERM);
243172106Srwatson}
244172106Srwatson
245172106Srwatsonvoid
246172106Srwatsonpriv_vfs_chflags_cleanup(int asroot, int injail, struct test *test)
247172106Srwatson{
248172106Srwatson
249172106Srwatson	if (fpath_initialized) {
250172106Srwatson		(void)chflags(fpath, 0);
251172106Srwatson		(void)unlink(fpath);
252172106Srwatson		fpath_initialized = 0;
253172106Srwatson	}
254172106Srwatson}
255