xref: /freebsd/tools/regression/priv/priv_acct.c (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
1 /*-
2  * Copyright (c) 2006 nCircle Network Security, Inc.
3  * All rights reserved.
4  *
5  * This software was developed by Robert N. M. Watson for the TrustedBSD
6  * Project under contract to nCircle Network Security, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
21  * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * Test that configuring accounting requires privilege.  First check that
34  * accounting is not in use on the system to prevent disrupting the
35  * accounting service.  Confirm three different state transitions, both as
36  * privileged and non-privileged: disabled to enabled, rotate, and enabled to
37  * disabled.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/sysctl.h>
43 
44 #include <err.h>
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 
49 #include "main.h"
50 
51 #define	SYSCTL_NAME	"kern.acct_configured"
52 #define	PATH_TEMPLATE	"/tmp/acct.XXXXXXXXXXX"
53 
54 void
55 priv_acct(void)
56 {
57 	char fpath1[1024] = PATH_TEMPLATE;
58 	char fpath2[1024] = PATH_TEMPLATE;
59 	int error, fd, i;
60 	size_t len;
61 
62 	assert_root();
63 
64 	/*
65 	 * Check that accounting isn't already configured in the kernel.
66 	 */
67 	len = sizeof(i);
68 	if (sysctlbyname(SYSCTL_NAME, &i, &len, NULL, 0) < 0)
69 		err(-1, "sysctlbyname(%s)", SYSCTL_NAME);
70 	if (i != 0)
71 		errx(-1, "sysctlbyname(%s) indicates accounting configured",
72 		    SYSCTL_NAME);
73 
74 	/*
75 	 * Create two temporary files to use as accounting targets.
76 	 */
77 	fd = mkstemp(fpath1);
78 	if (fd < 0)
79 		err(-1, "mkstemp");
80 	close(fd);
81 	fd = mkstemp(fpath2);
82 	if (fd < 0) {
83 		warn("mkstemp");
84 		(void)unlink(fpath1);
85 		exit(-1);
86 	}
87 
88 	/*
89 	 * Change the permissions on the file so that access control on the
90 	 * file doesn't come into play.
91 	 */
92 	if (chmod(fpath1, 0666) < 0) {
93 		warn("chmod(%s, 0666)", fpath1);
94 		goto out;
95 	}
96 
97 	if (chmod(fpath2, 0666) < 0) {
98 		warn("chmod(%s, 0600)", fpath2);
99 		goto out;
100 	}
101 
102 	/*
103 	 * Test that privileged can move through entire life cycle.
104 	 */
105 	if (acct(fpath1) < 0) {
106 		warn("acct(NULL -> %s) as root", fpath1);
107 		goto out;
108 	}
109 
110 	if (acct(fpath2) < 0) {
111 		warn("acct(%s -> %s) as root", fpath1, fpath2);
112 		goto out;
113 	}
114 
115 	if (acct(NULL) < 0) {
116 		warn("acct(%s -> NULL) as root", fpath1);
117 		goto out;
118 	}
119 
120 	/*
121 	 * Testing for unprivileged is a bit more tricky, as expect each step
122 	 * to fail, so must replay various bits of the setup process as root
123 	 * so that each step can be tested as !root.
124 	 */
125 	set_euid(UID_OTHER);
126 	error = acct(fpath1);
127 	if (error == 0) {
128 		warnx("acct(NULL -> %s) succeeded as !root", fpath1);
129 		goto out;
130 	}
131 	if (errno != EPERM) {
132 		warn("acct(NULL -> %s) wrong errno %d as !root", fpath1,
133 		    errno);
134 		goto out;
135 	}
136 
137 	set_euid(UID_ROOT);
138 	if (acct(fpath1) < 0) {
139 		err(-1, "acct(NULL -> %s) setup for !root", fpath1);
140 		goto out;
141 	}
142 
143 	set_euid(UID_OTHER);
144 	error = acct(fpath2);
145 	if (error == 0) {
146 		warnx("acct(%s -> %s) succeeded as !root", fpath1, fpath2);
147 		goto out;
148 	}
149 	if (errno != EPERM) {
150 		warn("acct(%s -> %s) wrong errno %d as !root", fpath1,
151 		    fpath2, errno);
152 		goto out;
153 	}
154 
155 	set_euid(UID_ROOT);
156 	if (acct(fpath2) < 0) {
157 		err(-1, "acct(%s -> %s) setup for !root", fpath1, fpath2);
158 		goto out;
159 	}
160 
161 	set_euid(UID_OTHER);
162 	error = acct(NULL);
163 	if (error == 0) {
164 		warnx("acct(%s -> NULL) succeeded as !root", fpath2);
165 		goto out;
166 	}
167 	if (errno != EPERM) {
168 		warn("acct(%s -> NULL) wrong errno %d as !root", fpath2,
169 		    errno);
170 		goto out;
171 	}
172 
173 out:
174 	(void)seteuid(UID_ROOT);
175 	(void)acct(NULL);
176 	(void)unlink(fpath1);
177 	(void)unlink(fpath2);
178 }
179