1/* 2 Unix SMB/Netbios implementation. 3 VFS module to get and set Tru64 acls 4 Copyright (C) Michael Adam 2006,2008 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21 22/* prototypes for private functions first - for clarity */ 23 24static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl); 25static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace, 26 struct smb_acl_entry *smb_ace); 27static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl); 28static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag); 29static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag); 30static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset); 31static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset); 32 33 34/* public functions - the api */ 35 36SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle, 37 const char *path_p, 38 SMB_ACL_TYPE_T type) 39{ 40 struct smb_acl_t *result; 41 acl_type_t the_acl_type; 42 acl_t tru64_acl; 43 44 DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n")); 45 46 switch(type) { 47 case SMB_ACL_TYPE_ACCESS: 48 the_acl_type = ACL_TYPE_ACCESS; 49 break; 50 case SMB_ACL_TYPE_DEFAULT: 51 the_acl_type = ACL_TYPE_DEFAULT; 52 break; 53 default: 54 errno = EINVAL; 55 return NULL; 56 } 57 58 tru64_acl = acl_get_file((char *)path_p, the_acl_type); 59 60 if (tru64_acl == NULL) { 61 return NULL; 62 } 63 64 result = tru64_acl_to_smb_acl(tru64_acl); 65 acl_free(tru64_acl); 66 return result; 67} 68 69SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle, 70 files_struct *fsp) 71{ 72 struct smb_acl_t *result; 73 acl_t tru64_acl = acl_get_fd(fsp->fh->fd, ACL_TYPE_ACCESS); 74 75 if (tru64_acl == NULL) { 76 return NULL; 77 } 78 79 result = tru64_acl_to_smb_acl(tru64_acl); 80 acl_free(tru64_acl); 81 return result; 82} 83 84int tru64acl_sys_acl_set_file(vfs_handle_struct *handle, 85 const char *name, 86 SMB_ACL_TYPE_T type, 87 SMB_ACL_T theacl) 88{ 89 int res; 90 acl_type_t the_acl_type; 91 acl_t tru64_acl; 92 93 DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n", 94 name, type)); 95 96 switch(type) { 97 case SMB_ACL_TYPE_ACCESS: 98 DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n")); 99 the_acl_type = ACL_TYPE_ACCESS; 100 break; 101 case SMB_ACL_TYPE_DEFAULT: 102 DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n")); 103 the_acl_type = ACL_TYPE_DEFAULT; 104 break; 105 default: 106 DEBUGADD(10, ("invalid acl type\n")); 107 errno = EINVAL; 108 goto fail; 109 } 110 111 tru64_acl = smb_acl_to_tru64_acl(theacl); 112 if (tru64_acl == NULL) { 113 DEBUG(10, ("smb_acl_to_tru64_acl failed!\n")); 114 goto fail; 115 } 116 DEBUG(10, ("got tru64 acl...\n")); 117 res = acl_set_file((char *)name, the_acl_type, tru64_acl); 118 acl_free(tru64_acl); 119 if (res != 0) { 120 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno))); 121 goto fail; 122 } 123 return res; 124fail: 125 DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n")); 126 return -1; 127} 128 129int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle, 130 files_struct *fsp, 131 SMB_ACL_T theacl) 132{ 133 int res; 134 acl_t tru64_acl = smb_acl_to_tru64_acl(theacl); 135 if (tru64_acl == NULL) { 136 return -1; 137 } 138 res = acl_set_fd(fsp->fh->fd, ACL_TYPE_ACCESS, tru64_acl); 139 acl_free(tru64_acl); 140 return res; 141 142} 143 144int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle, 145 const char *path) 146{ 147 return acl_delete_def_file((char *)path); 148} 149 150 151/* private functions */ 152 153static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl) 154{ 155 struct smb_acl_t *result; 156 acl_entry_t entry; 157 158 DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n")); 159 160 if ((result = SMB_MALLOC_P(struct smb_acl_t)) == NULL) { 161 DEBUG(0, ("SMB_MALLOC_P failed in tru64_acl_to_smb_acl\n")); 162 errno = ENOMEM; 163 goto fail; 164 } 165 ZERO_STRUCTP(result); 166 if (acl_first_entry((struct acl *)tru64_acl) != 0) { 167 DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno))); 168 goto fail; 169 } 170 while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) { 171 result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + 172 (sizeof(struct smb_acl_entry) * 173 (result->count + 1))); 174 if (result == NULL) { 175 DEBUG(0, ("SMB_REALLOC failed in tru64_acl_to_smb_acl\n")); 176 errno = ENOMEM; 177 goto fail; 178 } 179 /* XYZ */ 180 if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) { 181 SAFE_FREE(result); 182 goto fail; 183 } 184 result->count += 1; 185 } 186 return result; 187 188fail: 189 if (result != NULL) { 190 SAFE_FREE(result); 191 } 192 DEBUG(1, ("tru64_acl_to_smb_acl failed!\n")); 193 return NULL; 194} 195 196static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace, 197 struct smb_acl_entry *smb_ace) 198{ 199 acl_tag_t tru64_tag; 200 acl_permset_t permset; 201 SMB_ACL_TAG_T smb_tag_type; 202 SMB_ACL_PERM_T smb_permset; 203 void *qualifier; 204 205 if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) { 206 DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno))); 207 return False; 208 } 209 210 /* On could set the tag type directly to save a function call, 211 * but I like this better... */ 212 smb_tag_type = tru64_tag_to_smb(tru64_tag); 213 if (smb_tag_type == 0) { 214 DEBUG(3, ("invalid tag type given: %d\n", tru64_tag)); 215 return False; 216 } 217 if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) { 218 DEBUG(3, ("sys_acl_set_tag_type failed: %s\n", 219 strerror(errno))); 220 return False; 221 } 222 qualifier = acl_get_qualifier(tru64_ace); 223 if (qualifier != NULL) { 224 if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) { 225 DEBUG(3, ("sys_acl_set_qualifier failed\n")); 226 return False; 227 } 228 } 229 if (acl_get_permset(tru64_ace, &permset) != 0) { 230 DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno))); 231 return False; 232 } 233 smb_permset = tru64_permset_to_smb(*permset); 234 if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) { 235 DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno))); 236 return False; 237 } 238 return True; 239} 240 241static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl) 242{ 243 acl_t result; 244 acl_entry_t tru64_entry; 245 int i; 246 char *acl_text; 247 ssize_t acl_text_len; 248 249 /* The tru64 acl_init function takes a size_t value 250 * instead of a count of entries (as with posix). 251 * the size parameter "Specifies the size of the working 252 * storage in bytes" (according to the man page). 253 * But it is unclear to me, how this size is to be 254 * calculated. 255 * 256 * It should not matter, since acl_create_entry enlarges 257 * the working storage at need. ... */ 258 259 DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n")); 260 261 result = acl_init(1); 262 263 if (result == NULL) { 264 DEBUG(3, ("acl_init failed!\n")); 265 goto fail; 266 } 267 268 DEBUGADD(10, ("parsing acl entries...\n")); 269 for (i = 0; i < smb_acl->count; i++) { 270 /* XYZ - maybe eliminate this direct access? */ 271 const struct smb_acl_entry *smb_entry = &smb_acl->acl[i]; 272 acl_tag_t tru64_tag; 273 acl_perm_t tru64_permset; 274 275 tru64_tag = smb_tag_to_tru64(smb_entry->a_type); 276 if (tru64_tag == -1) { 277 DEBUG(3, ("smb_tag_to_tru64 failed!\n")); 278 goto fail; 279 } 280 281 if (tru64_tag == ACL_MASK) { 282 DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n")); 283 continue; 284 } 285 286 tru64_entry = acl_create_entry(&result); 287 if (tru64_entry == NULL) { 288 DEBUG(3, ("acl_create_entry failed: %s\n", 289 strerror(errno))); 290 goto fail; 291 } 292 293 if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) { 294 DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n", 295 strerror(errno))); 296 goto fail; 297 } 298 299 switch (smb_entry->a_type) { 300 case SMB_ACL_USER: 301 if (acl_set_qualifier(tru64_entry, 302 (int *)&smb_entry->uid) != 0) 303 { 304 DEBUG(3, ("acl_set_qualifier failed: %s\n", 305 strerror(errno))); 306 goto fail; 307 } 308 DEBUGADD(10, (" - setting uid to %d\n", smb_entry->uid)); 309 break; 310 case SMB_ACL_GROUP: 311 if (acl_set_qualifier(tru64_entry, 312 (int *)&smb_entry->gid) != 0) 313 { 314 DEBUG(3, ("acl_set_qualifier failed: %s\n", 315 strerror(errno))); 316 goto fail; 317 } 318 DEBUGADD(10, (" - setting gid to %d\n", smb_entry->gid)); 319 break; 320 default: 321 break; 322 } 323 324 tru64_permset = smb_permset_to_tru64(smb_entry->a_perm); 325 if (tru64_permset == -1) { 326 DEBUG(3, ("smb_permset_to_tru64 failed!\n")); 327 goto fail; 328 } 329 DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset)); 330 if (acl_set_permset(tru64_entry, &tru64_permset) != 0) 331 { 332 DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno))); 333 goto fail; 334 } 335 } /* for */ 336 DEBUGADD(10, ("done parsing acl entries\n")); 337 338 tru64_entry = NULL; 339 if (acl_valid(result, &tru64_entry) != 0) { 340 DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n", 341 strerror(errno))); 342 if (tru64_entry != NULL) { 343 DEBUGADD(1, ("the acl contains duplicate entries\n")); 344 } 345 goto fail; 346 } 347 DEBUGADD(10, ("acl is valid\n")); 348 349 acl_text = acl_to_text(result, &acl_text_len); 350 if (acl_text == NULL) { 351 DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno))); 352 goto fail; 353 } 354 DEBUG(1, ("acl_text: %s\n", acl_text)); 355 free(acl_text); 356 357 return result; 358 359fail: 360 if (result != NULL) { 361 acl_free(result); 362 } 363 DEBUG(1, ("smb_acl_to_tru64_acl failed!\n")); 364 return NULL; 365} 366 367static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag) 368{ 369 acl_tag_t result; 370 switch (smb_tag) { 371 case SMB_ACL_USER: 372 result = ACL_USER; 373 DEBUGADD(10, ("got acl type ACL_USER\n")); 374 break; 375 case SMB_ACL_USER_OBJ: 376 result = ACL_USER_OBJ; 377 DEBUGADD(10, ("got acl type ACL_USER_OBJ\n")); 378 break; 379 case SMB_ACL_GROUP: 380 result = ACL_GROUP; 381 DEBUGADD(10, ("got acl type ACL_GROUP\n")); 382 break; 383 case SMB_ACL_GROUP_OBJ: 384 result = ACL_GROUP_OBJ; 385 DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n")); 386 break; 387 case SMB_ACL_OTHER: 388 result = ACL_OTHER; 389 DEBUGADD(10, ("got acl type ACL_OTHER\n")); 390 break; 391 case SMB_ACL_MASK: 392 result = ACL_MASK; 393 DEBUGADD(10, ("got acl type ACL_MASK\n")); 394 break; 395 default: 396 DEBUG(1, ("Unknown tag type %d\n", smb_tag)); 397 result = -1; 398 } 399 return result; 400} 401 402 403static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag) 404{ 405 SMB_ACL_TAG_T smb_tag_type; 406 switch(tru64_tag) { 407 case ACL_USER: 408 smb_tag_type = SMB_ACL_USER; 409 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n")); 410 break; 411 case ACL_USER_OBJ: 412 smb_tag_type = SMB_ACL_USER_OBJ; 413 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n")); 414 break; 415 case ACL_GROUP: 416 smb_tag_type = SMB_ACL_GROUP; 417 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n")); 418 break; 419 case ACL_GROUP_OBJ: 420 smb_tag_type = SMB_ACL_GROUP_OBJ; 421 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n")); 422 break; 423 case ACL_OTHER: 424 smb_tag_type = SMB_ACL_OTHER; 425 DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n")); 426 break; 427 case ACL_MASK: 428 smb_tag_type = SMB_ACL_MASK; 429 DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n")); 430 break; 431 default: 432 DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag)); 433 smb_tag_type = 0; 434 } 435 return smb_tag_type; 436} 437 438static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset) 439{ 440 /* originally, I thought that acl_clear_perm was the 441 * proper way to reset the permset to 0. but without 442 * initializing it to 0, acl_clear_perm fails. 443 * so probably, acl_clear_perm is not necessary here... ?! */ 444 acl_perm_t tru64_permset = 0; 445 if (acl_clear_perm(&tru64_permset) != 0) { 446 DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno))); 447 return -1; 448 } 449 /* according to original lib/sysacls.c, acl_add_perm is 450 * broken on tru64 ... */ 451 tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0); 452 tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0); 453 tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0); 454 return tru64_permset; 455} 456 457static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset) 458{ 459 SMB_ACL_PERM_T smb_permset = 0; 460 smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0); 461 smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0); 462 smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0); 463 return smb_permset; 464} 465 466 467/* VFS operations structure */ 468 469static struct vfs_fn_pointers tru64acl_fns = { 470 .sys_acl_get_file = tru64acl_sys_acl_get_file, 471 .sys_acl_get_fd = tru64acl_sys_acl_get_fd, 472 .sys_acl_set_file = tru64acl_sys_acl_set_file, 473 .sys_acl_set_fd = tru64acl_sys_acl_set_fd, 474 .sys_acl_delete_def_file = tru64acl_sys_acl_delete_def_file, 475}; 476 477NTSTATUS vfs_tru64acl_init(void); 478NTSTATUS vfs_tru64acl_init(void) 479{ 480 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl", 481 &tru64acl_fns); 482} 483 484/* ENTE */ 485