1 /*- 2 * Copyright (c) 2003-2010 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include "test.h" 26 __FBSDID("$FreeBSD$"); 27 28 /* 29 * Exercise the system-independent portion of the ACL support. 30 * Check that archive_entry objects can save and restore NFS4 ACL data. 31 * 32 * This should work on all systems, regardless of whether local 33 * filesystems support ACLs or not. 34 */ 35 36 struct acl_t { 37 int type; /* Type of entry: "allow" or "deny" */ 38 int permset; /* Permissions for this class of users. */ 39 int tag; /* Owner, User, Owning group, group, everyone, etc. */ 40 int qual; /* GID or UID of user/group, depending on tag. */ 41 const char *name; /* Name of user/group, depending on tag. */ 42 }; 43 44 static struct acl_t acls1[] = { 45 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 46 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, 47 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_READ_DATA, 48 ARCHIVE_ENTRY_ACL_USER, 77, "user77" }, 49 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA, 50 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, 51 { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_WRITE_DATA, 52 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, 53 }; 54 55 static struct acl_t acls2[] = { 56 /* An entry for each type. */ 57 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 0, 58 ARCHIVE_ENTRY_ACL_USER, 108, "user108" }, 59 { ARCHIVE_ENTRY_ACL_TYPE_DENY, 0, 60 ARCHIVE_ENTRY_ACL_USER, 109, "user109" }, 61 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, 0, 62 ARCHIVE_ENTRY_ACL_USER, 110, "user110" }, 63 { ARCHIVE_ENTRY_ACL_TYPE_ALARM, 0, 64 ARCHIVE_ENTRY_ACL_USER, 111, "user111" }, 65 66 /* An entry for each permission. */ 67 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 68 ARCHIVE_ENTRY_ACL_USER, 112, "user112" }, 69 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA, 70 ARCHIVE_ENTRY_ACL_USER, 113, "user113" }, 71 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 72 ARCHIVE_ENTRY_ACL_USER, 114, "user114" }, 73 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA, 74 ARCHIVE_ENTRY_ACL_USER, 115, "user115" }, 75 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE, 76 ARCHIVE_ENTRY_ACL_USER, 116, "user116" }, 77 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA, 78 ARCHIVE_ENTRY_ACL_USER, 117, "user117" }, 79 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, 80 ARCHIVE_ENTRY_ACL_USER, 118, "user118" }, 81 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 82 ARCHIVE_ENTRY_ACL_USER, 119, "user119" }, 83 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 84 ARCHIVE_ENTRY_ACL_USER, 120, "user120" }, 85 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD, 86 ARCHIVE_ENTRY_ACL_USER, 121, "user121" }, 87 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 88 ARCHIVE_ENTRY_ACL_USER, 122, "user122" }, 89 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 90 ARCHIVE_ENTRY_ACL_USER, 123, "user123" }, 91 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE, 92 ARCHIVE_ENTRY_ACL_USER, 124, "user124" }, 93 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL, 94 ARCHIVE_ENTRY_ACL_USER, 125, "user125" }, 95 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL, 96 ARCHIVE_ENTRY_ACL_USER, 126, "user126" }, 97 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER, 98 ARCHIVE_ENTRY_ACL_USER, 127, "user127" }, 99 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 100 ARCHIVE_ENTRY_ACL_USER, 128, "user128" }, 101 102 /* One entry with each inheritance value. */ 103 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 104 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 105 ARCHIVE_ENTRY_ACL_USER, 129, "user129" }, 106 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 107 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 108 ARCHIVE_ENTRY_ACL_USER, 130, "user130" }, 109 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 110 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 111 ARCHIVE_ENTRY_ACL_USER, 131, "user131" }, 112 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, 113 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 114 ARCHIVE_ENTRY_ACL_USER, 132, "user132" }, 115 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, 116 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 117 ARCHIVE_ENTRY_ACL_USER, 133, "user133" }, 118 { ARCHIVE_ENTRY_ACL_TYPE_AUDIT, 119 ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 120 ARCHIVE_ENTRY_ACL_USER, 134, "user134" }, 121 122 /* One entry for each qualifier. */ 123 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 124 ARCHIVE_ENTRY_ACL_USER, 135, "user135" }, 125 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 126 ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, 127 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 128 ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" }, 129 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 130 ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, 131 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 132 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, 133 }; 134 135 /* 136 * Entries that should be rejected when we attempt to set them 137 * on an ACL that already has NFS4 entries. 138 */ 139 static struct acl_t acls_bad[] = { 140 /* POSIX.1e ACL types */ 141 { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE, 142 ARCHIVE_ENTRY_ACL_USER, 78, "" }, 143 { ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_EXECUTE, 144 ARCHIVE_ENTRY_ACL_USER, 78, "" }, 145 146 /* POSIX.1e tags */ 147 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 148 ARCHIVE_ENTRY_ACL_OTHER, -1, "" }, 149 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE, 150 ARCHIVE_ENTRY_ACL_MASK, -1, "" }, 151 152 /* POSIX.1e permissions */ 153 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ, 154 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, 155 { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE, 156 ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, 157 }; 158 159 static void 160 set_acls(struct archive_entry *ae, struct acl_t *acls, int n) 161 { 162 int i; 163 164 archive_entry_acl_clear(ae); 165 for (i = 0; i < n; i++) { 166 failure("type=%d, permset=%d, tag=%d, qual=%d name=%s", 167 acls[i].type, acls[i].permset, acls[i].tag, 168 acls[i].qual, acls[i].name); 169 assertEqualInt(ARCHIVE_OK, 170 archive_entry_acl_add_entry(ae, 171 acls[i].type, acls[i].permset, acls[i].tag, 172 acls[i].qual, acls[i].name)); 173 } 174 } 175 176 static int 177 acl_match(struct acl_t *acl, int type, int permset, int tag, int qual, 178 const char *name) 179 { 180 if (acl == NULL) 181 return (0); 182 if (type != acl->type) 183 return (0); 184 if (permset != acl->permset) 185 return (0); 186 if (tag != acl->tag) 187 return (0); 188 if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) 189 return (1); 190 if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) 191 return (1); 192 if (tag == ARCHIVE_ENTRY_ACL_EVERYONE) 193 return (1); 194 if (qual != acl->qual) 195 return (0); 196 if (name == NULL) { 197 if (acl->name == NULL || acl->name[0] == '\0') 198 return (1); 199 return (0); 200 } 201 if (acl->name == NULL) { 202 if (name[0] == '\0') 203 return (1); 204 return (0); 205 } 206 return (0 == strcmp(name, acl->name)); 207 } 208 209 static void 210 compare_acls(struct archive_entry *ae, struct acl_t *acls, int n) 211 { 212 int *marker = malloc(sizeof(marker[0]) * n); 213 int i; 214 int r; 215 int type, permset, tag, qual; 216 int matched; 217 const char *name; 218 219 for (i = 0; i < n; i++) 220 marker[i] = i; 221 222 while (0 == (r = archive_entry_acl_next(ae, 223 ARCHIVE_ENTRY_ACL_TYPE_NFS4, 224 &type, &permset, &tag, &qual, &name))) { 225 for (i = 0, matched = 0; i < n && !matched; i++) { 226 if (acl_match(&acls[marker[i]], type, permset, 227 tag, qual, name)) { 228 /* We found a match; remove it. */ 229 marker[i] = marker[n - 1]; 230 n--; 231 matched = 1; 232 } 233 } 234 failure("Could not find match for ACL " 235 "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')", 236 type, permset, tag, qual, name); 237 assertEqualInt(1, matched); 238 } 239 assertEqualInt(ARCHIVE_EOF, r); 240 failure("Could not find match for ACL " 241 "(type=%d,permset=%d,tag=%d,qual=%d,name=``%s'')", 242 acls[marker[0]].type, acls[marker[0]].permset, 243 acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name); 244 assertEqualInt(0, n); /* Number of ACLs not matched should == 0 */ 245 free(marker); 246 } 247 248 DEFINE_TEST(test_acl_nfs4) 249 { 250 struct archive_entry *ae; 251 int i; 252 253 /* Create a simple archive_entry. */ 254 assert((ae = archive_entry_new()) != NULL); 255 archive_entry_set_pathname(ae, "file"); 256 archive_entry_set_mode(ae, S_IFREG | 0777); 257 258 /* Store and read back some basic ACL entries. */ 259 set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); 260 assertEqualInt(4, 261 archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); 262 compare_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); 263 264 /* A more extensive set of ACLs. */ 265 set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); 266 assertEqualInt(32, 267 archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); 268 compare_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); 269 270 /* 271 * Check that clearing ACLs gets rid of them all by repeating 272 * the first test. 273 */ 274 set_acls(ae, acls1, sizeof(acls1)/sizeof(acls1[0])); 275 failure("Basic ACLs shouldn't be stored as extended ACLs"); 276 assertEqualInt(4, 277 archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); 278 279 /* 280 * Different types of malformed ACL entries that should 281 * fail when added to existing NFS4 ACLs. 282 */ 283 set_acls(ae, acls2, sizeof(acls2)/sizeof(acls2[0])); 284 for (i = 0; i < (int)(sizeof(acls_bad)/sizeof(acls_bad[0])); ++i) { 285 struct acl_t *p = &acls_bad[i]; 286 failure("Malformed ACL test #%d", i); 287 assertEqualInt(ARCHIVE_FAILED, 288 archive_entry_acl_add_entry(ae, 289 p->type, p->permset, p->tag, p->qual, p->name)); 290 failure("Malformed ACL test #%d", i); 291 assertEqualInt(32, 292 archive_entry_acl_reset(ae, 293 ARCHIVE_ENTRY_ACL_TYPE_NFS4)); 294 } 295 archive_entry_free(ae); 296 } 297