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 * Test privileges associated with setting file flags on files; whether or 35 * not it requires privilege depends on the flag, and some flags cannot be 36 * set in jail at all. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 42 #include <err.h> 43 #include <errno.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "main.h" 49 50 static char fpath[1024]; 51 static int fpath_initialized; 52 53 /* 54 * For chflags, we consider three dimmensions: process owner, file owner, and 55 * flag type. The calling framework handles variations in process owner; the 56 * rest are handled via multiple tests. One cleanup function is used. 57 */ 58 static u_long 59 getflags(char *fpathp) 60 { 61 struct stat sb; 62 63 if (stat(fpathp, &sb) < 0) 64 err(-1, "stat(%s)", fpathp); 65 66 return (sb.st_flags); 67 } 68 69 int 70 priv_vfs_chflags_froot_setup(int asroot, int injail, struct test *test) 71 { 72 73 setup_file("priv_vfs_chflags_froot_setup: fpath", fpath, UID_ROOT, 74 GID_WHEEL, 0600); 75 fpath_initialized = 1; 76 return (0); 77 } 78 79 int 80 priv_vfs_chflags_fowner_setup(int asroot, int injail, 81 struct test *test) 82 { 83 84 setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OWNER, 85 GID_OWNER, 0600); 86 fpath_initialized = 1; 87 return (0); 88 } 89 90 int 91 priv_vfs_chflags_fother_setup(int asroot, int injail, 92 struct test *test) 93 { 94 95 setup_file("priv_vfs_chflags_fowner_setup: fpath", fpath, UID_OTHER, 96 GID_OTHER, 0600); 97 fpath_initialized = 1; 98 return (0); 99 } 100 101 void 102 priv_vfs_chflags_froot_uflags(int asroot, int injail, 103 struct test *test) 104 { 105 u_long flags; 106 int error; 107 108 flags = getflags(fpath); 109 flags |= UF_NODUMP; 110 error = chflags(fpath, flags); 111 if (asroot && injail) 112 expect("priv_vfs_chflags_froot_uflags(asroot, injail)", 113 error, 0, 0); 114 if (asroot && !injail) 115 expect("priv_vfs_chflags_froot_uflags(asroot, !injail)", 116 error, 0, 0); 117 if (!asroot && injail) 118 expect("priv_vfs_chflags_froot_uflags(!asroot, injail)", 119 error, -1, EPERM); 120 if (!asroot && !injail) 121 expect("priv_vfs_chflags_froot_uflags(!asroot, !injail)", 122 error, -1, EPERM); 123 } 124 125 void 126 priv_vfs_chflags_fowner_uflags(int asroot, int injail, 127 struct test *test) 128 { 129 u_long flags; 130 int error; 131 132 flags = getflags(fpath); 133 flags |= UF_NODUMP; 134 error = chflags(fpath, flags); 135 if (asroot && injail) 136 expect("priv_vfs_chflags_fowner_uflags(asroot, injail)", 137 error, 0, 0); 138 if (asroot && !injail) 139 expect("priv_vfs_chflags_fowner_uflags(asroot, !injail)", 140 error, 0, 0); 141 if (!asroot && injail) 142 expect("priv_vfs_chflags_fowner_uflags(!asroot, injail)", 143 error, 0, 0); 144 if (!asroot && !injail) 145 expect("priv_vfs_chflags_fowner_uflags(!asroot, !injail)", 146 error, 0, 0); 147 } 148 149 void 150 priv_vfs_chflags_fother_uflags(int asroot, int injail, 151 struct test *test) 152 { 153 u_long flags; 154 int error; 155 156 flags = getflags(fpath); 157 flags |= UF_NODUMP; 158 error = chflags(fpath, flags); 159 if (asroot && injail) 160 expect("priv_vfs_chflags_fother_uflags(asroot, injail)", 161 error, 0, 0); 162 if (asroot && !injail) 163 expect("priv_vfs_chflags_fother_uflags(asroot, !injail)", 164 error, 0, 0); 165 if (!asroot && injail) 166 expect("priv_vfs_chflags_fother_uflags(!asroot, injail)", 167 error, -1, EPERM); 168 if (!asroot && !injail) 169 expect("priv_vfs_chflags_fother_uflags(!asroot, !injail)", 170 error, -1, EPERM); 171 } 172 173 void 174 priv_vfs_chflags_froot_sflags(int asroot, int injail, 175 struct test *test) 176 { 177 u_long flags; 178 int error; 179 180 flags = getflags(fpath); 181 flags |= SF_ARCHIVED; 182 error = chflags(fpath, flags); 183 if (asroot && injail) 184 expect("priv_vfs_chflags_froot_sflags(asroot, injail)", 185 error, -1, EPERM); 186 if (asroot && !injail) 187 expect("priv_vfs_chflags_froot_sflags(asroot, !injail)", 188 error, 0, 0); 189 if (!asroot && injail) 190 expect("priv_vfs_chflags_froot_sflags(!asroot, injail)", 191 error, -1, EPERM); 192 if (!asroot && !injail) 193 expect("priv_vfs_chflags_froot_sflags(!asroot, !injail)", 194 error, -1, EPERM); 195 } 196 197 void 198 priv_vfs_chflags_fowner_sflags(int asroot, int injail, 199 struct test *test) 200 { 201 u_long flags; 202 int error; 203 204 flags = getflags(fpath); 205 flags |= SF_ARCHIVED; 206 error = chflags(fpath, flags); 207 if (asroot && injail) 208 expect("priv_vfs_chflags_fowner_sflags(asroot, injail)", 209 error, -1, EPERM); 210 if (asroot && !injail) 211 expect("priv_vfs_chflags_fowner_sflags(asroot, !injail)", 212 error, 0, 0); 213 if (!asroot && injail) 214 expect("priv_vfs_chflags_fowner_sflags(!asroot, injail)", 215 error, -1, EPERM); 216 if (!asroot && !injail) 217 expect("priv_vfs_chflags_fowner_sflags(!asroot, !injail)", 218 error, -1, EPERM); 219 } 220 221 void 222 priv_vfs_chflags_fother_sflags(int asroot, int injail, 223 struct test *test) 224 { 225 u_long flags; 226 int error; 227 228 flags = getflags(fpath); 229 flags |= SF_ARCHIVED; 230 error = chflags(fpath, flags); 231 if (asroot && injail) 232 expect("priv_vfs_chflags_fother_sflags(asroot, injail)", 233 error, -1, EPERM); 234 if (asroot && !injail) 235 expect("priv_vfs_chflags_fother_sflags(asroot, !injail)", 236 error, 0, 0); 237 if (!asroot && injail) 238 expect("priv_vfs_chflags_fother_sflags(!asroot, injail)", 239 error, -1, EPERM); 240 if (!asroot && !injail) 241 expect("priv_vfs_chflags_fother_sflags(!asroot, !injail)", 242 error, -1, EPERM); 243 } 244 245 void 246 priv_vfs_chflags_cleanup(int asroot, int injail, struct test *test) 247 { 248 249 if (fpath_initialized) { 250 (void)chflags(fpath, 0); 251 (void)unlink(fpath); 252 fpath_initialized = 0; 253 } 254 } 255