1/* 2 * Convert AFS acls to NT acls and vice versa. 3 * 4 * Copyright (C) Volker Lendecke, 2003 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 2 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, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21#include "includes.h" 22 23#undef DBGC_CLASS 24#define DBGC_CLASS DBGC_VFS 25 26#include <afs/stds.h> 27#include <afs/afs.h> 28#include <afs/auth.h> 29#include <afs/venus.h> 30#include <afs/prs_fs.h> 31 32#define MAXSIZE 2048 33 34extern const DOM_SID global_sid_World; 35extern const DOM_SID global_sid_Builtin_Administrators; 36extern const DOM_SID global_sid_Builtin_Backup_Operators; 37extern const DOM_SID global_sid_Authenticated_Users; 38extern const DOM_SID global_sid_NULL; 39 40static char space_replacement = '%'; 41 42/* Do we expect SIDs as pts names? */ 43static BOOL sidpts; 44 45extern int afs_syscall(int, char *, int, char *, int); 46 47struct afs_ace { 48 BOOL positive; 49 char *name; 50 DOM_SID sid; 51 enum lsa_SidType type; 52 uint32 rights; 53 struct afs_ace *next; 54}; 55 56struct afs_acl { 57 TALLOC_CTX *ctx; 58 int type; 59 int num_aces; 60 struct afs_ace *acelist; 61}; 62 63struct afs_iob { 64 char *in, *out; 65 uint16 in_size, out_size; 66}; 67 68 69static BOOL init_afs_acl(struct afs_acl *acl) 70{ 71 ZERO_STRUCT(*acl); 72 acl->ctx = talloc_init("afs_acl"); 73 if (acl->ctx == NULL) { 74 DEBUG(10, ("Could not init afs_acl")); 75 return False; 76 } 77 return True; 78} 79 80static void free_afs_acl(struct afs_acl *acl) 81{ 82 if (acl->ctx != NULL) 83 talloc_destroy(acl->ctx); 84 acl->ctx = NULL; 85 acl->num_aces = 0; 86 acl->acelist = NULL; 87} 88 89static struct afs_ace *clone_afs_ace(TALLOC_CTX *mem_ctx, struct afs_ace *ace) 90{ 91 struct afs_ace *result = TALLOC_P(mem_ctx, struct afs_ace); 92 93 if (result == NULL) 94 return NULL; 95 96 *result = *ace; 97 98 result->next = NULL; 99 result->name = talloc_strdup(mem_ctx, ace->name); 100 101 if (result->name == NULL) { 102 return NULL; 103 } 104 105 return result; 106} 107 108static struct afs_ace *new_afs_ace(TALLOC_CTX *mem_ctx, 109 BOOL positive, 110 const char *name, uint32 rights) 111{ 112 DOM_SID sid; 113 enum lsa_SidType type; 114 struct afs_ace *result; 115 116 if (strcmp(name, "system:administrators") == 0) { 117 118 sid_copy(&sid, &global_sid_Builtin_Administrators); 119 type = SID_NAME_ALIAS; 120 121 } else if (strcmp(name, "system:anyuser") == 0) { 122 123 sid_copy(&sid, &global_sid_World); 124 type = SID_NAME_ALIAS; 125 126 } else if (strcmp(name, "system:authuser") == 0) { 127 128 sid_copy(&sid, &global_sid_Authenticated_Users); 129 type = SID_NAME_WKN_GRP; 130 131 } else if (strcmp(name, "system:backup") == 0) { 132 133 sid_copy(&sid, &global_sid_Builtin_Backup_Operators); 134 type = SID_NAME_ALIAS; 135 136 } else if (sidpts) { 137 /* All PTS users/groups are expressed as SIDs */ 138 139 sid_copy(&sid, &global_sid_NULL); 140 type = SID_NAME_UNKNOWN; 141 142 if (string_to_sid(&sid, name)) { 143 const char *user, *domain; 144 /* We have to find the type, look up the SID */ 145 lookup_sid(tmp_talloc_ctx(), &sid, 146 &domain, &user, &type); 147 } 148 149 } else { 150 151 const char *domain, *uname; 152 char *p; 153 154 p = strchr_m(name, *lp_winbind_separator()); 155 if (p != NULL) { 156 *p = '\\'; 157 } 158 159 if (!lookup_name(tmp_talloc_ctx(), name, LOOKUP_NAME_ALL, 160 &domain, &uname, &sid, &type)) { 161 DEBUG(10, ("Could not find AFS user %s\n", name)); 162 163 sid_copy(&sid, &global_sid_NULL); 164 type = SID_NAME_UNKNOWN; 165 166 } 167 } 168 169 result = TALLOC_P(mem_ctx, struct afs_ace); 170 171 if (result == NULL) { 172 DEBUG(0, ("Could not talloc AFS ace\n")); 173 return NULL; 174 } 175 176 result->name = talloc_strdup(mem_ctx, name); 177 if (result->name == NULL) { 178 DEBUG(0, ("Could not talloc AFS ace name\n")); 179 return NULL; 180 } 181 182 result->sid = sid; 183 result->type = type; 184 185 result->positive = positive; 186 result->rights = rights; 187 188 return result; 189} 190 191static void add_afs_ace(struct afs_acl *acl, 192 BOOL positive, 193 const char *name, uint32 rights) 194{ 195 struct afs_ace *ace; 196 197 for (ace = acl->acelist; ace != NULL; ace = ace->next) { 198 if ((ace->positive == positive) && 199 (strequal(ace->name, name))) { 200 ace->rights |= rights; 201 return; 202 } 203 } 204 205 ace = new_afs_ace(acl->ctx, positive, name, rights); 206 207 ace->next = acl->acelist; 208 acl->acelist = ace; 209 210 acl->num_aces += 1; 211 212 DEBUG(10, ("add_afs_ace: Added %s entry for %s with rights %d\n", 213 ace->positive?"positive":"negative", 214 ace->name, ace->rights)); 215 216 return; 217} 218 219/* AFS ACLs in string form are a long string of fields delimited with \n. 220 * 221 * First line: Number of positive entries 222 * Second line: Number of negative entries 223 * Third and following lines: The entries themselves 224 * 225 * An ACE is a line of two fields, delimited by \t. 226 * 227 * First field: Name 228 * Second field: Rights 229 */ 230 231static BOOL parse_afs_acl(struct afs_acl *acl, const char *acl_str) 232{ 233 int nplus, nminus; 234 int aces; 235 236 char str[MAXSIZE+1]; 237 char *p = str; 238 239 strncpy(str, acl_str, MAXSIZE); 240 241 if (sscanf(p, "%d", &nplus) != 1) 242 return False; 243 244 DEBUG(10, ("Found %d positive entries\n", nplus)); 245 246 if ((p = strchr(p, '\n')) == NULL) 247 return False; 248 p += 1; 249 250 if (sscanf(p, "%d", &nminus) != 1) 251 return False; 252 253 DEBUG(10, ("Found %d negative entries\n", nminus)); 254 255 if ((p = strchr(p, '\n')) == NULL) 256 return False; 257 p += 1; 258 259 for (aces = nplus+nminus; aces > 0; aces--) 260 { 261 262 const char *namep; 263 fstring name; 264 uint32 rights; 265 char *space; 266 267 namep = p; 268 269 if ((p = strchr(p, '\t')) == NULL) 270 return False; 271 *p = '\0'; 272 p += 1; 273 274 if (sscanf(p, "%d", &rights) != 1) 275 return False; 276 277 if ((p = strchr(p, '\n')) == NULL) 278 return False; 279 p += 1; 280 281 fstrcpy(name, namep); 282 283 while ((space = strchr_m(name, space_replacement)) != NULL) 284 *space = ' '; 285 286 add_afs_ace(acl, nplus>0, name, rights); 287 288 nplus -= 1; 289 } 290 291 return True; 292} 293 294static BOOL unparse_afs_acl(struct afs_acl *acl, char *acl_str) 295{ 296 /* TODO: String length checks!!!! */ 297 298 int positives = 0; 299 int negatives = 0; 300 fstring line; 301 302 *acl_str = 0; 303 304 struct afs_ace *ace = acl->acelist; 305 306 while (ace != NULL) { 307 if (ace->positive) 308 positives++; 309 else 310 negatives++; 311 ace = ace->next; 312 } 313 314 fstr_sprintf(line, "%d\n", positives); 315 safe_strcat(acl_str, line, MAXSIZE); 316 317 fstr_sprintf(line, "%d\n", negatives); 318 safe_strcat(acl_str, line, MAXSIZE); 319 320 ace = acl->acelist; 321 322 while (ace != NULL) { 323 fstr_sprintf(line, "%s\t%d\n", ace->name, ace->rights); 324 safe_strcat(acl_str, line, MAXSIZE); 325 ace = ace->next; 326 } 327 return True; 328} 329 330static uint32 afs_to_nt_file_rights(uint32 rights) 331{ 332 uint32 result = 0; 333 334 if (rights & PRSFS_READ) 335 result |= FILE_READ_DATA | FILE_READ_EA | 336 FILE_EXECUTE | FILE_READ_ATTRIBUTES | 337 READ_CONTROL_ACCESS | SYNCHRONIZE_ACCESS; 338 339 if (rights & PRSFS_WRITE) 340 result |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | 341 FILE_WRITE_EA | FILE_APPEND_DATA; 342 343 if (rights & PRSFS_LOCK) 344 result |= WRITE_OWNER_ACCESS; 345 346 if (rights & PRSFS_DELETE) 347 result |= DELETE_ACCESS; 348 349 return result; 350} 351 352static void afs_to_nt_dir_rights(uint32 afs_rights, uint32 *nt_rights, 353 uint8 *flag) 354{ 355 *nt_rights = 0; 356 *flag = SEC_ACE_FLAG_OBJECT_INHERIT | 357 SEC_ACE_FLAG_CONTAINER_INHERIT; 358 359 if (afs_rights & PRSFS_INSERT) 360 *nt_rights |= FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY; 361 362 if (afs_rights & PRSFS_LOOKUP) 363 *nt_rights |= FILE_READ_DATA | FILE_READ_EA | 364 FILE_EXECUTE | FILE_READ_ATTRIBUTES | 365 READ_CONTROL_ACCESS | SYNCHRONIZE_ACCESS; 366 367 if (afs_rights & PRSFS_WRITE) 368 *nt_rights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | 369 FILE_APPEND_DATA | FILE_WRITE_EA; 370 371 if ((afs_rights & (PRSFS_INSERT|PRSFS_LOOKUP|PRSFS_DELETE)) == 372 (PRSFS_INSERT|PRSFS_LOOKUP|PRSFS_DELETE)) 373 *nt_rights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | 374 GENERIC_WRITE_ACCESS; 375 376 if (afs_rights & PRSFS_DELETE) 377 *nt_rights |= DELETE_ACCESS; 378 379 if (afs_rights & PRSFS_ADMINISTER) 380 *nt_rights |= FILE_DELETE_CHILD | WRITE_DAC_ACCESS | 381 WRITE_OWNER_ACCESS; 382 383 if ( (afs_rights & PRSFS_LOOKUP) == 384 (afs_rights & (PRSFS_LOOKUP|PRSFS_READ)) ) { 385 /* Only lookup right */ 386 *flag = SEC_ACE_FLAG_CONTAINER_INHERIT; 387 } 388 389 return; 390} 391 392#define AFS_FILE_RIGHTS (PRSFS_READ|PRSFS_WRITE|PRSFS_LOCK) 393#define AFS_DIR_RIGHTS (PRSFS_INSERT|PRSFS_LOOKUP|PRSFS_DELETE|PRSFS_ADMINISTER) 394 395static void split_afs_acl(struct afs_acl *acl, 396 struct afs_acl *dir_acl, 397 struct afs_acl *file_acl) 398{ 399 struct afs_ace *ace; 400 401 init_afs_acl(dir_acl); 402 init_afs_acl(file_acl); 403 404 for (ace = acl->acelist; ace != NULL; ace = ace->next) { 405 if (ace->rights & AFS_FILE_RIGHTS) { 406 add_afs_ace(file_acl, ace->positive, ace->name, 407 ace->rights & AFS_FILE_RIGHTS); 408 } 409 410 if (ace->rights & AFS_DIR_RIGHTS) { 411 add_afs_ace(dir_acl, ace->positive, ace->name, 412 ace->rights & AFS_DIR_RIGHTS); 413 } 414 } 415 return; 416} 417 418static BOOL same_principal(struct afs_ace *x, struct afs_ace *y) 419{ 420 return ( (x->positive == y->positive) && 421 (sid_compare(&x->sid, &y->sid) == 0) ); 422} 423 424static void merge_afs_acls(struct afs_acl *dir_acl, 425 struct afs_acl *file_acl, 426 struct afs_acl *target) 427{ 428 struct afs_ace *ace; 429 430 init_afs_acl(target); 431 432 for (ace = dir_acl->acelist; ace != NULL; ace = ace->next) { 433 struct afs_ace *file_ace; 434 BOOL found = False; 435 436 for (file_ace = file_acl->acelist; 437 file_ace != NULL; 438 file_ace = file_ace->next) { 439 if (!same_principal(ace, file_ace)) 440 continue; 441 442 add_afs_ace(target, ace->positive, ace->name, 443 ace->rights | file_ace->rights); 444 found = True; 445 break; 446 } 447 if (!found) 448 add_afs_ace(target, ace->positive, ace->name, 449 ace->rights); 450 } 451 452 for (ace = file_acl->acelist; ace != NULL; ace = ace->next) { 453 struct afs_ace *dir_ace; 454 BOOL already_seen = False; 455 456 for (dir_ace = dir_acl->acelist; 457 dir_ace != NULL; 458 dir_ace = dir_ace->next) { 459 if (!same_principal(ace, dir_ace)) 460 continue; 461 already_seen = True; 462 break; 463 } 464 if (!already_seen) 465 add_afs_ace(target, ace->positive, ace->name, 466 ace->rights); 467 } 468} 469 470#define PERMS_READ 0x001200a9 471#define PERMS_CHANGE 0x001301bf 472#define PERMS_FULL 0x001f01ff 473 474static struct static_dir_ace_mapping { 475 uint8 type; 476 uint8 flags; 477 uint32 mask; 478 uint32 afs_rights; 479} ace_mappings[] = { 480 481 /* Full control */ 482 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT, 483 PERMS_FULL, 127 /* rlidwka */ }, 484 485 /* Change (write) */ 486 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT, 487 PERMS_CHANGE, 63 /* rlidwk */ }, 488 489 /* Read (including list folder content) */ 490 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT, 491 PERMS_READ, 9 /* rl */ }, 492 493 /* Read without list folder content -- same as "l" */ 494 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT, 495 0x00120089, 8 /* l */ }, 496 497 /* some stupid workaround for preventing fallbacks */ 498 { 0, 0x3, 0x0012019F, 9 /* rl */ }, 499 { 0, 0x13, PERMS_FULL, 127 /* full */ }, 500 501 /* read, delete and execute access plus synchronize */ 502 { 0, 0x3, 0x001300A9, 9 /* should be rdl, set to rl */}, 503 /* classical read list */ 504 { 0, 0x13, 0x001200A9, 9 /* rl */}, 505 /* almost full control, no delete */ 506 { 0, 0x13, PERMS_CHANGE, 63 /* rwidlk */}, 507 508 /* List folder */ 509 { 0, SEC_ACE_FLAG_CONTAINER_INHERIT, 510 PERMS_READ, 8 /* l */ }, 511 512 /* FULL without inheritance -- in all cases here we also get 513 the corresponding INHERIT_ONLY ACE in the same ACL */ 514 { 0, 0, PERMS_FULL, 127 /* rlidwka */ }, 515 516 /* FULL inherit only -- counterpart to previous one */ 517 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY, 518 PERMS_FULL | GENERIC_RIGHT_WRITE_ACCESS, 127 /* rlidwka */ }, 519 520 /* CHANGE without inheritance -- in all cases here we also get 521 the corresponding INHERIT_ONLY ACE in the same ACL */ 522 { 0, 0, PERMS_CHANGE, 63 /* rlidwk */ }, 523 524 /* CHANGE inherit only -- counterpart to previous one */ 525 { 0, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY, 526 PERMS_CHANGE | GENERIC_RIGHT_WRITE_ACCESS, 63 /* rlidwk */ }, 527 528 /* End marker, hopefully there's no afs right 9999 :-) */ 529 { 0, 0, 0, 9999 } 530}; 531 532static uint32 nt_to_afs_dir_rights(const char *filename, const SEC_ACE *ace) 533{ 534 uint32 result = 0; 535 uint32 rights = ace->info.mask; 536 uint8 flags = ace->flags; 537 538 struct static_dir_ace_mapping *m; 539 540 for (m = &ace_mappings[0]; m->afs_rights != 9999; m++) { 541 if ( (ace->type == m->type) && 542 (ace->flags == m->flags) && 543 (ace->info.mask == m->mask) ) 544 return m->afs_rights; 545 } 546 547 DEBUG(1, ("AFSACL FALLBACK: 0x%X 0x%X 0x%X %s %X\n", 548 ace->type, ace->flags, ace->info.mask, filename, rights)); 549 550 if (rights & (GENERIC_ALL_ACCESS|WRITE_DAC_ACCESS)) { 551 result |= PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | 552 PRSFS_LOOKUP | PRSFS_DELETE | PRSFS_LOCK | 553 PRSFS_ADMINISTER; 554 } 555 556 if (rights & (GENERIC_READ_ACCESS|FILE_READ_DATA)) { 557 result |= PRSFS_LOOKUP; 558 if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) { 559 result |= PRSFS_READ; 560 } 561 } 562 563 if (rights & (GENERIC_WRITE_ACCESS|FILE_WRITE_DATA)) { 564 result |= PRSFS_INSERT | PRSFS_DELETE; 565 if (flags & SEC_ACE_FLAG_OBJECT_INHERIT) { 566 result |= PRSFS_WRITE | PRSFS_LOCK; 567 } 568 } 569 570 return result; 571} 572 573static uint32 nt_to_afs_file_rights(const char *filename, const SEC_ACE *ace) 574{ 575 uint32 result = 0; 576 uint32 rights = ace->info.mask; 577 578 if (rights & (GENERIC_READ_ACCESS|FILE_READ_DATA)) { 579 result |= PRSFS_READ; 580 } 581 582 if (rights & (GENERIC_WRITE_ACCESS|FILE_WRITE_DATA)) { 583 result |= PRSFS_WRITE | PRSFS_LOCK; 584 } 585 586 return result; 587} 588 589static size_t afs_to_nt_acl(struct afs_acl *afs_acl, 590 struct files_struct *fsp, 591 uint32 security_info, 592 struct security_descriptor **ppdesc) 593{ 594 SEC_ACE *nt_ace_list; 595 DOM_SID owner_sid, group_sid; 596 SEC_ACCESS mask; 597 SMB_STRUCT_STAT sbuf; 598 SEC_ACL *psa = NULL; 599 int good_aces; 600 size_t sd_size; 601 TALLOC_CTX *mem_ctx = main_loop_talloc_get(); 602 603 struct afs_ace *afs_ace; 604 605 if (fsp->is_directory || fsp->fh->fd == -1) { 606 /* Get the stat struct for the owner info. */ 607 if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { 608 return 0; 609 } 610 } else { 611 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) { 612 return 0; 613 } 614 } 615 616 uid_to_sid(&owner_sid, sbuf.st_uid); 617 gid_to_sid(&group_sid, sbuf.st_gid); 618 619 if (afs_acl->num_aces) { 620 nt_ace_list = TALLOC_ARRAY(mem_ctx, SEC_ACE, afs_acl->num_aces); 621 622 if (nt_ace_list == NULL) 623 return 0; 624 } else { 625 nt_ace_list = NULL; 626 } 627 628 afs_ace = afs_acl->acelist; 629 good_aces = 0; 630 631 while (afs_ace != NULL) { 632 uint32 nt_rights; 633 uint8 flag = SEC_ACE_FLAG_OBJECT_INHERIT | 634 SEC_ACE_FLAG_CONTAINER_INHERIT; 635 636 if (afs_ace->type == SID_NAME_UNKNOWN) { 637 DEBUG(10, ("Ignoring unknown name %s\n", 638 afs_ace->name)); 639 afs_ace = afs_ace->next; 640 continue; 641 } 642 643 if (fsp->is_directory) 644 afs_to_nt_dir_rights(afs_ace->rights, &nt_rights, 645 &flag); 646 else 647 nt_rights = afs_to_nt_file_rights(afs_ace->rights); 648 649 init_sec_access(&mask, nt_rights); 650 init_sec_ace(&nt_ace_list[good_aces++], &(afs_ace->sid), 651 SEC_ACE_TYPE_ACCESS_ALLOWED, mask, flag); 652 afs_ace = afs_ace->next; 653 } 654 655 psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 656 good_aces, nt_ace_list); 657 if (psa == NULL) 658 return 0; 659 660 661 *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, 662 SEC_DESC_SELF_RELATIVE, 663 (security_info & OWNER_SECURITY_INFORMATION) 664 ? &owner_sid : NULL, 665 (security_info & GROUP_SECURITY_INFORMATION) 666 ? &group_sid : NULL, 667 NULL, psa, &sd_size); 668 669 return sd_size; 670} 671 672static BOOL mappable_sid(const DOM_SID *sid) 673{ 674 DOM_SID domain_sid; 675 676 if (sid_compare(sid, &global_sid_Builtin_Administrators) == 0) 677 return True; 678 679 if (sid_compare(sid, &global_sid_World) == 0) 680 return True; 681 682 if (sid_compare(sid, &global_sid_Authenticated_Users) == 0) 683 return True; 684 685 if (sid_compare(sid, &global_sid_Builtin_Backup_Operators) == 0) 686 return True; 687 688 string_to_sid(&domain_sid, "S-1-5-21"); 689 690 if (sid_compare_domain(sid, &domain_sid) == 0) 691 return True; 692 693 return False; 694} 695 696static BOOL nt_to_afs_acl(const char *filename, 697 uint32 security_info_sent, 698 struct security_descriptor *psd, 699 uint32 (*nt_to_afs_rights)(const char *filename, 700 const SEC_ACE *ace), 701 struct afs_acl *afs_acl) 702{ 703 SEC_ACL *dacl; 704 int i; 705 706 /* Currently we *only* look at the dacl */ 707 708 if (((security_info_sent & DACL_SECURITY_INFORMATION) == 0) || 709 (psd->dacl == NULL)) 710 return True; 711 712 if (!init_afs_acl(afs_acl)) 713 return False; 714 715 dacl = psd->dacl; 716 717 for (i = 0; i < dacl->num_aces; i++) { 718 SEC_ACE *ace = &(dacl->ace[i]); 719 const char *dom_name, *name; 720 enum lsa_SidType name_type; 721 char *p; 722 723 if (ace->type != SEC_ACE_TYPE_ACCESS_ALLOWED) { 724 /* First cut: Only positive ACEs */ 725 return False; 726 } 727 728 if (!mappable_sid(&ace->trustee)) { 729 DEBUG(10, ("Ignoring unmappable SID %s\n", 730 sid_string_static(&ace->trustee))); 731 continue; 732 } 733 734 if (sid_compare(&ace->trustee, 735 &global_sid_Builtin_Administrators) == 0) { 736 737 name = "system:administrators"; 738 739 } else if (sid_compare(&ace->trustee, 740 &global_sid_World) == 0) { 741 742 name = "system:anyuser"; 743 744 } else if (sid_compare(&ace->trustee, 745 &global_sid_Authenticated_Users) == 0) { 746 747 name = "system:authuser"; 748 749 } else if (sid_compare(&ace->trustee, 750 &global_sid_Builtin_Backup_Operators) 751 == 0) { 752 753 name = "system:backup"; 754 755 } else { 756 757 if (!lookup_sid(tmp_talloc_ctx(), &ace->trustee, 758 &dom_name, &name, &name_type)) { 759 DEBUG(1, ("AFSACL: Could not lookup SID %s on file %s\n", 760 sid_string_static(&ace->trustee), filename)); 761 continue; 762 } 763 764 if ( (name_type == SID_NAME_USER) || 765 (name_type == SID_NAME_DOM_GRP) || 766 (name_type == SID_NAME_ALIAS) ) { 767 char *tmp; 768 tmp = talloc_asprintf(tmp_talloc_ctx(), "%s%s%s", 769 dom_name, lp_winbind_separator(), 770 name); 771 if (tmp == NULL) { 772 return False; 773 } 774 strlower_m(tmp); 775 name = tmp; 776 } 777 778 if (sidpts) { 779 /* Expect all users/groups in pts as SIDs */ 780 name = talloc_strdup( 781 tmp_talloc_ctx(), 782 sid_string_static(&ace->trustee)); 783 if (name == NULL) { 784 return False; 785 } 786 } 787 } 788 789 while ((p = strchr_m(name, ' ')) != NULL) 790 *p = space_replacement; 791 792 add_afs_ace(afs_acl, True, name, 793 nt_to_afs_rights(filename, ace)); 794 } 795 796 return True; 797} 798 799static BOOL afs_get_afs_acl(char *filename, struct afs_acl *acl) 800{ 801 struct afs_iob iob; 802 803 int ret; 804 805 char space[MAXSIZE]; 806 807 DEBUG(5, ("afs_get_afs_acl: %s\n", filename)); 808 809 iob.in_size = 0; 810 iob.out_size = MAXSIZE; 811 iob.in = iob.out = space; 812 813 ret = afs_syscall(AFSCALL_PIOCTL, filename, VIOCGETAL, 814 (char *)&iob, 0); 815 816 if (ret) { 817 DEBUG(1, ("got error from PIOCTL: %d\n", ret)); 818 return False; 819 } 820 821 if (!init_afs_acl(acl)) 822 return False; 823 824 if (!parse_afs_acl(acl, space)) { 825 DEBUG(1, ("Could not parse AFS acl\n")); 826 free_afs_acl(acl); 827 return False; 828 } 829 830 return True; 831} 832 833static size_t afs_get_nt_acl(struct files_struct *fsp, uint32 security_info, 834 struct security_descriptor **ppdesc) 835{ 836 struct afs_acl acl; 837 size_t sd_size; 838 839 DEBUG(5, ("afs_get_nt_acl: %s\n", fsp->fsp_name)); 840 841 sidpts = lp_parm_bool(SNUM(fsp->conn), "afsacl", "sidpts", False); 842 843 if (!afs_get_afs_acl(fsp->fsp_name, &acl)) { 844 return 0; 845 } 846 847 sd_size = afs_to_nt_acl(&acl, fsp, security_info, ppdesc); 848 849 free_afs_acl(&acl); 850 851 return sd_size; 852} 853 854/* For setting an AFS ACL we have to take care of the ACEs we could 855 * not properly map to SIDs. Merge all of them into the new ACL. */ 856 857static void merge_unknown_aces(struct afs_acl *src, struct afs_acl *dst) 858{ 859 struct afs_ace *ace; 860 861 for (ace = src->acelist; ace != NULL; ace = ace->next) 862 { 863 struct afs_ace *copy; 864 865 if (ace->type != SID_NAME_UNKNOWN) { 866 DEBUG(10, ("Not merging known ACE for %s\n", 867 ace->name)); 868 continue; 869 } 870 871 DEBUG(10, ("Merging unknown ACE for %s\n", ace->name)); 872 873 copy = clone_afs_ace(dst->ctx, ace); 874 875 if (copy == NULL) { 876 DEBUG(0, ("Could not clone ACE for %s\n", ace->name)); 877 continue; 878 } 879 880 copy->next = dst->acelist; 881 dst->acelist = copy; 882 dst->num_aces += 1; 883 } 884} 885 886static BOOL afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, 887 uint32 security_info_sent, 888 struct security_descriptor *psd) 889{ 890 struct afs_acl old_afs_acl, new_afs_acl; 891 struct afs_acl dir_acl, file_acl; 892 char acl_string[2049]; 893 struct afs_iob iob; 894 int ret = -1; 895 pstring name; 896 const char *fileacls; 897 898 fileacls = lp_parm_const_string(SNUM(handle->conn), "afsacl", "fileacls", 899 "yes"); 900 901 sidpts = lp_parm_bool(SNUM(handle->conn), "afsacl", "sidpts", False); 902 903 ZERO_STRUCT(old_afs_acl); 904 ZERO_STRUCT(new_afs_acl); 905 ZERO_STRUCT(dir_acl); 906 ZERO_STRUCT(file_acl); 907 908 pstrcpy(name, fsp->fsp_name); 909 910 if (!fsp->is_directory) { 911 /* We need to get the name of the directory containing the 912 * file, this is where the AFS acls live */ 913 char *p = strrchr(name, '/'); 914 if (p != NULL) { 915 *p = '\0'; 916 } else { 917 pstrcpy(name, "."); 918 } 919 } 920 921 if (!afs_get_afs_acl(name, &old_afs_acl)) { 922 DEBUG(3, ("Could not get old ACL of %s\n", fsp->fsp_name)); 923 goto done; 924 } 925 926 split_afs_acl(&old_afs_acl, &dir_acl, &file_acl); 927 928 if (fsp->is_directory) { 929 930 if (!strequal(fileacls, "yes")) { 931 /* Throw away file acls, we depend on the 932 * inheritance ACEs that also give us file 933 * permissions */ 934 free_afs_acl(&file_acl); 935 } 936 937 free_afs_acl(&dir_acl); 938 if (!nt_to_afs_acl(fsp->fsp_name, security_info_sent, psd, 939 nt_to_afs_dir_rights, &dir_acl)) 940 goto done; 941 } else { 942 if (strequal(fileacls, "no")) { 943 ret = -1; 944 goto done; 945 } 946 947 if (strequal(fileacls, "ignore")) { 948 ret = 0; 949 goto done; 950 } 951 952 free_afs_acl(&file_acl); 953 if (!nt_to_afs_acl(fsp->fsp_name, security_info_sent, psd, 954 nt_to_afs_file_rights, &file_acl)) 955 goto done; 956 } 957 958 merge_afs_acls(&dir_acl, &file_acl, &new_afs_acl); 959 960 merge_unknown_aces(&old_afs_acl, &new_afs_acl); 961 962 unparse_afs_acl(&new_afs_acl, acl_string); 963 964 iob.in = acl_string; 965 iob.in_size = 1+strlen(iob.in); 966 iob.out = NULL; 967 iob.out_size = 0; 968 969 DEBUG(10, ("trying to set acl '%s' on file %s\n", iob.in, name)); 970 971 ret = afs_syscall(AFSCALL_PIOCTL, name, VIOCSETAL, (char *)&iob, 0); 972 973 if (ret != 0) { 974 DEBUG(10, ("VIOCSETAL returned %d\n", ret)); 975 } 976 977 done: 978 free_afs_acl(&dir_acl); 979 free_afs_acl(&file_acl); 980 free_afs_acl(&old_afs_acl); 981 free_afs_acl(&new_afs_acl); 982 983 return (ret == 0); 984} 985 986static size_t afsacl_fget_nt_acl(struct vfs_handle_struct *handle, 987 struct files_struct *fsp, 988 int fd, uint32 security_info, 989 struct security_descriptor **ppdesc) 990{ 991 return afs_get_nt_acl(fsp, security_info, ppdesc); 992} 993static size_t afsacl_get_nt_acl(struct vfs_handle_struct *handle, 994 struct files_struct *fsp, 995 const char *name, uint32 security_info, 996 struct security_descriptor **ppdesc) 997{ 998 return afs_get_nt_acl(fsp, security_info, ppdesc); 999} 1000 1001BOOL afsacl_fset_nt_acl(vfs_handle_struct *handle, 1002 files_struct *fsp, 1003 int fd, uint32 security_info_sent, 1004 SEC_DESC *psd) 1005{ 1006 return afs_set_nt_acl(handle, fsp, security_info_sent, psd); 1007} 1008 1009BOOL afsacl_set_nt_acl(vfs_handle_struct *handle, 1010 files_struct *fsp, 1011 const char *name, uint32 security_info_sent, 1012 SEC_DESC *psd) 1013{ 1014 return afs_set_nt_acl(handle, fsp, security_info_sent, psd); 1015} 1016 1017static int afsacl_connect(vfs_handle_struct *handle, 1018 const char *service, 1019 const char *user) 1020{ 1021 const char *spc; 1022 1023 spc = lp_parm_const_string(SNUM(handle->conn), "afsacl", "space", "%"); 1024 1025 if (spc != NULL) 1026 space_replacement = spc[0]; 1027 1028 return SMB_VFS_NEXT_CONNECT(handle, service, user); 1029} 1030 1031/* VFS operations structure */ 1032 1033static vfs_op_tuple afsacl_ops[] = { 1034 {SMB_VFS_OP(afsacl_connect), SMB_VFS_OP_CONNECT, 1035 SMB_VFS_LAYER_TRANSPARENT}, 1036 {SMB_VFS_OP(afsacl_fget_nt_acl), SMB_VFS_OP_FGET_NT_ACL, 1037 SMB_VFS_LAYER_TRANSPARENT}, 1038 {SMB_VFS_OP(afsacl_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, 1039 SMB_VFS_LAYER_TRANSPARENT}, 1040 {SMB_VFS_OP(afsacl_fset_nt_acl), SMB_VFS_OP_FSET_NT_ACL, 1041 SMB_VFS_LAYER_TRANSPARENT}, 1042 {SMB_VFS_OP(afsacl_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, 1043 SMB_VFS_LAYER_TRANSPARENT}, 1044 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} 1045}; 1046 1047NTSTATUS vfs_afsacl_init(void); 1048NTSTATUS vfs_afsacl_init(void) 1049{ 1050 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "afsacl", 1051 afsacl_ops); 1052} 1053