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