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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This module provides Security Descriptor handling functions. 30 */ 31 32 #include <smbsrv/smb_incl.h> 33 #include <smbsrv/smb_fsops.h> 34 #include <smbsrv/smb_idmap.h> 35 36 #define AS_DWORD(X) (*(uint32_t *)&(X)) 37 #define SELF_REL(P, M, T) (T *)(((char *)(P)) + AS_DWORD((P)->M)) 38 39 void smb_fmt_sid(char *buf, nt_sid_t *sid); 40 41 void 42 smb_sd_init(smb_sd_t *sd, uint8_t revision) 43 { 44 bzero(sd, sizeof (smb_sd_t)); 45 sd->sd_hdr.sd_revision = revision; 46 } 47 48 /* 49 * smb_sd_term 50 * 51 * Free non-NULL members of 'sd' which has to be in 52 * absolute (pointer) form. 53 */ 54 void 55 smb_sd_term(smb_sd_t *sd) 56 { 57 ASSERT(sd); 58 ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); 59 60 if (sd->sd_owner) 61 MEM_FREE("libnt", sd->sd_owner); 62 63 if (sd->sd_group) 64 MEM_FREE("libnt", sd->sd_group); 65 66 if (sd->sd_dacl) 67 kmem_free(sd->sd_dacl, sd->sd_dacl->sl_size); 68 69 if (sd->sd_sacl) 70 kmem_free(sd->sd_sacl, sd->sd_sacl->sl_size); 71 72 bzero(sd, sizeof (smb_sd_t)); 73 } 74 75 /* 76 * Hmmm. For all of these smb_sd_set_xxx() functions, 77 * what do we do if the affected member is already set? 78 * Should we free() it? For now, punt and risk a memory leak. 79 */ 80 81 void 82 smb_sd_set_owner(smb_sd_t *sd, nt_sid_t *owner, int defaulted) 83 { 84 ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); 85 86 sd->sd_owner = owner; 87 if (defaulted) 88 sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED; 89 else 90 sd->sd_hdr.sd_control &= ~SE_OWNER_DEFAULTED; 91 } 92 93 void 94 smb_sd_set_group(smb_sd_t *sd, nt_sid_t *group, int defaulted) 95 { 96 ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); 97 98 sd->sd_group = group; 99 if (defaulted) 100 sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED; 101 else 102 sd->sd_hdr.sd_control &= ~SE_GROUP_DEFAULTED; 103 } 104 105 void 106 smb_sd_set_dacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags) 107 { 108 ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); 109 110 sd->sd_dacl = acl; 111 112 if (flags & ACL_DEFAULTED) 113 sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED; 114 if (flags & ACL_AUTO_INHERIT) 115 sd->sd_hdr.sd_control |= SE_DACL_AUTO_INHERITED; 116 if (flags & ACL_PROTECTED) 117 sd->sd_hdr.sd_control |= SE_DACL_PROTECTED; 118 119 if (present) 120 sd->sd_hdr.sd_control |= SE_DACL_PRESENT; 121 } 122 123 void 124 smb_sd_set_sacl(smb_sd_t *sd, int present, smb_acl_t *acl, int flags) 125 { 126 ASSERT((sd->sd_hdr.sd_control & SE_SELF_RELATIVE) == 0); 127 128 sd->sd_sacl = acl; 129 130 if (flags & ACL_DEFAULTED) 131 sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED; 132 if (flags & ACL_AUTO_INHERIT) 133 sd->sd_hdr.sd_control |= SE_SACL_AUTO_INHERITED; 134 if (flags & ACL_PROTECTED) 135 sd->sd_hdr.sd_control |= SE_SACL_PROTECTED; 136 137 if (present) 138 sd->sd_hdr.sd_control |= SE_SACL_PRESENT; 139 } 140 141 nt_sid_t * 142 smb_sd_get_owner(void *sd, int *defaulted) 143 { 144 smb_sdbuf_t *sr_sd; 145 smb_sd_hdr_t *sd_hdr; 146 nt_sid_t *sid; 147 148 sd_hdr = (smb_sd_hdr_t *)sd; 149 if (defaulted != NULL) 150 *defaulted = (sd_hdr->sd_control & SE_OWNER_DEFAULTED) ? 1 : 0; 151 152 if (sd_hdr->sd_control & SE_SELF_RELATIVE) { 153 sr_sd = ((smb_sdbuf_t *)sd); 154 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 155 sid = SELF_REL(sr_sd, sd_owner_offs, nt_sid_t); 156 } 157 else 158 sid = ((smb_sd_t *)sd)->sd_owner; 159 160 return (sid); 161 } 162 163 nt_sid_t * 164 smb_sd_get_group(void *sd, int *defaulted) 165 { 166 smb_sdbuf_t *sr_sd; 167 smb_sd_hdr_t *sd_hdr; 168 nt_sid_t *sid; 169 170 sd_hdr = (smb_sd_hdr_t *)sd; 171 if (defaulted != NULL) 172 *defaulted = (sd_hdr->sd_control & SE_GROUP_DEFAULTED) ? 1 : 0; 173 174 if (sd_hdr->sd_control & SE_SELF_RELATIVE) { 175 sr_sd = ((smb_sdbuf_t *)sd); 176 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 177 sid = SELF_REL(sr_sd, sd_group_offs, nt_sid_t); 178 } 179 else 180 sid = ((smb_sd_t *)sd)->sd_group; 181 182 return (sid); 183 } 184 185 smb_acl_t * 186 smb_sd_get_dacl(void *sd, int *present, int *defaulted) 187 { 188 smb_sdbuf_t *sr_sd; 189 smb_sd_hdr_t *sd_hdr; 190 smb_acl_t *acl = NULL; 191 192 sd_hdr = (smb_sd_hdr_t *)sd; 193 if (present != NULL) 194 *present = (sd_hdr->sd_control & SE_DACL_PRESENT) ? 1 : 0; 195 196 if (defaulted != NULL) 197 *defaulted = (sd_hdr->sd_control & SE_DACL_DEFAULTED) ? 1 : 0; 198 199 if (sd_hdr->sd_control & SE_SELF_RELATIVE) { 200 sr_sd = ((smb_sdbuf_t *)sd); 201 if (sr_sd->sd_dacl_offs) { 202 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 203 acl = SELF_REL(sr_sd, sd_dacl_offs, smb_acl_t); 204 } 205 } 206 else 207 acl = ((smb_sd_t *)sd)->sd_dacl; 208 209 return (acl); 210 } 211 212 smb_acl_t * 213 smb_sd_get_sacl(void *sd, int *present, int *defaulted) 214 { 215 smb_sdbuf_t *sr_sd; 216 smb_sd_hdr_t *sd_hdr; 217 smb_acl_t *acl = NULL; 218 219 sd_hdr = (smb_sd_hdr_t *)sd; 220 if (present != NULL) 221 *present = (sd_hdr->sd_control & SE_SACL_PRESENT) ? 1 : 0; 222 223 if (defaulted != NULL) 224 *defaulted = (sd_hdr->sd_control & SE_SACL_DEFAULTED) ? 1 : 0; 225 226 if (sd_hdr->sd_control & SE_SELF_RELATIVE) { 227 sr_sd = ((smb_sdbuf_t *)sd); 228 if (sr_sd->sd_sacl_offs) { 229 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 230 acl = SELF_REL(sr_sd, sd_sacl_offs, smb_acl_t); 231 } 232 } 233 else 234 acl = ((smb_sd_t *)sd)->sd_sacl; 235 236 return (acl); 237 } 238 239 uint32_t 240 smb_sd_len(void *sd, uint32_t secinfo) 241 { 242 uint32_t length = 0; 243 nt_sid_t *sid; 244 smb_acl_t *acl; 245 int present; 246 247 /* SD Header */ 248 length += sizeof (smb_sdbuf_t); 249 250 /* Owner */ 251 if (secinfo & SMB_OWNER_SECINFO) { 252 sid = smb_sd_get_owner(sd, NULL); 253 if (sid) 254 length += nt_sid_length(sid); 255 } 256 257 258 /* Group */ 259 if (secinfo & SMB_GROUP_SECINFO) { 260 sid = smb_sd_get_group(sd, NULL); 261 if (sid) 262 length += nt_sid_length(sid); 263 } 264 265 266 /* DACL */ 267 if (secinfo & SMB_DACL_SECINFO) { 268 acl = smb_sd_get_dacl(sd, &present, NULL); 269 if (present && acl) 270 length += smb_acl_len(acl); 271 } 272 273 /* SACL */ 274 if (secinfo & SMB_SACL_SECINFO) { 275 acl = smb_sd_get_sacl(sd, &present, NULL); 276 if (present && acl) 277 length += smb_acl_len(acl); 278 } 279 280 return (length); 281 } 282 283 /* 284 * smb_sd_get_secinfo 285 * 286 * Return the security information mask for the specified security 287 * descriptor. 288 */ 289 uint32_t 290 smb_sd_get_secinfo(void *sd) 291 { 292 uint32_t sec_info = 0; 293 smb_acl_t *acl; 294 int present; 295 296 if (sd == 0) 297 return (0); 298 299 if (smb_sd_get_owner(sd, NULL) != 0) 300 sec_info |= SMB_OWNER_SECINFO; 301 302 if (smb_sd_get_group(sd, NULL) != 0) 303 sec_info |= SMB_GROUP_SECINFO; 304 305 acl = smb_sd_get_dacl(sd, &present, NULL); 306 if (acl && present) 307 sec_info |= SMB_DACL_SECINFO; 308 309 acl = smb_sd_get_sacl(sd, &present, NULL); 310 if (acl && present) 311 sec_info |= SMB_SACL_SECINFO; 312 313 return (sec_info); 314 } 315 316 /* 317 * smb_sd_abs2selfrel 318 * 319 * This function takes an absolute SD (sd) and make a self relative 320 * SD which will be returned in srel_sd. 321 * 322 * srel_sdsz contains the size of buffer which srel_sd points to. 323 * 324 * Do not add new error codes here without checking the impact on 325 * all callers of this function. 326 * 327 * Returns NT status codes: 328 * NT_STATUS_SUCCESS 329 * NT_STATUS_BUFFER_TOO_SMALL 330 * NT_STATUS_INVALID_SECURITY_DESCR 331 */ 332 static uint32_t 333 smb_sd_abs2selfrel( 334 smb_sd_t *sd, 335 uint32_t secinfo, 336 smb_sdbuf_t *srel_sd, 337 uint32_t srel_sdsz) 338 { 339 uint32_t avail_len = srel_sdsz; 340 uint32_t length = 0; 341 unsigned char *scan_beg = (unsigned char *) srel_sd; 342 unsigned char *scan = scan_beg; 343 unsigned char *scan_end; 344 nt_sid_t *sid; 345 smb_acl_t *acl; 346 int present, defaulted; 347 348 length = smb_sd_len(sd, secinfo); 349 350 if (length == 0) 351 return (NT_STATUS_INVALID_SECURITY_DESCR); 352 353 if (avail_len < length) 354 return (NT_STATUS_BUFFER_TOO_SMALL); 355 356 bzero(srel_sd, length); 357 scan_end = scan_beg + length; 358 359 /* SD Header */ 360 length = sizeof (smb_sdbuf_t); 361 srel_sd->sd_hdr.sd_revision = sd->sd_hdr.sd_revision; 362 srel_sd->sd_hdr.sd_control = SE_SELF_RELATIVE; 363 scan += length; 364 365 if (secinfo & SMB_OWNER_SECINFO) { 366 /* Owner */ 367 sid = smb_sd_get_owner(sd, &defaulted); 368 369 if (defaulted) 370 srel_sd->sd_hdr.sd_control |= SE_OWNER_DEFAULTED; 371 372 if (sid) { 373 /*LINTED E_PTRDIFF_OVERFLOW*/ 374 length = nt_sid_copy((void*)scan, sid, scan_end - scan); 375 if (length == 0) 376 goto fail; 377 /*LINTED E_PTRDIFF_OVERFLOW*/ 378 srel_sd->sd_owner_offs = scan - scan_beg; 379 scan += length; 380 } 381 } 382 383 if (secinfo & SMB_GROUP_SECINFO) { 384 /* Group */ 385 sid = smb_sd_get_group(sd, &defaulted); 386 387 if (defaulted) 388 srel_sd->sd_hdr.sd_control |= SE_GROUP_DEFAULTED; 389 390 if (sid) { 391 /*LINTED E_PTRDIFF_OVERFLOW*/ 392 length = nt_sid_copy((void*)scan, sid, scan_end - scan); 393 if (length == 0) 394 goto fail; 395 /*LINTED E_PTRDIFF_OVERFLOW*/ 396 srel_sd->sd_group_offs = scan - scan_beg; 397 scan += length; 398 } 399 } 400 401 402 if (secinfo & SMB_DACL_SECINFO) { 403 /* Dacl */ 404 acl = smb_sd_get_dacl(sd, &present, &defaulted); 405 406 srel_sd->sd_hdr.sd_control |= 407 (sd->sd_hdr.sd_control & SE_DACL_INHERITANCE_MASK); 408 409 if (defaulted) 410 srel_sd->sd_hdr.sd_control |= SE_DACL_DEFAULTED; 411 412 if (present) 413 srel_sd->sd_hdr.sd_control |= SE_DACL_PRESENT; 414 415 if (present && acl) { 416 /*LINTED E_PTRDIFF_OVERFLOW*/ 417 length = smb_acl_copy(scan_end - scan, 418 (void*) scan, acl); 419 if (length == 0) 420 goto fail; 421 /*LINTED E_PTRDIFF_OVERFLOW*/ 422 srel_sd->sd_dacl_offs = scan - scan_beg; 423 /*LINTED E_PTRDIFF_OVERFLOW*/ 424 acl = (smb_acl_t *)scan; 425 acl->sl_size = (WORD)length; /* set the size */ 426 scan += length; 427 } 428 } 429 430 if (secinfo & SMB_SACL_SECINFO) { 431 /* Sacl */ 432 acl = smb_sd_get_sacl(sd, &present, &defaulted); 433 434 srel_sd->sd_hdr.sd_control |= 435 (sd->sd_hdr.sd_control & SE_SACL_INHERITANCE_MASK); 436 437 if (defaulted) 438 srel_sd->sd_hdr.sd_control |= SE_SACL_DEFAULTED; 439 440 if (present) 441 srel_sd->sd_hdr.sd_control |= SE_SACL_PRESENT; 442 443 if (present && acl) { 444 /*LINTED E_PTRDIFF_OVERFLOW*/ 445 length = smb_acl_copy(scan_end - scan, 446 (void*) scan, acl); 447 if (length == 0) 448 goto fail; 449 /*LINTED E_PTRDIFF_OVERFLOW*/ 450 srel_sd->sd_sacl_offs = scan - scan_beg; 451 /*LINTED E_PTRDIFF_OVERFLOW*/ 452 acl = (smb_acl_t *)scan; 453 acl->sl_size = (WORD)length; /* set the size */ 454 scan += length; 455 } 456 } 457 458 return (NT_STATUS_SUCCESS); 459 460 fail: 461 return (NT_STATUS_INVALID_SECURITY_DESCR); 462 } 463 464 /* 465 * smb_sd_fromfs 466 * 467 * Makes an Windows style security descriptor in absolute form 468 * based on the given filesystem security information. 469 * 470 * Should call smb_sd_term() for the returned sd to free allocated 471 * members. 472 */ 473 static uint32_t 474 smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) 475 { 476 uint32_t status = NT_STATUS_SUCCESS; 477 smb_acl_t *acl = NULL; 478 smb_acl_t *sorted_acl; 479 nt_sid_t *sid; 480 idmap_stat idm_stat; 481 482 ASSERT(fs_sd); 483 ASSERT(sd); 484 485 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 486 487 /* Owner */ 488 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 489 idm_stat = smb_idmap_getsid(fs_sd->sd_uid, 490 SMB_IDMAP_USER, &sid); 491 492 if (idm_stat != IDMAP_SUCCESS) { 493 return (NT_STATUS_NONE_MAPPED); 494 } 495 496 smb_sd_set_owner(sd, sid, 0); 497 } 498 499 /* Group */ 500 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 501 idm_stat = smb_idmap_getsid(fs_sd->sd_gid, 502 SMB_IDMAP_GROUP, &sid); 503 504 if (idm_stat != IDMAP_SUCCESS) { 505 smb_sd_term(sd); 506 return (NT_STATUS_NONE_MAPPED); 507 } 508 509 smb_sd_set_group(sd, sid, 0); 510 } 511 512 /* DACL */ 513 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 514 if (fs_sd->sd_zdacl != NULL) { 515 acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid, 516 fs_sd->sd_gid); 517 if (acl == NULL) { 518 smb_sd_term(sd); 519 return (NT_STATUS_INTERNAL_ERROR); 520 } 521 522 /* 523 * Need to sort the ACL before send it to Windows 524 * clients. Winodws GUI is sensitive about the order 525 * of ACEs. 526 */ 527 sorted_acl = smb_acl_sort(acl); 528 if (sorted_acl && (sorted_acl != acl)) { 529 kmem_free(acl, acl->sl_size); 530 acl = sorted_acl; 531 } 532 smb_sd_set_dacl(sd, 1, acl, fs_sd->sd_zdacl->acl_flags); 533 } else { 534 smb_sd_set_dacl(sd, 0, NULL, 0); 535 } 536 } 537 538 /* SACL */ 539 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 540 if (fs_sd->sd_zsacl != NULL) { 541 acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid, 542 fs_sd->sd_gid); 543 if (acl == NULL) { 544 smb_sd_term(sd); 545 return (NT_STATUS_INTERNAL_ERROR); 546 } 547 548 smb_sd_set_sacl(sd, 1, acl, fs_sd->sd_zsacl->acl_flags); 549 } else { 550 smb_sd_set_sacl(sd, 0, NULL, 0); 551 } 552 } 553 554 return (status); 555 } 556 557 /* 558 * smb_sd_tofs 559 * 560 * Creates a filesystem security structure based on the given 561 * Windows security descriptor. 562 */ 563 uint32_t 564 smb_sd_tofs(smb_sdbuf_t *sr_sd, smb_fssd_t *fs_sd) 565 { 566 nt_sid_t *sid; 567 smb_acl_t *acl; 568 uint32_t status = NT_STATUS_SUCCESS; 569 uint16_t sd_control; 570 idmap_stat idm_stat; 571 int present; 572 int idtype; 573 int flags = 0; 574 575 sd_control = sr_sd->sd_hdr.sd_control; 576 577 /* 578 * ZFS only has one set of flags so for now only 579 * Windows DACL flags are taken into account. 580 */ 581 if (sd_control & SE_DACL_DEFAULTED) 582 flags |= ACL_DEFAULTED; 583 if (sd_control & SE_DACL_AUTO_INHERITED) 584 flags |= ACL_AUTO_INHERIT; 585 if (sd_control & SE_DACL_PROTECTED) 586 flags |= ACL_PROTECTED; 587 588 if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) 589 flags |= ACL_IS_DIR; 590 591 /* Owner */ 592 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 593 sid = smb_sd_get_owner(sr_sd, NULL); 594 if (nt_sid_is_valid(sid) == 0) { 595 return (NT_STATUS_INVALID_SID); 596 } 597 598 idtype = SMB_IDMAP_UNKNOWN; 599 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype); 600 if (idm_stat != IDMAP_SUCCESS) { 601 return (NT_STATUS_NONE_MAPPED); 602 } 603 } 604 605 /* Group */ 606 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 607 sid = smb_sd_get_group(sr_sd, NULL); 608 if (nt_sid_is_valid(sid) == 0) { 609 return (NT_STATUS_INVALID_SID); 610 } 611 612 idtype = SMB_IDMAP_UNKNOWN; 613 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype); 614 if (idm_stat != IDMAP_SUCCESS) { 615 return (NT_STATUS_NONE_MAPPED); 616 } 617 } 618 619 /* DACL */ 620 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 621 acl = smb_sd_get_dacl(sr_sd, &present, NULL); 622 if (present) { 623 status = smb_acl_to_zfs(acl, flags, 624 SMB_DACL_SECINFO, &fs_sd->sd_zdacl); 625 if (status != NT_STATUS_SUCCESS) 626 return (status); 627 } 628 else 629 return (NT_STATUS_INVALID_ACL); 630 } 631 632 /* SACL */ 633 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 634 acl = smb_sd_get_sacl(sr_sd, &present, NULL); 635 if (present) { 636 status = smb_acl_to_zfs(acl, flags, 637 SMB_SACL_SECINFO, &fs_sd->sd_zsacl); 638 if (status != NT_STATUS_SUCCESS) { 639 return (status); 640 } 641 } else { 642 return (NT_STATUS_INVALID_ACL); 643 } 644 } 645 646 return (status); 647 } 648 649 /* 650 * smb_sd_read 651 * 652 * Read uid, gid and ACL from filesystem. The returned ACL from read 653 * routine is always in ZFS format. Convert the ZFS acl to a Win acl 654 * and return the Win SD in relative form. 655 * 656 * NOTE: upon successful return caller MUST free the memory allocated 657 * for the returned SD by calling kmem_free(). The length of the allocated 658 * buffer is returned in 'buflen'. 659 */ 660 uint32_t 661 smb_sd_read(smb_request_t *sr, smb_sdbuf_t **sr_sd, 662 uint32_t secinfo, uint32_t *buflen) 663 { 664 smb_sd_t sd; 665 smb_fssd_t fs_sd; 666 smb_error_t smb_err; 667 smb_sdbuf_t *sdbuf; 668 smb_node_t *node; 669 uint32_t sdlen; 670 uint32_t status = NT_STATUS_SUCCESS; 671 uint32_t sd_flags; 672 int error; 673 674 *sr_sd = NULL; 675 676 node = sr->fid_ofile->f_node; 677 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 678 smb_fsop_sdinit(&fs_sd, secinfo, sd_flags); 679 680 error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); 681 if (error) { 682 smb_errmap_unix2smb(error, &smb_err); 683 return (smb_err.status); 684 } 685 686 status = smb_sd_fromfs(&fs_sd, &sd); 687 smb_fsop_sdterm(&fs_sd); 688 689 if (status != NT_STATUS_SUCCESS) 690 return (status); 691 692 sdlen = smb_sd_len(&sd, secinfo); 693 694 if (*buflen < sdlen) { 695 /* return the required size */ 696 *buflen = sdlen; 697 smb_sd_term(&sd); 698 return (NT_STATUS_BUFFER_TOO_SMALL); 699 } 700 701 sdbuf = kmem_alloc(sdlen, KM_SLEEP); 702 status = smb_sd_abs2selfrel(&sd, secinfo, sdbuf, sdlen); 703 smb_sd_term(&sd); 704 705 if (status == NT_STATUS_SUCCESS) { 706 *sr_sd = sdbuf; 707 *buflen = sdlen; 708 } 709 else 710 kmem_free(sdbuf, sdlen); 711 712 return (status); 713 } 714 715 /* 716 * smb_sd_write 717 * 718 * Takes a Win SD in self-relative form, convert it to 719 * ZFS format and write it to filesystem. The write routine 720 * converts ZFS acl to Posix acl if required. 721 */ 722 uint32_t 723 smb_sd_write(smb_request_t *sr, smb_sdbuf_t *sr_sd, uint32_t secinfo) 724 { 725 smb_node_t *node; 726 smb_fssd_t fs_sd; 727 smb_error_t smb_err; 728 uint32_t status; 729 uint32_t sd_flags; 730 int error; 731 732 node = sr->fid_ofile->f_node; 733 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 734 smb_fsop_sdinit(&fs_sd, secinfo, sd_flags); 735 736 status = smb_sd_tofs(sr_sd, &fs_sd); 737 if (status != NT_STATUS_SUCCESS) { 738 smb_fsop_sdterm(&fs_sd); 739 return (status); 740 } 741 742 error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); 743 smb_fsop_sdterm(&fs_sd); 744 745 if (error) { 746 smb_errmap_unix2smb(error, &smb_err); 747 return (smb_err.status); 748 } 749 750 return (NT_STATUS_SUCCESS); 751 } 752 753 /* 754 * smb_fmt_sid 755 * 756 * Make an string SID and copy the result into the specified buffer. 757 */ 758 void 759 smb_fmt_sid(char *buf, nt_sid_t *sid) 760 { 761 char *sid_str; 762 763 sid_str = nt_sid_format(sid); 764 if (sid_str) { 765 (void) strcpy(buf, sid_str); 766 MEM_FREE("smb", sid_str); 767 } else { 768 (void) strcpy(buf, "<invalid SID>"); 769 } 770 } 771 772 /* 773 * smb_sd_log 774 * 775 * log the given Windows style security descriptor information 776 * in system log. This is for debugging purposes. 777 */ 778 void 779 smb_sd_log(void *sd) 780 { 781 smb_acl_t *acl; 782 smb_ace_t *ace; 783 nt_sid_t *sid; 784 int present, defaulted; 785 char entry[128]; 786 char *inherit; 787 char *type; 788 int ix_dacl; 789 790 sid = smb_sd_get_owner(sd, &defaulted); 791 if (sid) 792 smb_fmt_sid(entry, sid); 793 else 794 (void) strcpy(entry, "NULL"); 795 796 cmn_err(CE_NOTE, " Owner: %s", entry); 797 798 sid = smb_sd_get_group(sd, &defaulted); 799 if (sid) 800 smb_fmt_sid(entry, sid); 801 else 802 (void) strcpy(entry, "NULL"); 803 804 cmn_err(CE_NOTE, " Primary Group: %s", entry); 805 806 acl = smb_sd_get_dacl(sd, &present, &defaulted); 807 808 if (!present || !acl) { 809 cmn_err(CE_NOTE, " No DACL"); 810 return; 811 } 812 813 for (ix_dacl = 0; 814 ace = smb_ace_get(acl, ix_dacl); 815 ix_dacl++) { 816 /* 817 * Make sure the ACE type is something we grok. 818 * All ACE, now and in the future, have a valid 819 * header. Can't access fields passed the Header 820 * until we're sure it's right. 821 */ 822 switch (ace->se_header.se_type) { 823 case ACCESS_ALLOWED_ACE_TYPE: 824 type = "(Allow)"; 825 break; 826 case ACCESS_DENIED_ACE_TYPE: 827 type = "(Deny)"; 828 break; 829 830 case SYSTEM_AUDIT_ACE_TYPE: 831 default: 832 /* Ignore unrecognized/misplaced ACE */ 833 continue; 834 } 835 836 smb_fmt_sid(entry, &ace->se_sid); 837 838 switch (ace->se_header.se_flags & INHERIT_MASK_ACE) { 839 case OBJECT_INHERIT_ACE: 840 inherit = "(OI)"; 841 break; 842 case CONTAINER_INHERIT_ACE: 843 inherit = "(CI)"; 844 break; 845 case INHERIT_ONLY_ACE: 846 inherit = "(IO)"; 847 break; 848 case NO_PROPOGATE_INHERIT_ACE: 849 inherit = "(NP)"; 850 break; 851 default: 852 inherit = ""; 853 } 854 855 (void) snprintf(entry + strlen(entry), sizeof (entry), 856 ":%s 0x%X %s", inherit, ace->se_mask, type); 857 858 cmn_err(CE_NOTE, " %s", entry); 859 } 860 861 cmn_err(CE_NOTE, " %d ACE(s)", ix_dacl); 862 } 863