1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stddef.h> 27 #include <strings.h> 28 #include <assert.h> 29 30 #include <smbsrv/smb.h> 31 #include <smbsrv/smb_sid.h> 32 #include <smbsrv/smb_idmap.h> 33 34 #define ACE_ALL_TYPES 0x001F 35 36 /* 37 * ACE groups within a DACL 38 * 39 * This is from lower to higher ACE order priority 40 */ 41 #define SMB_AG_START 0 42 #define SMB_AG_ALW_INHRT 0 43 #define SMB_AG_DNY_INHRT 1 44 #define SMB_AG_ALW_DRCT 2 45 #define SMB_AG_DNY_DRCT 3 46 #define SMB_AG_NUM 4 47 48 /* 49 * SID for Everyone group: S-1-1-0. 50 */ 51 smb_sid_t everyone_sid = { 52 NT_SID_REVISION, 53 1, 54 NT_SECURITY_WORLD_AUTH, 55 { 0 } 56 }; 57 58 #define DEFAULT_DACL_ACENUM 2 59 acl_t *acl_alloc(enum acl_type); 60 61 static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *, uid_t, gid_t); 62 static acl_t *smb_fsacl_null_empty(boolean_t); 63 static uint16_t smb_ace_len(smb_ace_t *); 64 static uint32_t smb_ace_mask_g2s(uint32_t); 65 static uint16_t smb_ace_flags_tozfs(uint8_t); 66 static uint8_t smb_ace_flags_fromzfs(uint16_t); 67 68 smb_acl_t * 69 smb_acl_alloc(uint8_t revision, uint16_t bsize, uint16_t acecnt) 70 { 71 smb_acl_t *acl; 72 int size; 73 74 size = sizeof (smb_acl_t) + (acecnt * sizeof (smb_ace_t)); 75 if ((acl = malloc(size)) == NULL) 76 return (NULL); 77 78 acl->sl_revision = revision; 79 acl->sl_bsize = bsize; 80 acl->sl_acecnt = acecnt; 81 acl->sl_aces = (smb_ace_t *)(acl + 1); 82 83 list_create(&acl->sl_sorted, sizeof (smb_ace_t), 84 offsetof(smb_ace_t, se_sln)); 85 return (acl); 86 } 87 88 void 89 smb_acl_free(smb_acl_t *acl) 90 { 91 int i; 92 void *ace; 93 94 if (acl == NULL) 95 return; 96 97 for (i = 0; i < acl->sl_acecnt; i++) 98 smb_sid_free(acl->sl_aces[i].se_sid); 99 100 while ((ace = list_head(&acl->sl_sorted)) != NULL) 101 list_remove(&acl->sl_sorted, ace); 102 list_destroy(&acl->sl_sorted); 103 free(acl); 104 105 } 106 107 /* 108 * smb_acl_len 109 * 110 * Returns the size of given ACL in bytes. Note that this 111 * is not an in-memory size, it's the ACL's size as it would 112 * appear on the wire 113 */ 114 uint16_t 115 smb_acl_len(smb_acl_t *acl) 116 { 117 return ((acl) ? acl->sl_bsize : 0); 118 } 119 120 /*ARGSUSED*/ 121 boolean_t 122 smb_acl_isvalid(smb_acl_t *acl, int which_acl) 123 { 124 if (acl->sl_bsize < SMB_ACL_HDRSIZE) 125 return (B_FALSE); 126 127 if (acl->sl_revision != ACL_REVISION) { 128 /* 129 * we are rejecting ACLs with object-specific ACEs for now 130 */ 131 return (B_FALSE); 132 } 133 134 return (B_TRUE); 135 } 136 137 /* 138 * smb_acl_sort 139 * 140 * Sorts the given ACL in place if it needs to be sorted. 141 * 142 * The following is an excerpt from MSDN website. 143 * 144 * Order of ACEs in a DACL 145 * 146 * For Windows NT versions 4.0 and earlier, the preferred order of ACEs 147 * is simple: In a DACL, all access-denied ACEs should precede any 148 * access-allowed ACEs. 149 * 150 * For Windows 2000 or later, the proper order of ACEs is more complicated 151 * because of the introduction of object-specific ACEs and automatic 152 * inheritance. 153 * 154 * The following describes the preferred order: 155 * 156 * To ensure that noninherited ACEs have precedence over inherited ACEs, 157 * place all noninherited ACEs in a group before any inherited ACEs. This 158 * ordering ensures, for example, that a noninherited access-denied ACE 159 * is enforced regardless of any inherited ACE that allows access. 160 * Within the groups of noninherited ACEs and inherited ACEs, order ACEs 161 * according to ACE type, as the following shows: 162 * . Access-denied ACEs that apply to the object itself 163 * . Access-denied ACEs that apply to a subobject of the 164 * object, such as a property set or property 165 * . Access-allowed ACEs that apply to the object itself 166 * . Access-allowed ACEs that apply to a subobject of the object 167 * 168 * So, here is the desired ACE order 169 * 170 * deny-direct, allow-direct, deny-inherited, allow-inherited 171 * 172 * Of course, not all ACE types are required in an ACL. 173 */ 174 void 175 smb_acl_sort(smb_acl_t *acl) 176 { 177 list_t ace_grps[SMB_AG_NUM]; 178 list_t *alist; 179 smb_ace_t *ace; 180 uint8_t ace_flags; 181 int ag, i; 182 183 assert(acl); 184 185 if (acl->sl_acecnt == 0) { 186 /* 187 * ACL with no entry is a valid ACL and it means 188 * no access for anybody. 189 */ 190 return; 191 } 192 193 for (i = SMB_AG_START; i < SMB_AG_NUM; i++) { 194 list_create(&ace_grps[i], sizeof (smb_ace_t), 195 offsetof(smb_ace_t, se_sln)); 196 } 197 198 for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; ++i, ace++) { 199 ace_flags = ace->se_hdr.se_flags; 200 201 switch (ace->se_hdr.se_type) { 202 case ACCESS_DENIED_ACE_TYPE: 203 ag = (ace_flags & INHERITED_ACE) ? 204 SMB_AG_DNY_INHRT : SMB_AG_DNY_DRCT; 205 break; 206 207 case ACCESS_ALLOWED_ACE_TYPE: 208 ag = (ace_flags & INHERITED_ACE) ? 209 SMB_AG_ALW_INHRT : SMB_AG_ALW_DRCT; 210 break; 211 212 default: 213 /* 214 * This is the lowest priority group so we put 215 * evertything unknown here. 216 */ 217 ag = SMB_AG_ALW_INHRT; 218 break; 219 } 220 221 /* Add the ACE to the selected group */ 222 list_insert_tail(&ace_grps[ag], ace); 223 } 224 225 /* 226 * start with highest priority ACE group and append 227 * the ACEs to the ACL. 228 */ 229 for (i = SMB_AG_NUM - 1; i >= SMB_AG_START; i--) { 230 alist = &ace_grps[i]; 231 while ((ace = list_head(alist)) != NULL) { 232 list_remove(alist, ace); 233 list_insert_tail(&acl->sl_sorted, ace); 234 } 235 list_destroy(alist); 236 } 237 } 238 239 /* 240 * smb_acl_from_zfs 241 * 242 * Converts given ZFS ACL to a Windows ACL. 243 * 244 * A pointer to allocated memory for the Windows ACL will be 245 * returned upon successful conversion. 246 */ 247 smb_acl_t * 248 smb_acl_from_zfs(acl_t *zacl, uid_t uid, gid_t gid) 249 { 250 ace_t *zace; 251 int numaces; 252 smb_acl_t *acl; 253 smb_ace_t *ace; 254 smb_idmap_batch_t sib; 255 smb_idmap_t *sim; 256 idmap_stat idm_stat; 257 258 idm_stat = smb_idmap_batch_create(&sib, zacl->acl_cnt, 259 SMB_IDMAP_ID2SID); 260 if (idm_stat != IDMAP_SUCCESS) 261 return (NULL); 262 263 if (smb_fsacl_getsids(&sib, zacl, uid, gid) != IDMAP_SUCCESS) { 264 smb_idmap_batch_destroy(&sib); 265 return (NULL); 266 } 267 268 acl = smb_acl_alloc(ACL_REVISION, SMB_ACL_HDRSIZE, zacl->acl_cnt); 269 270 sim = sib.sib_maps; 271 for (numaces = 0, zace = zacl->acl_aclp; 272 numaces < zacl->acl_cnt; 273 zace++, numaces++, sim++) { 274 assert(sim->sim_sid); 275 if (sim->sim_sid == NULL) { 276 smb_acl_free(acl); 277 acl = NULL; 278 break; 279 } 280 281 ace = &acl->sl_aces[numaces]; 282 ace->se_hdr.se_type = zace->a_type; 283 ace->se_hdr.se_flags = smb_ace_flags_fromzfs(zace->a_flags); 284 ace->se_mask = zace->a_access_mask; 285 ace->se_sid = smb_sid_dup(sim->sim_sid); 286 ace->se_hdr.se_bsize = smb_ace_len(ace); 287 288 acl->sl_bsize += ace->se_hdr.se_bsize; 289 } 290 291 smb_idmap_batch_destroy(&sib); 292 return (acl); 293 } 294 295 /* 296 * smb_acl_to_zfs 297 * 298 * Converts given Windows ACL to a ZFS ACL. 299 * 300 * fs_acl will contain a pointer to the created ZFS ACL. 301 * The allocated memory should be freed by calling 302 * smb_fsacl_free(). 303 * 304 * Since the output parameter, fs_acl, is allocated in this 305 * function, the caller has to make sure *fs_acl is NULL which 306 * means it's not pointing to any memory. 307 */ 308 uint32_t 309 smb_acl_to_zfs(smb_acl_t *acl, uint32_t flags, int which_acl, acl_t **fs_acl) 310 { 311 smb_ace_t *ace; 312 acl_t *zacl; 313 ace_t *zace; 314 smb_idmap_batch_t sib; 315 smb_idmap_t *sim; 316 idmap_stat idm_stat; 317 int i; 318 319 assert(fs_acl); 320 assert(*fs_acl == NULL); 321 322 if (acl && !smb_acl_isvalid(acl, which_acl)) 323 return (NT_STATUS_INVALID_ACL); 324 325 if ((acl == NULL) || (acl->sl_acecnt == 0)) { 326 if (which_acl == SMB_DACL_SECINFO) { 327 *fs_acl = smb_fsacl_null_empty(acl == NULL); 328 } 329 330 return (NT_STATUS_SUCCESS); 331 } 332 333 idm_stat = smb_idmap_batch_create(&sib, acl->sl_acecnt, 334 SMB_IDMAP_SID2ID); 335 if (idm_stat != IDMAP_SUCCESS) 336 return (NT_STATUS_INTERNAL_ERROR); 337 338 zacl = smb_fsacl_alloc(acl->sl_acecnt, flags); 339 340 zace = zacl->acl_aclp; 341 ace = acl->sl_aces; 342 sim = sib.sib_maps; 343 344 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 345 zace->a_type = ace->se_hdr.se_type & ACE_ALL_TYPES; 346 zace->a_access_mask = smb_ace_mask_g2s(ace->se_mask); 347 zace->a_flags = smb_ace_flags_tozfs(ace->se_hdr.se_flags); 348 349 if (smb_sid_cmp(ace->se_sid, &everyone_sid)) 350 zace->a_flags |= ACE_EVERYONE; 351 else { 352 sim->sim_id = &zace->a_who; 353 idm_stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, 354 ace->se_sid, -1); 355 356 if (idm_stat != IDMAP_SUCCESS) { 357 smb_fsacl_free(zacl); 358 smb_idmap_batch_destroy(&sib); 359 return (NT_STATUS_INTERNAL_ERROR); 360 } 361 } 362 } 363 364 idm_stat = smb_idmap_batch_getmappings(&sib); 365 if (idm_stat != IDMAP_SUCCESS) { 366 smb_fsacl_free(zacl); 367 smb_idmap_batch_destroy(&sib); 368 return (NT_STATUS_NONE_MAPPED); 369 } 370 371 /* 372 * Set the ACEs group flag based on the type of ID returned. 373 */ 374 zace = zacl->acl_aclp; 375 ace = acl->sl_aces; 376 sim = sib.sib_maps; 377 for (i = 0; i < acl->sl_acecnt; i++, zace++, ace++, sim++) { 378 if (zace->a_flags & ACE_EVERYONE) 379 continue; 380 381 if (sim->sim_idtype == SMB_IDMAP_GROUP) 382 zace->a_flags |= ACE_IDENTIFIER_GROUP; 383 } 384 385 smb_idmap_batch_destroy(&sib); 386 387 *fs_acl = zacl; 388 return (NT_STATUS_SUCCESS); 389 } 390 391 /* 392 * smb_fsacl_getsids 393 * 394 * Batch all the uid/gid in given ZFS ACL to get their corresponding SIDs. 395 */ 396 static idmap_stat 397 smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl, uid_t uid, gid_t gid) 398 { 399 ace_t *zace; 400 idmap_stat idm_stat; 401 smb_idmap_t *sim; 402 uid_t id; 403 int i, idtype; 404 405 sim = sib->sib_maps; 406 407 for (i = 0, zace = zacl->acl_aclp; i < zacl->acl_cnt; 408 zace++, i++, sim++) { 409 switch (zace->a_flags & ACE_TYPE_FLAGS) { 410 case ACE_OWNER: 411 id = uid; 412 idtype = SMB_IDMAP_USER; 413 break; 414 415 case (ACE_GROUP | ACE_IDENTIFIER_GROUP): 416 /* owning group */ 417 id = gid; 418 idtype = SMB_IDMAP_GROUP; 419 break; 420 421 case ACE_IDENTIFIER_GROUP: 422 /* regular group */ 423 id = zace->a_who; 424 idtype = SMB_IDMAP_GROUP; 425 break; 426 427 case ACE_EVERYONE: 428 idtype = SMB_IDMAP_EVERYONE; 429 break; 430 431 default: 432 /* user entry */ 433 id = zace->a_who; 434 idtype = SMB_IDMAP_USER; 435 } 436 437 idm_stat = smb_idmap_batch_getsid(sib->sib_idmaph, sim, 438 id, idtype); 439 440 if (idm_stat != IDMAP_SUCCESS) { 441 return (idm_stat); 442 } 443 } 444 445 idm_stat = smb_idmap_batch_getmappings(sib); 446 return (idm_stat); 447 } 448 449 /* 450 * smb_fsacl_null_empty 451 * 452 * NULL DACL means everyone full-access 453 * Empty DACL means everyone full-deny 454 * 455 * ZFS ACL must have at least one entry so smb server has 456 * to simulate the aforementioned expected behavior by adding 457 * an entry in case the requested DACL is null or empty. Adding 458 * a everyone full-deny entry has proved to be problematic in 459 * tests since a deny entry takes precedence over allow entries. 460 * So, instead of adding a everyone full-deny, an owner ACE with 461 * owner implicit permissions will be set. 462 */ 463 static acl_t * 464 smb_fsacl_null_empty(boolean_t null) 465 { 466 acl_t *zacl; 467 ace_t *zace; 468 469 zacl = smb_fsacl_alloc(1, ACL_AUTO_INHERIT); 470 zace = zacl->acl_aclp; 471 472 zace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 473 if (null) { 474 zace->a_access_mask = ACE_ALL_PERMS; 475 zace->a_flags = ACE_EVERYONE; 476 } else { 477 zace->a_access_mask = ACE_READ_ACL | ACE_WRITE_ACL | 478 ACE_READ_ATTRIBUTES; 479 zace->a_flags = ACE_OWNER; 480 } 481 482 return (zacl); 483 } 484 485 /* 486 * FS ACL (acl_t) Functions 487 */ 488 acl_t * 489 smb_fsacl_alloc(int acenum, int flags) 490 { 491 acl_t *acl; 492 493 acl = acl_alloc(ACE_T); 494 acl->acl_cnt = acenum; 495 if ((acl->acl_aclp = malloc(acl->acl_entry_size * acenum)) == NULL) 496 return (NULL); 497 498 acl->acl_flags = flags; 499 return (acl); 500 } 501 502 void 503 smb_fsacl_free(acl_t *acl) 504 { 505 if (acl) 506 acl_free(acl); 507 } 508 509 /* 510 * ACE Functions 511 */ 512 513 /* 514 * smb_ace_len 515 * 516 * Returns the length of the given ACE as it appears in an 517 * ACL on the wire (i.e. a flat buffer which contains the SID) 518 */ 519 static uint16_t 520 smb_ace_len(smb_ace_t *ace) 521 { 522 assert(ace); 523 assert(ace->se_sid); 524 525 if (ace == NULL) 526 return (0); 527 528 return (SMB_ACE_HDRSIZE + sizeof (ace->se_mask) + 529 smb_sid_len(ace->se_sid)); 530 } 531 532 /* 533 * smb_ace_mask_g2s 534 * 535 * Converts generic access bits in the given mask (if any) 536 * to file specific bits. Generic access masks shouldn't be 537 * stored in filesystem ACEs. 538 */ 539 static uint32_t 540 smb_ace_mask_g2s(uint32_t mask) 541 { 542 if (mask & GENERIC_ALL) { 543 mask &= ~(GENERIC_ALL | GENERIC_READ | GENERIC_WRITE 544 | GENERIC_EXECUTE); 545 546 mask |= FILE_ALL_ACCESS; 547 return (mask); 548 } 549 550 if (mask & GENERIC_READ) { 551 mask &= ~GENERIC_READ; 552 mask |= FILE_GENERIC_READ; 553 } 554 555 if (mask & GENERIC_WRITE) { 556 mask &= ~GENERIC_WRITE; 557 mask |= FILE_GENERIC_WRITE; 558 } 559 560 if (mask & GENERIC_EXECUTE) { 561 mask &= ~GENERIC_EXECUTE; 562 mask |= FILE_GENERIC_EXECUTE; 563 } 564 565 return (mask); 566 } 567 568 /* 569 * smb_ace_flags_tozfs 570 * 571 * This function maps the flags which have different values 572 * in Windows and Solaris. The ones with the same value are 573 * transferred untouched. 574 */ 575 static uint16_t 576 smb_ace_flags_tozfs(uint8_t c_flags) 577 { 578 uint16_t z_flags = 0; 579 580 if (c_flags & SUCCESSFUL_ACCESS_ACE_FLAG) 581 z_flags |= ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 582 583 if (c_flags & FAILED_ACCESS_ACE_FLAG) 584 z_flags |= ACE_FAILED_ACCESS_ACE_FLAG; 585 586 if (c_flags & INHERITED_ACE) 587 z_flags |= ACE_INHERITED_ACE; 588 589 z_flags |= (c_flags & ACE_INHERIT_FLAGS); 590 591 return (z_flags); 592 } 593 594 static uint8_t 595 smb_ace_flags_fromzfs(uint16_t z_flags) 596 { 597 uint8_t c_flags; 598 599 c_flags = z_flags & ACE_INHERIT_FLAGS; 600 601 if (z_flags & ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 602 c_flags |= SUCCESSFUL_ACCESS_ACE_FLAG; 603 604 if (z_flags & ACE_FAILED_ACCESS_ACE_FLAG) 605 c_flags |= FAILED_ACCESS_ACE_FLAG; 606 607 if (z_flags & ACE_INHERITED_ACE) 608 c_flags |= INHERITED_ACE; 609 610 return (c_flags); 611 } 612