1/* 2 * Copyright (c) 2009 - 2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/mount.h> 25#include <sys/kauth.h> 26#include <sys/syslog.h> 27 28#include <sys/smb_byte_order.h> 29#include <sys/smb_apple.h> 30#include <sys/mchain.h> 31#include <sys/msfscc.h> 32 33#include <netsmb/smb.h> 34#include <netsmb/smb_2.h> 35#include <netsmb/smb_conn.h> 36#include <smbfs/smbfs.h> 37#include <smbfs/smbfs_node.h> 38#include <smbfs/smbfs_subr.h> 39#include <smbfs/smbfs_subr_2.h> 40#include <smbfs/smbfs_security.h> 41#include <smbfs/smb_rq_2.h> 42 43 44#define MAX_SID_PRINTBUFFER 256 /* Used to print out the sid in case of an error */ 45#define DEBUG_ACLS 0 46 47/* 48 * Directory Service generates these UUIDs for SIDs that are unknown. These UUIDs 49 * are used so we can round trip a translation from SID-->UUID-->SID. The first 50 * 12 bytes are well known and allow us to tell if this is a temporary UUID. 51 */ 52static const uint8_t tmpuuid1[12] = { 0xFF, 0xFF, 0xEE, 0xEE, 0xDD, 0xDD, 53 0xCC, 0xCC, 0xBB, 0xBB, 0xAA, 0xAA}; 54static const uint8_t tmpuuid2[12] = { 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCC, 55 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF}; 56 57static const ntsid_t unix_users_domsid = 58{ 1, 1, {0, 0, 0, 0, 0, 22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; 59 60static const ntsid_t unix_groups_domsid = 61{ 1, 1, {0, 0, 0, 0, 0, 22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; 62 63static void * smb_sdoffset(struct ntsecdesc *w_secp, size_t w_seclen, int sd_type); 64 65#define sdowner(s, s_len) (struct ntsid *)smb_sdoffset(s, s_len, OWNER_SECURITY_INFORMATION) 66#define sdgroup(s, s_len) (struct ntsid *)smb_sdoffset(s, s_len, GROUP_SECURITY_INFORMATION) 67#define sdsacl(s, s_len) (struct ntacl *)smb_sdoffset(s, s_len, SACL_SECURITY_INFORMATION) 68#define sddacl(s, s_len) (struct ntacl *)smb_sdoffset(s, s_len, DACL_SECURITY_INFORMATION) 69 70#if DEBUG_ACLS 71static void 72smb_print_guid(guid_t *uuidp) 73{ 74 char *user = NULL; 75 char *group = NULL; 76 uid_t uid = 0; 77 gid_t gid = 0; 78 79 SMB_MALLOC(user, char *, MAXPATHLEN, M_TEMP, M_WAITOK | M_ZERO); 80 if (user == NULL) { 81 SMBERROR("user failed malloc\n"); 82 return; 83 } 84 85 SMB_MALLOC(group, char *, MAXPATHLEN, M_TEMP, M_WAITOK | M_ZERO); 86 if (group == NULL) { 87 SMBERROR("group failed malloc\n"); 88 return; 89 } 90 91 if (is_memberd_tempuuid(uuidp)) { 92 SMBERROR("\tguid: TEMPUUID \n"); 93 } 94 else { 95 SMBERROR("\tguid: 0x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x \n", 96 uuidp->g_guid[0], uuidp->g_guid[1], uuidp->g_guid[2], 97 uuidp->g_guid[3], uuidp->g_guid[4], uuidp->g_guid[5], 98 uuidp->g_guid[6], uuidp->g_guid[7], uuidp->g_guid[8], 99 uuidp->g_guid[9], uuidp->g_guid[10], uuidp->g_guid[11], 100 uuidp->g_guid[12], uuidp->g_guid[13], uuidp->g_guid[14], 101 uuidp->g_guid[15] 102 ); 103 kauth_cred_guid2uid(uuidp, &uid); 104 kauth_cred_guid2gid(uuidp, &gid); 105 kauth_cred_guid2pwnam(uuidp, user); 106 kauth_cred_guid2grnam(uuidp, group); 107 SMBERROR("\tuser/group: %s (%d)/%s (%d) \n", user, uid, group, gid); 108 } 109 110 if (user) { 111 SMB_FREE(user, M_TEMP); 112 } 113 114 if (group) { 115 SMB_FREE(group, M_TEMP); 116 } 117} 118 119 120static void 121smb_print_acl(struct smbnode *np, const char *function, struct kauth_acl *acl) 122{ 123 uint32_t i; 124 char *buffer = NULL; 125 size_t buf_len = MAXPATHLEN * 2; 126 127 SMB_MALLOC(buffer, char *, buf_len, M_TEMP, M_WAITOK | M_ZERO); 128 if (buffer == NULL) { 129 SMBERROR("buffer failed malloc\n"); 130 return; 131 } 132 133 if ((np == NULL) || (acl == NULL)) { 134 SMBERROR("node or acl is null \n"); 135 return; 136 } 137 138 SMBERROR_LOCK(np, "function: %s node %s \n", function, np->n_name); 139 140 SMBERROR("acl_entrycount %d\n", acl->acl_entrycount); 141 142 bzero(buffer, buf_len); 143 if (acl->acl_flags & KAUTH_ACL_DEFER_INHERIT) { 144 strlcat(buffer, "defer_inherit ", buf_len); 145 } 146 if (acl->acl_flags & KAUTH_ACL_NO_INHERIT) { 147 strlcat(buffer, "no_inherit ", buf_len); 148 } 149 SMBERROR("acl_flags 0x%x ( %s) \n", acl->acl_flags, buffer); 150 151 if (acl->acl_entrycount != KAUTH_FILESEC_NOACL) { 152 for (i = 0; i < acl->acl_entrycount; i++) { 153 SMBERROR("ACE: %d \n", i); 154 smb_print_guid(&acl->acl_ace[i].ace_applicable); 155 156 /* Try to print out ace_flags in same order as ls does */ 157 bzero(buffer, MAXPATHLEN); 158 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_INHERITED) { 159 strlcat(buffer, "inherited ", buf_len); 160 } 161 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_FILE_INHERIT) { 162 strlcat(buffer, "file_inherit ", buf_len); 163 } 164 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_DIRECTORY_INHERIT) { 165 strlcat(buffer, "dir_inherit ", buf_len); 166 } 167 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_LIMIT_INHERIT) { 168 strlcat(buffer, "limit_inherit ", buf_len); 169 } 170 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_ONLY_INHERIT) { 171 strlcat(buffer, "only_inherit ", buf_len); 172 } 173 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_SUCCESS) { 174 strlcat(buffer, "success ", buf_len); 175 } 176 if (acl->acl_ace[i].ace_flags & KAUTH_ACE_FAILURE) { 177 strlcat(buffer, "failure ", buf_len); 178 } 179 switch(acl->acl_ace[i].ace_flags & KAUTH_ACE_KINDMASK) { 180 case KAUTH_ACE_PERMIT: 181 strlcat(buffer, "allow ", buf_len); 182 break; 183 case KAUTH_ACE_DENY: 184 strlcat(buffer, "deny ", buf_len); 185 break; 186 case KAUTH_ACE_AUDIT: 187 strlcat(buffer, "audit ", buf_len); 188 break; 189 case KAUTH_ACE_ALARM: 190 strlcat(buffer, "alarm ", buf_len); 191 break; 192 default: 193 strlcat(buffer, "unknown_kind ", buf_len); 194 } 195 196 SMBERROR("\tflags 0x%x ( %s) \n", acl->acl_ace[i].ace_flags, 197 buffer); 198 199 /* Try to print out ace_rights in same order as ls does */ 200 bzero(buffer, buf_len); 201 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_READ_DATA) { 202 strlcat(buffer, "read ", buf_len); 203 } 204 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_WRITE_DATA) { 205 strlcat(buffer, "write ", buf_len); 206 } 207 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_EXECUTE) { 208 strlcat(buffer, "execute ", buf_len); 209 } 210 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_DELETE) { 211 strlcat(buffer, "delete ", buf_len); 212 } 213 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_APPEND_DATA) { 214 strlcat(buffer, "append ", buf_len); 215 } 216 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_DELETE_CHILD) { 217 strlcat(buffer, "delete_child ", buf_len); 218 } 219 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_READ_ATTRIBUTES) { 220 strlcat(buffer, "read_attr ", buf_len); 221 } 222 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_WRITE_ATTRIBUTES) { 223 strlcat(buffer, "write_attr ", buf_len); 224 } 225 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_READ_EXTATTRIBUTES) { 226 strlcat(buffer, "read_ext_attr ", buf_len); 227 } 228 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_WRITE_EXTATTRIBUTES) { 229 strlcat(buffer, "write_ext_attr ", buf_len); 230 } 231 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_READ_SECURITY) { 232 strlcat(buffer, "read_security ", buf_len); 233 } 234 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_WRITE_SECURITY) { 235 strlcat(buffer, "write_security ", buf_len); 236 } 237 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_CHANGE_OWNER) { 238 strlcat(buffer, "change_owner ", buf_len); 239 } 240 if (acl->acl_ace[i].ace_rights & KAUTH_ACE_GENERIC_READ) { 241 strlcat(buffer, "generic_read ", buf_len); 242 } 243 if (acl->acl_ace[i].ace_rights & KAUTH_ACE_GENERIC_WRITE) { 244 strlcat(buffer, "generic_write ", buf_len); 245 } 246 if (acl->acl_ace[i].ace_rights & KAUTH_ACE_GENERIC_EXECUTE) { 247 strlcat(buffer, "generic_execute ", buf_len); 248 } 249 if (acl->acl_ace[i].ace_rights & KAUTH_ACE_GENERIC_ALL) { 250 strlcat(buffer, "generic_all ", buf_len); 251 } 252 if (acl->acl_ace[i].ace_rights & KAUTH_VNODE_SYNCHRONIZE) { 253 strlcat(buffer, "synchronize ", buf_len); 254 } 255 SMBERROR("\trights 0x%x ( %s) \n", acl->acl_ace[i].ace_rights, 256 buffer); 257 } 258 } 259 else { 260 SMBERROR("No ACE's \n"); 261 } 262 263 if (buffer) { 264 SMB_FREE(buffer, M_TEMP); 265 } 266} 267#endif 268 269/* 270 * Check to see if this is a temporary uuid, generated by Directory Service 271 */ 272int 273is_memberd_tempuuid(const guid_t *uuidp) 274{ 275 if ((bcmp(uuidp, tmpuuid1, sizeof(tmpuuid1)) == 0) || 276 (bcmp(uuidp, tmpuuid2, sizeof(tmpuuid2)) == 0)) { 277 return TRUE; 278 } 279 return FALSE; 280} 281 282/* 283 * Free any memory and clear any value used by the acl caching 284 * We have a lock around this routine to make sure no one plays 285 * with these values until we are done. 286 */ 287void 288smbfs_clear_acl_cache(struct smbnode *np) 289{ 290 lck_mtx_lock(&np->f_ACLCacheLock); 291 if (np->acl_cache_data) { 292 SMB_FREE(np->acl_cache_data, M_TEMP); 293 } 294 np->acl_cache_data = NULL; 295 np->acl_cache_timer = 0; 296 np->acl_error = 0; 297 np->acl_cache_len = 0; 298 lck_mtx_unlock(&np->f_ACLCacheLock); 299} 300 301/* 302 * Get a pointer to the offset requested. Verify that the offset is 303 * is in bounds and the structure does not go past the end of the buffer. 304 */ 305static void * 306smb_sdoffset(struct ntsecdesc *w_secp, size_t w_seclen, int sd_type) 307{ 308 void *rt_ptr; 309 int32_t sd_off = 0; 310 int32_t sd_len = 0; 311 int32_t end_len = 0; 312 313 if (sd_type == OWNER_SECURITY_INFORMATION) { 314 sd_len = (int32_t)sizeof(struct ntsid); 315 sd_off = letohl(w_secp->OffsetOwner); 316 } 317 else if (sd_type == GROUP_SECURITY_INFORMATION) { 318 sd_len = (int32_t)sizeof(struct ntsid); 319 sd_off = letohl(w_secp->OffsetGroup); 320 } 321 else if (sd_type == DACL_SECURITY_INFORMATION) { 322 sd_len = (int32_t)sizeof(struct ntacl); 323 sd_off = letohl(w_secp->OffsetDacl); 324 } 325 else if (sd_type == SACL_SECURITY_INFORMATION) { 326 sd_len = (int32_t)sizeof(struct ntacl); 327 sd_off = letohl(w_secp->OffsetSacl); 328 } 329 330 /* Make sure w_seclen is reasonable, once typed cast */ 331 if ((int32_t)w_seclen < 0) 332 return NULL; 333 334 /* Make sure the length is reasonable */ 335 if (sd_len > (int32_t)w_seclen) 336 return NULL; 337 338 /* 339 * Make sure the offset is reasonable. NOTE: We can get a zero offset which 340 * is legal, just means no entry was sent. So we just return a null pointer 341 * since that doesn't cause an error. 342 */ 343 if ((sd_off <= 0) || (sd_off > (int32_t)w_seclen)) 344 return NULL; 345 346 /* Make sure adding them together is reasonable */ 347 end_len = sd_off+sd_len; 348 if ((end_len < 0) || (end_len > (int32_t)w_seclen)) 349 return NULL; 350 351 rt_ptr = sd_off+(uint8_t *)w_secp; 352 353 return rt_ptr; 354} 355 356/* 357 * Used for debugging and writing error messages into the system log. Still 358 * needs to have buffer checking done on it. 359 */ 360static void 361smb_printsid(struct ntsid *sidptr, char *sidendptr, const char *printstr, 362 const char *filename, int index, int error) 363{ 364 char sidprintbuf[MAX_SID_PRINTBUFFER]; 365 char *s = sidprintbuf; 366 int subs; 367 uint64_t auth = 0; 368 unsigned i, *ip; 369 size_t len; 370 uint32_t *subauthptr = (uint32_t *)((char *)sidptr + sizeof(struct ntsid)); 371 char *subauthendptr; 372 373 bzero(sidprintbuf, MAX_SID_PRINTBUFFER); 374 for (i = 0; i < sizeof(sidptr->sid_authority); i++) 375 auth = (auth << 8) | sidptr->sid_authority[i]; 376 s += snprintf(s, MAX_SID_PRINTBUFFER, "S-%u-%llu", sidptr->sid_revision, auth); 377 378 subs = sidptr->sid_subauthcount; 379 if (subs > KAUTH_NTSID_MAX_AUTHORITIES) { 380 SMBERROR("sid_subauthcount > KAUTH_NTSID_MAX_AUTHORITIES : %d\n", subs); 381 subs = KAUTH_NTSID_MAX_AUTHORITIES; 382 } 383 /* 384 * We know that sid_subauthcount has to be less than or equal to 385 * KAUTH_NTSID_MAX_AUTHORITIES which is currently 16. So the highest 386 * this can go is 16 * sizeof(uint32_t) so no overflow problem here. 387 */ 388 subauthendptr = (char *)((char *)subauthptr + (subs * sizeof(uint32_t))); 389 390 if (subauthendptr > sidendptr) { 391 len = MAX_SID_PRINTBUFFER - (s - sidprintbuf); 392 (void)snprintf(s, len, " buffer overflow prevented: %p > %p", 393 subauthendptr, sidendptr); 394 return; 395 } 396 397 for (ip = subauthptr; subs--; ip++) { 398 len = MAX_SID_PRINTBUFFER - (s - sidprintbuf); 399 DBG_ASSERT(len > 0) 400 s += snprintf(s, len, "-%u", *ip); 401 } 402 403 if (error) { 404 SMBWARNING("%s: sid[%d] = %s error = %d %s%s\n", printstr, index, 405 sidprintbuf, error, (filename) ? "for " : "", filename); 406 } else { 407 SMBWARNING("%s: sid[%d] = %s %s%s\n", printstr, index, sidprintbuf, 408 (filename) ? "for " : "", filename); 409 } 410} 411 412static int 413smb_sid_is_equal(const ntsid_t * rhs, const ntsid_t * lhs) 414{ 415 if (rhs->sid_kind != lhs->sid_kind) { 416 return 0; 417 } 418 419 if (rhs->sid_authcount != lhs->sid_authcount) { 420 return 0; 421 } 422 423 if (bcmp(rhs->sid_authority, lhs->sid_authority, 424 sizeof(rhs->sid_authority)) != 0) { 425 return 0; 426 } 427 428 if (bcmp(rhs->sid_authorities, lhs->sid_authorities, 429 sizeof(uint32_t) * rhs->sid_authcount) != 0) { 430 return 0; 431 } 432 return 1; 433} 434 435/* 436 * Return 1 or 0, depending on whether the SID is in the domain given by the 437 * domain SID. 438 */ 439static int 440smb_sid_in_domain(const ntsid_t * domain, const ntsid_t * sid) 441{ 442 ntsid_t tmp = *sid; 443 444 if (tmp.sid_authcount == 0) { 445 SMBDEBUG("Bogus network sid sid_authcount = %d\n", tmp.sid_authcount); 446 return 0; 447 } 448 tmp.sid_authcount -= 1; 449 return smb_sid_is_equal(domain, &tmp); 450} 451 452/* 453 * If a Windows Server 2008 R2 NFS share is configured to enable Unmapped UNIX 454 * User Access and there is no existing mapping available to the NFSserver (via 455 * either [MS-UNMP] or [RFC2307]) then the server will encode the owner, group, 456 * and mode of a file into a security descriptor directly using generated SIDs. 457 * The NFSserver uses a specific sub-authority (SECURITY_NFS_ID_BASE_RID == 0x00000058) 458 * relative to the well known authority "NT Authority" (SECURITY_NT_AUTHORITY == {0,0,0,0,0,5}). 459 * The NFSserver then uses further relative sub-authorities to build SIDs for 460 * different NfsTypes that represent the owner (0x00000001), the group (0x00000002), 461 * and the permissions mask (0x00000003) for the file. A further SID is also 462 * generated, which is used to store the other, or world access mask, within the 463 * security descriptor. 464 * 465 * "<NTSecurityAuthority>-<SECURITY_NFS_ID_BASE_RID>-<NfsSidType>-<NfsSidValue>" 466 * 467 * To construct a complete security descriptor, the NFSserver generates a set 468 * of NFS-specific SIDs based on the UID, GID, and mode bits to be represented: 469 * 470 * Owner SID based on the UID (for example, "S-1-5-88-1-<uid>") 471 * Group SID based on the GID (for example, "S-1-5-88-2-<gid>") 472 * Mode SID based on the UNIX mode bits (for example, "S-1-5-88-3-<mode>") 473 * Other SID, a constant value (for example, "S-1-5-88-4") 474 */ 475static const uint8_t security_nt_authority[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x05}; 476#define SECURITY_NFS_ID_BASE_RID 0x00000058 477enum { 478 NfsSidTypeOwner = 1, 479 NfsSidTypeGroup = 2, 480 NfsSidTypeModes = 3, 481 NfsSidTypeOther = 4 482}; 483 484static Boolean 485WindowsNfsSID(struct smbnode *np, ntsid_t *sidptr) 486{ 487 if ((sidptr->sid_kind == 1) && (sidptr->sid_authcount == 3) && 488 (memcmp(sidptr->sid_authority, security_nt_authority, sizeof(security_nt_authority)) == 0) && 489 (sidptr->sid_authorities[0] == SECURITY_NFS_ID_BASE_RID)) { 490 491 switch (sidptr->sid_authorities[1]) { 492 case NfsSidTypeOwner: 493 SMB_LOG_ACCESS_LOCK(np, "%s has a NfsSidTypeOwner of %d\n", 494 np->n_name, sidptr->sid_authorities[2]); 495 np->n_nfs_uid = sidptr->sid_authorities[2]; 496 break; 497 case NfsSidTypeGroup: 498 SMB_LOG_ACCESS_LOCK(np, "%s has a NfsSidTypeGroup of %d\n", 499 np->n_name, sidptr->sid_authorities[2]); 500 np->n_nfs_gid = sidptr->sid_authorities[2]; 501 break; 502 case NfsSidTypeModes: 503 SMB_LOG_ACCESS_LOCK(np, "%s has a NfsSidTypeModes of O%o\n", 504 np->n_name, sidptr->sid_authorities[2]); 505 np->n_flag |= NHAS_POSIXMODES; 506 np->n_mode &= ~ACCESSPERMS; 507 np->n_mode |= (mode_t)(sidptr->sid_authorities[2] & ACCESSPERMS); 508 break; 509 case NfsSidTypeOther: 510 SMB_LOG_ACCESS_LOCK(np, "%s has a NfsSidTypeOther of O%o\n", 511 np->n_name, sidptr->sid_authorities[2]); 512 break; 513 default: 514 SMB_LOG_ACCESS_LOCK(np, "%s: unknown NfsSidType of 0x%x 0x%x\n", np->n_name, 515 sidptr->sid_authorities[1], sidptr->sid_authorities[2]); 516 break; 517 } 518 return TRUE; 519 } 520 return FALSE; 521} 522 523/* 524 * The calling routine will guarantee that sidptr has enough space to hold the 525 * ntsid structure, but we need to protect ourself from going pass the size 526 * of the ntsid structure and any values contain inside the ntsid structure. 527 * 528 * We no longer need to call smb_sid_endianize before calling this routine. We 529 * now do it place, should help with performance. 530 */ 531static void 532smb_sid2sid16(struct ntsid *sidptr, ntsid_t *sid16ptr, char *sidendptr) 533{ 534 uint8_t ii; 535 uint32_t *subauthptr = (uint32_t *)((char *)sidptr + sizeof(struct ntsid)); 536 char *subauthendptr; 537 538 bzero(sid16ptr, sizeof(*sid16ptr)); 539 if (sidptr->sid_subauthcount > KAUTH_NTSID_MAX_AUTHORITIES) { 540 SMBERROR("sidp->sid_subauthcount count too big: %d\n", 541 sidptr->sid_subauthcount); 542 return; 543 } 544 545 /* 546 * We know that sid_subauthcount has to be less than or equal to 547 * KAUTH_NTSID_MAX_AUTHORITIES which is currently 16. So the highest 548 * this can go is 16 * sizeof(uint32_t) so no overflow problem here. 549 */ 550 subauthendptr = (char *)((char *)subauthptr + 551 (sidptr->sid_subauthcount * sizeof(uint32_t))); 552 if (subauthendptr > sidendptr) { 553 SMBERROR("Too many sid authorities: %p %p\n", subauthendptr, sidendptr); 554 return; 555 } 556 sid16ptr->sid_kind = sidptr->sid_revision; 557 sid16ptr->sid_authcount = sidptr->sid_subauthcount; 558 559 /* Why not just a bcopy? */ 560 for (ii = 0; ii < sizeof(sid16ptr->sid_authority); ii++) 561 sid16ptr->sid_authority[ii] = sidptr->sid_authority[ii]; 562 563 for (ii = 0; ii < sid16ptr->sid_authcount; ii++) { 564 sid16ptr->sid_authorities[ii] = letohl(*subauthptr); 565 subauthptr++; 566 } 567} 568 569/* 570 * The calling routine will guarantee that sidptr has enough space to hold the 571 * ntsid structure, but we need to protect ourself from going pass the size 572 * of the ntsid structure and any values contain inside the ntsid structure. 573 * 574 * Really over kill, but what the heck lets double check that the user land 575 * code didn't send us something bad. 576 */ 577static void 578smb_sid_endianize(struct ntsid *sidptr, size_t len) 579{ 580 char *sidendptr = (char *)sidptr + len; 581 uint32_t *subauthptr = (uint32_t *)((char *)sidptr + sizeof(struct ntsid)); 582 char *subauthendptr; 583 int n; 584 585 /* 586 * We know that sid_subauthcount has to be less than or equal to 587 * KAUTH_NTSID_MAX_AUTHORITIES which is currently 16. So the highest 588 * this can go is 16 * sizeof(uint32_t) so no overflow problem here. 589 */ 590 subauthendptr = (char *)((char *)subauthptr + 591 (sidptr->sid_subauthcount * sizeof(uint32_t))); 592 if (subauthendptr > sidendptr) { 593 SMBERROR("Too many sid authorities: %p %p\n", subauthendptr, sidendptr); 594 return; 595 } 596 597 n = sidptr->sid_subauthcount; 598 while (n--) { 599 *subauthptr = letohl(*subauthptr); 600 subauthptr++; 601 } 602} 603 604/* 605 * This is the main routine that goes across the network to get our acl 606 * information. We now always ask for everything so we can make less calls. If 607 * the cache data is up to date then we will return that information. We also do 608 * negative caching, if the server returns an error we cache that fact and 609 * continue to return the error until the cache information times out. 610 * 611 * Remember that the vfs will help us with caching, but not in the negative case. 612 * Also it does not solve the problem of multiple different calls coming into us 613 * back to back. So in a typical case we will get the following calls and they 614 * will require an acl lookup for each item. 615 * 616 * UID and GID request 617 * Do we have write access 618 * Do we have read access 619 * Do we have search/excute access 620 * 621 * So by caching we are removing 12 network calls for each file in a directory. 622 * We only hold on to this cache for a very short time, because it has a memory 623 * cost that we don't want to pay for any real length of time. This is ok, becasue 624 * one we go through this process the vfs layer will handle the longer caching of 625 * these request. 626 */ 627static int 628smbfs_update_acl_cache(struct smb_share *share, struct smbnode *np, 629 vfs_context_t context, struct ntsecdesc **w_sec, 630 size_t *seclen) 631{ 632 uint32_t selector = OWNER_SECURITY_INFORMATION | 633 GROUP_SECURITY_INFORMATION | 634 DACL_SECURITY_INFORMATION; 635 SMBFID fid = 0; 636 struct timespec ts; 637 struct ntsecdesc *acl_cache_data = NULL; 638 size_t acl_cache_len = 0; 639 int error = 0; 640 time_t attrtimeo; 641 int use_cached_data = 0; 642 643 /* If we are in reconnect, use cached data if we have it */ 644 if (np->acl_cache_timer != 0) { 645 use_cached_data = (share->ss_flags & SMBS_RECONNECTING); 646 } 647 648 /* Check to see if the cache has timed out */ 649 SMB_CACHE_TIME(ts, np, attrtimeo); 650 if (((ts.tv_sec - np->acl_cache_timer) <= attrtimeo) || 651 use_cached_data) { 652 /* Ok the cache is still good take a lock and retrieve the data */ 653 lck_mtx_lock(&np->f_ACLCacheLock); 654 655 SMB_CACHE_TIME(ts, np, attrtimeo); 656 if (((ts.tv_sec - np->acl_cache_timer) <= attrtimeo) || 657 use_cached_data) { 658 /* We have the lock and the cache is still good, use the cached ACL */ 659 goto done; 660 } 661 else { 662 /* 663 * Cache expired while we were waiting on the lock, release the lock 664 * and get the ACL from the network. 665 */ 666 lck_mtx_unlock(&np->f_ACLCacheLock); 667 } 668 } 669 670 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 671 /* Only open file if its SMB 1 */ 672 error = smbfs_tmpopen(share, np, SMB2_READ_CONTROL, &fid, context); 673 } 674 675 if (error == 0) { 676 int cerror; 677 678 error = smbfs_smb_getsec(share, np, SMB2_READ_CONTROL | SMB2_SYNCHRONIZE, fid, selector, 679 (struct ntsecdesc **)&acl_cache_data, 680 &acl_cache_len, context); 681 682 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 683 /* Only close file if its SMB 1 */ 684 cerror = smbfs_tmpclose(share, np, fid, context); 685 if (cerror) { 686 SMBWARNING_LOCK(np, "error %d closing fid %llx file %s\n", 687 cerror, fid, np->n_name); 688 } 689 } 690 691 if ((error == 0) && (acl_cache_data == NULL)) 692 error = EBADRPC; 693 } 694 695 /* Don't let anyone play with the acl cache until we are done */ 696 lck_mtx_lock(&np->f_ACLCacheLock); 697 698 if ((error == ETIMEDOUT) && (np->acl_cache_timer != 0)) { 699 /* Just return the cached data */ 700 error = 0; 701 np->acl_error = error; 702 goto done; 703 } 704 705 /* Free the old data no longer needed */ 706 if (np->acl_cache_data) 707 SMB_FREE(np->acl_cache_data, M_TEMP); 708 709 np->acl_cache_data = acl_cache_data; 710 np->acl_cache_len = acl_cache_len; 711 np->acl_error = error; 712 713 /* We have new information reset our timer */ 714 np->acl_cache_timer = ts.tv_sec; 715 716done: 717 if (np->acl_error || (np->acl_cache_data == NULL)) { 718 *w_sec = NULL; 719 *seclen = 0; 720 if (np->acl_error == 0) 721 np->acl_error = EBADRPC; /* Should never happen, but just to be safe */ 722 } else { 723 SMB_MALLOC(*w_sec, struct ntsecdesc *, np->acl_cache_len, M_TEMP, M_WAITOK); 724 if (*w_sec) { 725 *seclen = np->acl_cache_len; 726 bcopy(np->acl_cache_data, *w_sec, np->acl_cache_len); 727 } else { 728 *w_sec = np->acl_cache_data; 729 *seclen = np->acl_cache_len; 730 np->acl_cache_data = NULL; 731 np->acl_cache_len = 0; 732 np->acl_cache_timer = 0; 733 } 734 } 735 error = np->acl_error; 736 lck_mtx_unlock(&np->f_ACLCacheLock); 737 return error; 738} 739 740/* 741 * Universal routine for getting the UUID/GUID and setting the nodes 742 * uid/gid. We will get the nodes UUID and set its uid if the owner flag 743 * is set, otherwise we get the nodes GUID and set its gid. 744 */ 745static void 746smbfs_set_node_identifier(struct smbnode *np, struct ntsecdesc *w_sec, 747 size_t seclen, guid_t *unique_identifier, int owner) 748{ 749 struct smbmount *smp = np->n_mount; 750 struct ntsid *w_sidp = NULL; 751 ntsid_t sid; 752 uid_t *node_identifier; 753 int error; 754 755 if (owner) { 756 if (w_sec) /* Getting the security descriptor failed */ 757 w_sidp = sdowner(w_sec, seclen); 758 node_identifier = &np->n_uid; 759 } else { 760 if (w_sec) /* Getting the security descriptor failed */ 761 w_sidp = sdgroup(w_sec, seclen); 762 node_identifier = &np->n_gid; 763 } 764 765 if (!w_sidp || !w_sec) { 766 SMB_LOG_ACCESS_LOCK(np, "no %s sid received, file %s\n", 767 (owner) ? "user" : "group", np->n_name); 768 goto error_out; 769 } 770 771 smb_sid2sid16(w_sidp, &sid, (char*)w_sec+seclen); 772 /* We are mapping the owner id, so if its a match replace it with the local id */ 773 if (owner && (smp->sm_flags & MNT_MAPS_NETWORK_LOCAL_USER) && 774 (bcmp(&smp->ntwrk_sids[0], &sid, sizeof(sid)) == 0)) { 775 *unique_identifier = smp->sm_args.uuid; 776 *node_identifier = smp->sm_args.uid; 777 return; /* We are done */ 778 } 779 780 error = kauth_cred_ntsid2guid(&sid, unique_identifier); 781 if (error) { 782 if (smbfs_loglevel == SMB_ACL_LOG_LEVEL) { 783 lck_rw_lock_shared(&np->n_name_rwlock); 784 smb_printsid(w_sidp, (char*)w_sec+seclen, "Owner/Group lookup failed", 785 (const char *)np->n_name, 0, error); 786 lck_rw_unlock_shared(&np->n_name_rwlock); 787 } 788 goto error_out; 789 } 790 791 /* 792 * This is a cheap call since we lookup the uuid/guid above, so the kernel 793 * will have the uid or gid in its cache. If we get a temp gid/uid and we 794 * already have a uid/gid always use the one we already have. 795 */ 796 if (is_memberd_tempuuid(unique_identifier) && 797 (*node_identifier != KAUTH_UID_NONE)) { 798 return; /* We already have a real uid/gid from the server keep using it */ 799 } 800 801 if (owner) 802 error = kauth_cred_ntsid2uid(&sid, node_identifier); 803 else 804 error = kauth_cred_ntsid2gid(&sid, node_identifier); 805 if (error == 0) 806 return; /* We are done */ 807 808error_out: 809 /* Not sure what else to do here, so we default to the mounted users uid/gid */ 810 if (*node_identifier == KAUTH_UID_NONE) 811 *node_identifier = (owner) ? smp->sm_args.uid : smp->sm_args.gid; 812 /* Something bad happen and we didn't get the UUID/GUID */ 813 if (kauth_guid_equal(unique_identifier, &kauth_null_guid)) { 814 /* At this point we have a uid/gid, so use it to get the UUID/GUID */ 815 if (owner) 816 error = kauth_cred_uid2guid(*node_identifier, unique_identifier); 817 else 818 error = kauth_cred_gid2guid(*node_identifier, unique_identifier); 819 /* Should never error out in the case, but just in case lets log it */ 820 if (error) { 821 SMB_LOG_ACCESS_LOCK(np, "%s couldn't translate the uid/gid %d to a UUID/GUID, error = %d\n", 822 np->n_name, *node_identifier, error); 823 } 824 } 825} 826 827/* 828 * This routine will retrieve the owner, group and any ACLs associate with 829 * this node. We treat an access error the same as an empty security descriptor. 830 * 831 * The calling routine must hold a reference on the share 832 * 833 */ 834int 835smbfs_getsecurity(struct smb_share *share, struct smbnode *np, 836 struct vnode_attr *vap, vfs_context_t context) 837{ 838 struct smbmount *smp = np->n_mount; 839 int error; 840 struct ntsecdesc *w_sec; /* Wire sec descriptor */ 841 size_t seclen = 0; 842 kauth_acl_t res = NULL; /* acl result buffer */ 843 844 /* We do not support acl access on a stream node */ 845 if (vnode_isnamedstream(np->n_vnode)) 846 return EINVAL; 847 848 SMB_LOG_KTRACE(SMB_DBG_SMBFS_GET_SEC | DBG_FUNC_START, 0, 0, 0, 0, 0); 849 850 if (VATTR_IS_ACTIVE(vap, va_acl)) 851 vap->va_acl = NULL; /* default */ 852 853 if (VATTR_IS_ACTIVE(vap, va_guuid)) 854 vap->va_guuid = kauth_null_guid; /* default */ 855 856 if (VATTR_IS_ACTIVE(vap, va_uuuid)) 857 vap->va_uuuid = kauth_null_guid; /* default */ 858 859 /* Check to make sure we have current acl information */ 860 error = smbfs_update_acl_cache(share, np, context, &w_sec, &seclen); 861 if (error) { 862 if (w_sec) 863 SMB_FREE(w_sec, M_TEMP); 864 w_sec = NULL; 865 /* 866 * When should we eat the error and when shouldn't we, that is the 867 * real question? Any error here will fail the copy engine. Not sure 868 * thats what we really want. We currently only ignore an access error, 869 * but in the future we may want return all errors or none. The old 870 * code ignored all errors, now we only ignore EACCES. 871 */ 872 if (error == EACCES) { 873 error = 0; 874 } 875 else { 876 SMB_LOG_ACCESS_LOCK(np, "smbfs_update_acl_cache of %s failed with error = %d\n", 877 np->n_name, error); 878 } 879 } 880 881 /* 882 * The smbfs_set_node_identifier routine will check to see if w_sec 883 * is null. If null it will do what is need to return the correct 884 * values. 885 * 886 * smbfs_set_node_identifier will set the np->n_uid/n_gid based on the 887 * ACL values returned by the server 888 */ 889 if (VATTR_IS_ACTIVE(vap, va_guuid)) { 890 smbfs_set_node_identifier(np, w_sec, seclen, &vap->va_guuid, FALSE); 891 } 892 if (VATTR_IS_ACTIVE(vap, va_uuuid)) { 893 smbfs_set_node_identifier(np, w_sec, seclen, &vap->va_uuuid, TRUE); 894 } 895 896 if (VATTR_IS_ACTIVE(vap, va_acl)) { 897 struct ntacl *w_dacl = NULL; 898 char *endptr; 899 uint32_t acecount, j, aflags; 900 struct ntsid *w_sidp; /* Wire SID */ 901 struct ntace *w_acep = NULL; /* Wire ACE */ 902 kauth_ace_rights_t arights; 903 uint32_t w_rights; 904 ntsid_t sid; /* temporary, for a kauth sid */ 905 906 if (w_sec) 907 w_dacl = sddacl(w_sec, seclen); 908 if (!w_dacl || !w_sec) 909 goto exit; 910 /* Is there anything we can do to verify acecount, just not sure */ 911 acecount = letohs(w_dacl->acl_acecount); 912 res = kauth_acl_alloc(acecount); 913 if (!res) { 914 error = ENOMEM; 915 goto exit; 916 } 917 /* Only count entries we add to the array, don't count dropped entries */ 918 res->acl_entrycount = 0; 919 res->acl_flags = letohs(w_sec->ControlFlags); 920 if (res->acl_flags & SE_DACL_PROTECTED) 921 res->acl_flags |= KAUTH_FILESEC_NO_INHERIT; 922 else 923 res->acl_flags &= ~KAUTH_FILESEC_NO_INHERIT; 924 925 endptr = (char *)w_sec+seclen; 926 927 for (j = 0, w_acep = aclace(w_dacl); (((char *)acesid(w_acep) < endptr) && 928 (j < acecount)); j++, w_acep = aceace(w_acep)) { 929 int warn_error = 0; 930 931 switch(acetype(w_acep)) { 932 case ACCESS_ALLOWED_ACE_TYPE: 933 aflags = KAUTH_ACE_PERMIT; 934 break; 935 case ACCESS_DENIED_ACE_TYPE: 936 aflags = KAUTH_ACE_DENY; 937 break; 938 case SYSTEM_AUDIT_ACE_TYPE: 939 aflags = KAUTH_ACE_AUDIT; 940 break; 941 case SYSTEM_ALARM_ACE_TYPE: 942 aflags = KAUTH_ACE_ALARM; 943 break; 944 default: 945 SMBERROR_LOCK(np, "ACE type %d file(%s)\n", acetype(w_acep), np->n_name); 946 error = EPROTO; /* Should it be EIO */ 947 goto exit; 948 } 949 w_sidp = acesid(w_acep); 950 if ((char *)w_sidp+sizeof(*w_sidp) > endptr) { 951 SMBERROR_LOCK(np, "ACE type %d file(%s) would have caused a buffer overrun!\n", 952 acetype(w_acep), np->n_name); 953 954 error = EPROTO; /* Should it be EIO */ 955 goto exit; 956 } 957 smb_sid2sid16(w_sidp, &sid, (char*)w_sec+seclen); 958 if (WindowsNfsSID(np, &sid)) { 959 continue; 960 } 961 if ((smp->sm_flags & MNT_MAPS_NETWORK_LOCAL_USER) && 962 (bcmp(&smp->ntwrk_sids[0], &sid, sizeof(sid)) == 0)) { 963 res->acl_ace[res->acl_entrycount].ace_applicable = smp->sm_args.uuid; 964 } else { 965 warn_error = kauth_cred_ntsid2guid(&sid, &res->acl_ace[res->acl_entrycount].ace_applicable); 966 } 967 if (warn_error) { 968 if (smbfs_loglevel == SMB_ACL_LOG_LEVEL) { 969 lck_rw_lock_shared(&np->n_name_rwlock); 970 smb_printsid(w_sidp, (char*)w_sec+seclen, "ACL lookup failed", 971 (const char *)np->n_name, j, warn_error); 972 lck_rw_unlock_shared(&np->n_name_rwlock); 973 } 974 continue; 975 } 976#if DEBUG_ACLS 977 else { 978 lck_rw_lock_shared(&np->n_name_rwlock); 979 smb_printsid(w_sidp, (char*)w_sec+seclen, "sid maps to", 980 (const char *)np->n_name, j, 0); 981 lck_rw_unlock_shared(&np->n_name_rwlock); 982 smb_print_guid(&res->acl_ace[res->acl_entrycount].ace_applicable); 983 } 984#endif 985 986 if (aceflags(w_acep) & OBJECT_INHERIT_ACE_FLAG) 987 aflags |= KAUTH_ACE_FILE_INHERIT; 988 if (aceflags(w_acep) & CONTAINER_INHERIT_ACE_FLAG) 989 aflags |= KAUTH_ACE_DIRECTORY_INHERIT; 990 if (aceflags(w_acep) & NO_PROPAGATE_INHERIT_ACE_FLAG) 991 aflags |= KAUTH_ACE_LIMIT_INHERIT; 992 if (aceflags(w_acep) & INHERIT_ONLY_ACE_FLAG) 993 aflags |= KAUTH_ACE_ONLY_INHERIT; 994 if (aceflags(w_acep) & INHERITED_ACE_FLAG) 995 aflags |= KAUTH_ACE_INHERITED; 996 if (aceflags(w_acep) & UNDEF_ACE_FLAG) { 997 SMBERROR_LOCK(np, "unknown ACE flag on file(%s)\n", np->n_name); 998 } 999 if (aceflags(w_acep) & SUCCESSFUL_ACCESS_ACE_FLAG) 1000 aflags |= KAUTH_ACE_SUCCESS; 1001 if (aceflags(w_acep) & FAILED_ACCESS_ACE_FLAG) 1002 aflags |= KAUTH_ACE_FAILURE; 1003 res->acl_ace[res->acl_entrycount].ace_flags = aflags; 1004 1005 w_rights = acerights(w_acep); 1006 arights = 0; 1007 if (w_rights & SMB2_GENERIC_READ) 1008 arights |= KAUTH_ACE_GENERIC_READ; 1009 if (w_rights & SMB2_GENERIC_WRITE) 1010 arights |= KAUTH_ACE_GENERIC_WRITE; 1011 if (w_rights & SMB2_GENERIC_EXECUTE) 1012 arights |= KAUTH_ACE_GENERIC_EXECUTE; 1013 if (w_rights & SMB2_GENERIC_ALL) 1014 arights |= KAUTH_ACE_GENERIC_ALL; 1015 if (w_rights & SMB2_SYNCHRONIZE) 1016 arights |= KAUTH_VNODE_SYNCHRONIZE; 1017 if (w_rights & SMB2_WRITE_OWNER) 1018 arights |= KAUTH_VNODE_CHANGE_OWNER; 1019 if (w_rights & SMB2_WRITE_DAC) 1020 arights |= KAUTH_VNODE_WRITE_SECURITY; 1021 if (w_rights & SMB2_READ_CONTROL) 1022 arights |= KAUTH_VNODE_READ_SECURITY; 1023 if (w_rights & SMB2_DELETE) 1024 arights |= KAUTH_VNODE_DELETE; 1025 1026 if (w_rights & SMB2_FILE_WRITE_ATTRIBUTES) 1027 arights |= KAUTH_VNODE_WRITE_ATTRIBUTES; 1028 if (w_rights & SMB2_FILE_READ_ATTRIBUTES) 1029 arights |= KAUTH_VNODE_READ_ATTRIBUTES; 1030 if (w_rights & SMB2_FILE_DELETE_CHILD) 1031 arights |= KAUTH_VNODE_DELETE_CHILD; 1032 if (w_rights & SMB2_FILE_EXECUTE) 1033 arights |= KAUTH_VNODE_EXECUTE; 1034 if (w_rights & SMB2_FILE_WRITE_EA) 1035 arights |= KAUTH_VNODE_WRITE_EXTATTRIBUTES; 1036 if (w_rights & SMB2_FILE_READ_EA) 1037 arights |= KAUTH_VNODE_READ_EXTATTRIBUTES; 1038 if (w_rights & SMB2_FILE_APPEND_DATA) 1039 arights |= KAUTH_VNODE_APPEND_DATA; 1040 if (w_rights & SMB2_FILE_WRITE_DATA) 1041 arights |= KAUTH_VNODE_WRITE_DATA; 1042 if (w_rights & SMB2_FILE_READ_DATA) 1043 arights |= KAUTH_VNODE_READ_DATA; 1044 res->acl_ace[res->acl_entrycount].ace_rights = arights; 1045 1046 /* Success we have an entry, now count it */ 1047 res->acl_entrycount++; 1048 } 1049#if DEBUG_ACLS 1050 smb_print_acl(np, "smbfs_getsecurity", res); 1051#endif 1052 1053 /* Only return the acl if we have at least one ace. */ 1054 if (res->acl_entrycount) { 1055 vap->va_acl = res; 1056 res = NULL; 1057 } 1058 } 1059 1060exit: 1061 if (VATTR_IS_ACTIVE(vap, va_acl)) 1062 VATTR_SET_SUPPORTED(vap, va_acl); 1063 if (VATTR_IS_ACTIVE(vap, va_guuid)) 1064 VATTR_SET_SUPPORTED(vap, va_guuid); 1065 if (VATTR_IS_ACTIVE(vap, va_uuuid)) 1066 VATTR_SET_SUPPORTED(vap, va_uuuid); 1067 1068 if (res) 1069 kauth_acl_free(res); 1070 1071 if (w_sec) 1072 SMB_FREE(w_sec, M_TEMP); 1073 1074 SMB_LOG_KTRACE(SMB_DBG_SMBFS_GET_SEC | DBG_FUNC_END, error, 0, 0, 0, 0); 1075 return error; 1076} 1077 1078/* 1079 * Fill in the network ace used to describe the posix uid, gid and modes. 1080 */ 1081static struct ntace * 1082set_nfs_ace(struct ntace *w_acep, ntsid_t *nfs_sid, size_t needed) 1083{ 1084 struct ntsid *w_sidp; 1085 1086 wset_acetype(w_acep, ACCESS_DENIED_ACE_TYPE); 1087 wset_aceflags(w_acep, 0); 1088 wset_acerights(w_acep, 0); 1089 w_sidp = acesid(w_acep); 1090 bcopy(nfs_sid, w_sidp, sizeof(ntsid_t)); 1091 smb_sid_endianize(w_sidp, needed); 1092 wset_acelen(w_acep, sizeof(struct ntace) + sidlen(w_sidp)); 1093 return aceace(w_acep); 1094} 1095 1096/* 1097 * This routine will set the owner, group and any ACLs associate with 1098 * this node. 1099 * 1100 * The calling routine must hold a reference on the share 1101 * 1102 */ 1103int 1104smbfs_setsecurity(struct smb_share *share, vnode_t vp, struct vnode_attr *vap, 1105 vfs_context_t context) 1106{ 1107 struct smbnode *np = VTOSMB(vp); 1108 struct smbmount *smp = np->n_mount; 1109 uint32_t selector = 0, acecount; 1110 struct ntsid *w_usr = NULL, *w_grp = NULL, *w_sidp; 1111 struct ntacl *w_dacl = NULL; /* Wire DACL */ 1112 int error; 1113 struct ntace *w_acep, *start_acep; /* Wire ACE */ 1114 struct kauth_ace *acep; 1115 uint8_t aflags; 1116 uint32_t arights, openrights; 1117 size_t needed; 1118 uint16_t ControlFlags = 0; 1119 SMBFID fid = 0; 1120 uuid_string_t out_str; 1121 1122 /* We do not support acl access on a stream node */ 1123 if (vnode_isnamedstream(vp)) 1124 return ENOTSUP; 1125 1126 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SET_SEC | DBG_FUNC_START, 0, 0, 0, 0, 0); 1127 1128 openrights = SMB2_READ_CONTROL | SMB2_SYNCHRONIZE; 1129 error = 0; 1130 1131 if (VATTR_IS_ACTIVE(vap, va_guuid) && !kauth_guid_equal(&vap->va_guuid, &kauth_null_guid)) { 1132 SMB_MALLOC(w_grp, struct ntsid *, MAXSIDLEN, M_TEMP, M_WAITOK); 1133 bzero(w_grp, MAXSIDLEN); 1134 error = kauth_cred_guid2ntsid(&vap->va_guuid, (ntsid_t *)w_grp); 1135 if (error) { 1136 uuid_unparse(*((const uuid_t *)&vap->va_guuid), out_str); 1137 SMBERROR("kauth_cred_guid2ntsid failed with va_guuid %s and error %d\n", 1138 out_str, error); 1139 goto exit; 1140 } 1141 smb_sid_endianize(w_grp, MAXSIDLEN); 1142 openrights |= SMB2_WRITE_OWNER; 1143 selector |= GROUP_SECURITY_INFORMATION; 1144 } 1145 1146 if (VATTR_IS_ACTIVE(vap, va_uuuid) && !kauth_guid_equal(&vap->va_uuuid, &kauth_null_guid)) { 1147 SMB_MALLOC(w_usr, struct ntsid *, MAXSIDLEN, M_TEMP, M_WAITOK); 1148 bzero(w_usr, MAXSIDLEN); 1149 /* We are mapping the owner id, so if its a match replace it with the network sid */ 1150 if ((smp->sm_flags & MNT_MAPS_NETWORK_LOCAL_USER) && 1151 (kauth_guid_equal(&smp->sm_args.uuid, &vap->va_uuuid))) { 1152 bcopy(&smp->ntwrk_sids[0], w_usr, sizeof(ntsid_t)); 1153 error = 0; 1154 } else { 1155 error = kauth_cred_guid2ntsid(&vap->va_uuuid, (ntsid_t *)w_usr); 1156 } 1157 if (error) { 1158 uuid_unparse(*((const uuid_t *)&vap->va_uuuid), out_str); 1159 SMBERROR("kauth_cred_guid2ntsid failed with va_uuuid %s and error %d\n", 1160 out_str, error); 1161 goto exit; 1162 } 1163 smb_sid_endianize(w_usr, MAXSIDLEN); 1164 openrights |= SMB2_WRITE_OWNER; 1165 selector |= OWNER_SECURITY_INFORMATION; 1166 } 1167 1168 if (VATTR_IS_ACTIVE(vap, va_acl)) { 1169 ntsid_t nfs_sid; 1170 1171 openrights |= SMB2_WRITE_DAC; 1172 selector |= DACL_SECURITY_INFORMATION; 1173 1174 if (vap->va_acl) { 1175#if DEBUG_ACLS 1176 smb_print_acl(np, "smbfs_setsecurity", vap->va_acl); 1177#endif 1178 if (vap->va_acl->acl_flags & KAUTH_FILESEC_NO_INHERIT) { 1179 selector |= PROTECTED_DACL_SECURITY_INFORMATION; 1180 ControlFlags |= SE_DACL_PROTECTED; 1181 } else { 1182 selector |= UNPROTECTED_DACL_SECURITY_INFORMATION; 1183 ControlFlags &= ~SE_DACL_PROTECTED; 1184 } 1185 } 1186 1187 if ((vap->va_acl == NULL) || (vap->va_acl->acl_entrycount == KAUTH_FILESEC_NOACL)) { 1188 ControlFlags |= SE_DACL_PRESENT; 1189 /* If we are removing the ACL nothing left to do but set it. */ 1190 goto set_dacl; 1191 } 1192 1193 if (vap->va_acl->acl_entrycount > KAUTH_ACL_MAX_ENTRIES) { 1194 SMBERROR_LOCK(np, "acl_entrycount=%d, file(%s)\n", 1195 vap->va_acl->acl_entrycount, np->n_name); 1196 error = EINVAL; 1197 goto exit; 1198 } 1199 1200 acecount = vap->va_acl->acl_entrycount; 1201 if (np->n_nfs_uid != KAUTH_UID_NONE) { 1202 /* Make room for the Windows NFS UID ACE */ 1203 acecount += 1; 1204 } 1205 1206 if (np->n_nfs_gid != KAUTH_GID_NONE) { 1207 /* Make room for the Windows NFS GID ACE */ 1208 acecount += 1; 1209 } 1210 1211 if (np->n_flag & NHAS_POSIXMODES) { 1212 /* Make room for the Windows NFS Modes ACE */ 1213 acecount += 1; 1214 } 1215 1216 needed = sizeof(struct ntacl) + acecount * (sizeof(struct ntace) + MAXSIDLEN); 1217 SMB_MALLOC(w_dacl, struct ntacl *, needed, M_TEMP, M_WAITOK); 1218 bzero(w_dacl, needed); 1219 w_dacl->acl_revision = 0x02; 1220 wset_aclacecount(w_dacl, acecount); 1221 1222 start_acep = aclace(w_dacl); 1223 nfs_sid.sid_kind = 1; 1224 nfs_sid.sid_authcount = 3; 1225 memcpy(nfs_sid.sid_authority, security_nt_authority, sizeof(security_nt_authority)); 1226 nfs_sid.sid_authorities[0] = SECURITY_NFS_ID_BASE_RID; 1227 1228 if (np->n_nfs_uid != KAUTH_UID_NONE) { 1229 /* Set the Windows nfs uid ace */ 1230 nfs_sid.sid_authorities[1] = NfsSidTypeOwner; 1231 nfs_sid.sid_authorities[2] = np->n_nfs_uid; 1232 start_acep = set_nfs_ace(start_acep,&nfs_sid, needed); 1233 acecount--; 1234 } 1235 1236 if (np->n_nfs_gid != KAUTH_GID_NONE) { 1237 /* Set the Windows nfs gid ace */ 1238 nfs_sid.sid_authorities[1] = NfsSidTypeGroup; 1239 nfs_sid.sid_authorities[2] = np->n_nfs_gid; 1240 start_acep = set_nfs_ace(start_acep,&nfs_sid, needed); 1241 acecount--; 1242 } 1243 1244 if (np->n_flag & NHAS_POSIXMODES) { 1245 /* Set the Windows nfs posix modes ace */ 1246 nfs_sid.sid_authorities[1] = NfsSidTypeModes; 1247 nfs_sid.sid_authorities[2] = np->n_mode; 1248 start_acep = set_nfs_ace(start_acep,&nfs_sid, needed); 1249 acecount--; 1250 } 1251 1252 for (w_acep = start_acep, acep = &vap->va_acl->acl_ace[0]; 1253 acecount--; w_acep = aceace(w_acep), acep++) { 1254 switch(acep->ace_flags & KAUTH_ACE_KINDMASK) { 1255 case KAUTH_ACE_PERMIT: 1256 wset_acetype(w_acep, ACCESS_ALLOWED_ACE_TYPE); 1257 break; 1258 case KAUTH_ACE_DENY: 1259 wset_acetype(w_acep, ACCESS_DENIED_ACE_TYPE); 1260 break; 1261 case KAUTH_ACE_AUDIT: 1262 wset_acetype(w_acep, SYSTEM_AUDIT_ACE_TYPE); 1263 break; 1264 case KAUTH_ACE_ALARM: 1265 wset_acetype(w_acep, SYSTEM_ALARM_ACE_TYPE); 1266 break; 1267 default: 1268 SMBERROR_LOCK(np, "ace_flags=0x%x, file(%s)\n", 1269 acep->ace_flags, np->n_name); 1270 error = EINVAL; 1271 goto exit; 1272 } 1273 aflags = 0; 1274 if (acep->ace_flags & KAUTH_ACE_INHERITED) 1275 aflags |= INHERITED_ACE_FLAG; 1276 if (acep->ace_flags & KAUTH_ACE_FILE_INHERIT) 1277 aflags |= OBJECT_INHERIT_ACE_FLAG; 1278 if (acep->ace_flags & KAUTH_ACE_DIRECTORY_INHERIT) 1279 aflags |= CONTAINER_INHERIT_ACE_FLAG; 1280 if (acep->ace_flags & KAUTH_ACE_LIMIT_INHERIT) 1281 aflags |= NO_PROPAGATE_INHERIT_ACE_FLAG; 1282 if (acep->ace_flags & KAUTH_ACE_ONLY_INHERIT) 1283 aflags |= INHERIT_ONLY_ACE_FLAG; 1284 if (acep->ace_flags & KAUTH_ACE_SUCCESS) 1285 aflags |= SUCCESSFUL_ACCESS_ACE_FLAG; 1286 if (acep->ace_flags & KAUTH_ACE_FAILURE) 1287 aflags |= FAILED_ACCESS_ACE_FLAG; 1288 wset_aceflags(w_acep, aflags); 1289 arights = 0; 1290 if (acep->ace_rights & KAUTH_ACE_GENERIC_READ) 1291 arights |= SMB2_GENERIC_READ; 1292 if (acep->ace_rights & KAUTH_ACE_GENERIC_WRITE) 1293 arights |= SMB2_GENERIC_WRITE; 1294 if (acep->ace_rights & KAUTH_ACE_GENERIC_EXECUTE) 1295 arights |= SMB2_GENERIC_EXECUTE; 1296 if (acep->ace_rights & KAUTH_ACE_GENERIC_ALL) 1297 arights |= SMB2_GENERIC_ALL; 1298 if (acep->ace_rights & KAUTH_VNODE_SYNCHRONIZE) 1299 arights |= SMB2_SYNCHRONIZE; 1300 if (acep->ace_rights & KAUTH_VNODE_CHANGE_OWNER) 1301 arights |= SMB2_WRITE_OWNER; 1302 if (acep->ace_rights & KAUTH_VNODE_WRITE_SECURITY) 1303 arights |= SMB2_WRITE_DAC; 1304 if (acep->ace_rights & KAUTH_VNODE_READ_SECURITY) 1305 arights |= SMB2_READ_CONTROL; 1306 if (acep->ace_rights & KAUTH_VNODE_WRITE_EXTATTRIBUTES) 1307 arights |= SMB2_FILE_WRITE_EA; 1308 if (acep->ace_rights & KAUTH_VNODE_READ_EXTATTRIBUTES) 1309 arights |= SMB2_FILE_READ_EA; 1310 if (acep->ace_rights & KAUTH_VNODE_WRITE_ATTRIBUTES) 1311 arights |= SMB2_FILE_WRITE_ATTRIBUTES; 1312 if (acep->ace_rights & KAUTH_VNODE_READ_ATTRIBUTES) 1313 arights |= SMB2_FILE_READ_ATTRIBUTES; 1314 if (acep->ace_rights & KAUTH_VNODE_DELETE_CHILD) 1315 arights |= SMB2_FILE_DELETE_CHILD; 1316 if (acep->ace_rights & KAUTH_VNODE_APPEND_DATA) 1317 arights |= SMB2_FILE_APPEND_DATA; 1318 if (acep->ace_rights & KAUTH_VNODE_DELETE) 1319 arights |= SMB2_DELETE; 1320 if (acep->ace_rights & KAUTH_VNODE_EXECUTE) 1321 arights |= SMB2_FILE_EXECUTE; 1322 if (acep->ace_rights & KAUTH_VNODE_WRITE_DATA) 1323 arights |= SMB2_FILE_WRITE_DATA; 1324 if (acep->ace_rights & KAUTH_VNODE_READ_DATA) 1325 arights |= SMB2_FILE_READ_DATA; 1326 1327 /* <15782523> Always set the Synchronize bit for now */ 1328 arights |= SMB2_SYNCHRONIZE; 1329 1330 wset_acerights(w_acep, arights); 1331 w_sidp = acesid(w_acep); 1332 1333 if ((smp->sm_flags & MNT_MAPS_NETWORK_LOCAL_USER) && 1334 (kauth_guid_equal(&smp->sm_args.uuid, &acep->ace_applicable))) { 1335 bcopy(&smp->ntwrk_sids[0], w_sidp, sizeof(ntsid_t)); 1336 } 1337 else { 1338 error = kauth_cred_guid2ntsid(&acep->ace_applicable, (ntsid_t *)w_sidp); 1339 } 1340#if DEBUG_ACLS 1341 lck_rw_lock_shared(&np->n_name_rwlock); 1342 smb_printsid(w_sidp, (char*)w_sidp+sidlen(w_sidp), "guid maps to", 1343 (const char *)np->n_name, acecount, 0); 1344 lck_rw_unlock_shared(&np->n_name_rwlock); 1345 1346 smb_print_guid(&acep->ace_applicable); 1347#endif 1348 1349 if (error) { 1350 uuid_unparse(*((const uuid_t *)&acep->ace_applicable), out_str); 1351 SMBERROR("kauth_cred_guid2ntsid failed with va_acl %s and error %d\n", 1352 out_str, error); 1353 goto exit; 1354 } 1355 smb_sid_endianize(w_sidp, needed); 1356 wset_acelen(w_acep, sizeof(struct ntace) + sidlen(w_sidp)); 1357 } 1358 wset_acllen(w_dacl, ((char *)w_acep - (char *)w_dacl)); 1359 } 1360 1361set_dacl: 1362 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 1363 /* Only open file if its SMB 1 */ 1364 error = smbfs_tmpopen(share, np, openrights, &fid, context); 1365 } 1366 1367 if (error == 0) { 1368 error = smbfs_smb_setsec(share, np, openrights, 1369 fid, selector, ControlFlags, 1370 w_usr, w_grp, NULL, w_dacl, context); 1371 1372 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 1373 /* Only close file if its SMB 1 */ 1374 (void)smbfs_tmpclose(share, np, fid, context); 1375 } 1376 } 1377exit: 1378 if (w_usr != NULL) { 1379 SMB_FREE(w_usr, M_TEMP); 1380 } 1381 if (w_grp != NULL) { 1382 SMB_FREE(w_grp, M_TEMP); 1383 } 1384 if (w_dacl != NULL) { 1385 SMB_FREE(w_dacl, M_TEMP); 1386 } 1387 1388 /* The current cache is out of date clear it */ 1389 smbfs_clear_acl_cache(np); 1390 1391 SMB_LOG_KTRACE(SMB_DBG_SMBFS_SET_SEC | DBG_FUNC_END, error, 0, 0, 0, 0); 1392 return (error); 1393} 1394 1395/* 1396* The calling routine must hold a reference on the share 1397*/ 1398void 1399smb_get_sid_list(struct smb_share *share, struct smbmount *smp, struct mdchain *mdp, 1400 uint32_t ntwrk_sids_cnt, uint32_t ntwrk_sid_size) 1401{ 1402 uint32_t ii; 1403 int error; 1404 void *sidbufptr = NULL; 1405 char *endsidbufptr; 1406 char *nextsidbufptr; 1407 struct ntsid *ntwrk_wire_sid; 1408 ntsid_t *ntwrk_sids = NULL; 1409 ntsid_t tmpsid; 1410 uint32_t sidCnt = 0; 1411 1412 if ((ntwrk_sids_cnt == 0) || (ntwrk_sid_size == 0)) { 1413 SMBDEBUG("ntwrk_sids_cnt = %d ntwrk_sid_size = %d\n", 1414 ntwrk_sids_cnt, ntwrk_sid_size); 1415 goto done; /* Nothing to do here we are done */ 1416 } 1417 1418 /* Never allocate more than we could have received in this message */ 1419 if (ntwrk_sid_size > SSTOVC(share)->vc_txmax) { 1420 SMBDEBUG("Too big ntwrk_sid_size = %d\n", ntwrk_sid_size); 1421 goto done; 1422 } 1423 1424 /* Max number we will support, about 9K */ 1425 if (ntwrk_sids_cnt > KAUTH_ACL_MAX_ENTRIES) 1426 ntwrk_sids_cnt = KAUTH_ACL_MAX_ENTRIES; 1427 1428 SMB_MALLOC(ntwrk_sids, void *, ntwrk_sids_cnt * sizeof(*ntwrk_sids) , M_TEMP, 1429 M_WAITOK | M_ZERO); 1430 if (ntwrk_sids == NULL) { 1431 SMBDEBUG("ntwrk_sids malloc failed!\n"); 1432 goto done; 1433 } 1434 SMB_MALLOC(sidbufptr, void *, ntwrk_sid_size, M_TEMP, M_WAITOK); 1435 if (sidbufptr == NULL) { 1436 SMBDEBUG("SID malloc failed!\n"); 1437 goto done; 1438 } 1439 error = md_get_mem(mdp, sidbufptr, ntwrk_sid_size, MB_MSYSTEM); 1440 if (error) { 1441 SMBDEBUG("Could get the list of sids? error = %d\n", error); 1442 goto done; 1443 } 1444 1445 endsidbufptr = (char *)sidbufptr + ntwrk_sid_size; 1446 nextsidbufptr = sidbufptr; 1447 for (ii = 0; ii < ntwrk_sids_cnt; ii++) { 1448 ntwrk_wire_sid = (struct ntsid *)nextsidbufptr; 1449 nextsidbufptr += sizeof(*ntwrk_wire_sid); 1450 /* Make sure we don't overrun our buffer */ 1451 if (nextsidbufptr > endsidbufptr) { 1452 SMBDEBUG("Network sid[%d] buffer to small start %p current %p end %p\n", 1453 ii, sidbufptr, nextsidbufptr, endsidbufptr); 1454 break; 1455 } 1456 /* 1457 * We are done with nextsidbufptr for this loop, reset it to the next 1458 * entry. The smb_sid2sid16 routine will protect us from any buffer overruns, 1459 * so no need to check here. 1460 */ 1461 nextsidbufptr += (ntwrk_wire_sid->sid_subauthcount * sizeof(uint32_t)); 1462 1463 smb_sid2sid16(ntwrk_wire_sid, &tmpsid, endsidbufptr); 1464 1465 /* Don't store any unix_users or unix_groups sids */ 1466 if (!smb_sid_in_domain(&unix_users_domsid, &tmpsid) && 1467 !smb_sid_in_domain(&unix_groups_domsid, &tmpsid)) { 1468 ntwrk_sids[sidCnt++] = tmpsid; 1469 } else { 1470 SMBDEBUG("Skipping ntwrk_wire_sid entry %d\n", ii); 1471 continue; 1472 } 1473 1474 if (smbfs_loglevel == SMB_ACL_LOG_LEVEL) { 1475 smb_printsid(ntwrk_wire_sid, endsidbufptr, "WHOAMI network", NULL, ii, 0); 1476 } 1477 } 1478 1479 /* We skipped some unix_users or unix_groups, resize the buffer down */ 1480 if (sidCnt != ntwrk_sids_cnt) { 1481 size_t sidarraysize = sidCnt * sizeof(*ntwrk_sids); 1482 ntsid_t *holdSids = ntwrk_sids; 1483 1484 ntwrk_sids = NULL; 1485 SMB_MALLOC(ntwrk_sids, void *, sidarraysize, M_TEMP, M_WAITOK | M_ZERO); 1486 if (ntwrk_sids) { 1487 bcopy(holdSids, ntwrk_sids, sidarraysize); 1488 } 1489 SMB_FREE(holdSids, M_TEMP); 1490 } 1491 1492 /* 1493 * We found a list of sid returned by the server, we alway use those over 1494 * the LSA ones. Remove the LSA ones and mark that we have WHOAMI SIDS. 1495 */ 1496 if (sidCnt && ntwrk_sids) { 1497 SMB_FREE(smp->ntwrk_sids, M_TEMP); 1498 smp->ntwrk_sids_cnt = sidCnt; 1499 smp->ntwrk_sids = ntwrk_sids; 1500 ntwrk_sids = NULL; 1501 UNIX_CAPS(share) |= UNIX_QFS_POSIX_WHOAMI_SID_CAP; 1502 } 1503 1504done: 1505 /* Just clean up */ 1506 SMB_FREE(ntwrk_sids, M_TEMP); 1507 SMB_FREE(sidbufptr, M_TEMP); 1508} 1509 1510/* 1511 * Need to check to see if the maximum access rights needs to be updated. We 1512 * use the node's change time to determine when we need to update. We check to 1513 * see if the node's change time has changed since the last time we got the 1514 * maximum access rights. The change time is cached as part of the node's meta 1515 * data. So the maximum access rights is cached based on the node's meta cache 1516 * timer and the node's change time. 1517 * 1518 * Now we have some issues we need to deal with here. We can get the maximum 1519 * access rights from the extended open reply. Windows server always return the 1520 * correct maximum access rights, but some servers lie. Samba just returns that 1521 * you have full access. Also if the server doesn't support the extended open 1522 * reply we never test again and the cache never expired. 1523 * 1524 * For servers that supports the extended open reply we just believe they are 1525 * returning the correct information. 1526 * 1527 * If the server doesn't support the extended open reply, then we will set the 1528 * maximum access rights to full access. We mark that the call failed so we 1529 * don't need to update ever agian. 1530 * 1531 * The calling routine must hold a reference on the share 1532 * 1533 */ 1534uint32_t 1535smbfs_get_maximum_access(struct smb_share *share, vnode_t vp, vfs_context_t context) 1536{ 1537 struct smbnode *np; 1538 uint32_t maxAccessRights; 1539 int error; 1540 SMBFID fid = 0; 1541 1542 /* 1543 * Need to have the node locked while getting the maximum access rights. In 1544 * the future we may want to only lock what we need. 1545 */ 1546 if (smbnode_lock(VTOSMB(vp), SMBFS_EXCLUSIVE_LOCK)) 1547 return 0; 1548 1549 SMB_LOG_KTRACE(SMB_DBG_SMBFS_GET_MAX_ACCESS | DBG_FUNC_START, 0, 0, 0, 0, 0); 1550 1551 np = VTOSMB(vp); 1552 np->n_lastvop = smbfs_get_maximum_access; 1553 1554 /* 1555 * We can't open a reparse point that has a Dfs tag, so don't even try. Let 1556 * the server handle any security issues. 1557 */ 1558 if ((np->n_dosattr & SMB_EFA_REPARSE_POINT) && 1559 (np->n_reparse_tag == IO_REPARSE_TAG_DFS)) { 1560 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 1561 goto done; 1562 } 1563 1564 /* This server doesn't support maximum access, just lie */ 1565 if (np->n_flag & NO_EXTENDEDOPEN) { 1566 /* When smb1fs_smb_ntcreatex() sets NO_EXTENDEDOPEN, it also sets 1567 * np->maxAccessRights to "all access". So we don't need to modify 1568 * np->maxAccessRights here. 1569 */ 1570 goto done; 1571 } 1572 1573 /* 1574 * This server doesn't support extended security, so assume 1575 * it doesn't support maximum access. We grant all access and 1576 * let the server make the final call. 1577 */ 1578 if (!(VC_CAPS(SSTOVC(share)) & SMB_CAP_EXT_SECURITY)) { 1579 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 1580 goto done; 1581 } 1582 1583 /* Cache is still good, return the last value we had */ 1584 if (timespeccmp(&np->maxAccessRightChTime, &np->n_chtime, ==)) 1585 goto done; 1586 1587 /* 1588 * For Windows we only need to open and close the item. Need to see if 1589 * we can write a routine that does a CreateAndX/close in one message. 1590 * Also Windows server allow us to get the maximum access by opening the 1591 * file without requesting access. This allows us to get the maximum 1592 * access, even when we can't read the security descriptor. We need to 1593 * test with other servers and see if they behave the same as windows or 1594 * do we need to open them with SMB2_READ_CONTROL? 1595 * 1596 * <9874997> In Lion, we started using maximal access returned by the 1597 * server. One odd setup with a Windows 2003 server where the maximal 1598 * access returned in the Tree Connect response (share ACL) gave more 1599 * access than the maximal access given by CreateAndX on the '\' folder 1600 * (filesystem ACL). 1601 * Treat the root folder as a special case. 1602 * 1) If the CreateAndX fails on the root, then assume full access 1603 * 2) If the CreateAndX works on the root, if no ReadAttr or Execute BUT 1604 * the share ACL grants ReadAttr or Execute then assume '\' also has 1605 * ReadAttr or Execute. 1606 */ 1607 /* 1608 * We could solve a lot of headaches by testing for the servers that do 1609 * not support opening the item with no access. Something like the following 1610 * should work (accessOpenModes defaults to zero): 1611 * 1612 * error = smbfs_tmpopen(share, np, share->accessOpenModes, &fid, context); 1613 * if (error && share->firstAccessOpen) { 1614 * share->accessOpenModes = SMB2_READ_CONTROL; 1615 * error = smbfs_tmpopen(share, np, share->accessOpenModes, &fid, context); 1616 * } 1617 * share->firstAccessOpen = TRUE; 1618 * 1619 * At this point we should just trust what they say, may want to make an exception 1620 * for the root node, and non darwin Unix systems. 1621 */ 1622 1623 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 1624 struct smbfattr *fap = NULL; 1625 uint32_t desired_access = 0; 1626 enum vtype vnode_type = vnode_isdir(np->n_vnode) ? VDIR : VREG; 1627 uint32_t share_access = NTCREATEX_SHARE_ACCESS_ALL; 1628 uint64_t create_flags = SMB2_CREATE_GET_MAX_ACCESS; 1629 uint32_t ntstatus = 0; 1630 1631 /* 1632 * Do a compound create/close 1633 * Note: this always does a create/close over the wire and never 1634 * uses an existing open file like smbfs_tmpopen can do. 1635 */ 1636 SMB_MALLOC(fap, 1637 struct smbfattr *, 1638 sizeof(struct smbfattr), 1639 M_SMBTEMP, 1640 M_WAITOK | M_ZERO); 1641 if (fap == NULL) { 1642 SMBERROR("SMB_MALLOC failed\n"); 1643 error = ENOMEM; 1644 } 1645 else { 1646 /* Send a Create/Close */ 1647 error = smb2fs_smb_cmpd_create(share, np, 1648 NULL, 0, 1649 NULL, 0, 1650 desired_access, vnode_type, 1651 share_access, FILE_OPEN, 1652 create_flags, &ntstatus, 1653 NULL, fap, 1654 NULL, context); 1655 /* 1656 * smb2fs_smb_cmpd_create() will update the vnodes 1657 * maxAccessRights 1658 */ 1659 1660 SMB_FREE(fap, M_SMBTEMP); 1661 } 1662 } 1663 else { 1664 error = smbfs_tmpopen(share, np, 0, &fid, context); 1665 if (!error) { 1666 smbfs_tmpclose(share, np, fid, context); 1667 } 1668 } 1669 1670 if (error) { 1671 if (error != EACCES) { 1672 /* We have no idea why it failed, give them full access. */ 1673 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 1674 } else { 1675 if (vnode_isvroot(np->n_vnode)) { 1676 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 1677 } else if (((!UNIX_SERVER(SSTOVC(share))) || (SSTOVC(share)->vc_flags & SMBV_DARWIN))) { 1678 /* Windows or Darwin Server and they told us we have no access. */ 1679 np->maxAccessRights = 0; 1680 } else { 1681 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 1682 } 1683 } 1684 1685 SMB_LOG_ACCESS_LOCK(np, "Opening %s failed with error = %d, granting %s access\n", 1686 np->n_name, error, (np->maxAccessRights) ? "full" : "no"); 1687 1688 /* 1689 * The open call failed so the cache timer wasn't set, so do that 1690 * here 1691 */ 1692 np->maxAccessRightChTime = np->n_chtime; 1693 } 1694 else { 1695 /* Special case the root vnode */ 1696 if (vnode_isvroot(np->n_vnode)) { 1697 /* 1698 * its the root folder, if no Execute, but share grants 1699 * Execute then grant Execute to root folder 1700 */ 1701 if ((!(np->maxAccessRights & SMB2_FILE_EXECUTE)) && 1702 (share->maxAccessRights & SMB2_FILE_EXECUTE)) { 1703 np->maxAccessRights |= SMB2_FILE_EXECUTE; 1704 } 1705 1706 /* 1707 * its the root, if no ReadAttr, but share grants 1708 * ReadAttr then grant ReadAttr to root 1709 */ 1710 if ((!(np->maxAccessRights & SMB2_FILE_READ_ATTRIBUTES)) && 1711 (share->maxAccessRights & SMB2_FILE_READ_ATTRIBUTES)) { 1712 np->maxAccessRights |= SMB2_FILE_READ_ATTRIBUTES; 1713 } 1714 } 1715 } 1716 1717 SMB_LOG_ACCESS_LOCK(np, "%s maxAccessRights = 0x%x\n", np->n_name, np->maxAccessRights); 1718 1719done: 1720 maxAccessRights = np->maxAccessRights; 1721 smbnode_unlock(VTOSMB(vp)); 1722 1723 SMB_LOG_KTRACE(SMB_DBG_SMBFS_GET_MAX_ACCESS | DBG_FUNC_END, 0, 0, 0, 0, 0); 1724 return maxAccessRights; 1725} 1726 1727/* 1728 * The composition: 1729 * 1730 * (RED, REA, RID, RIA) is what we receive with the vnop. Those are: 1731 * RED - Requested Explicit Deny 1732 * REA - Requested Explicit Allow 1733 * RID - Requested Inherited Deny 1734 * RIA - Requested Inherited Allow 1735 * That's the canonical order the ACEs should have arrived in, but in 1736 * reality we should never get inherited ACE here and the order could 1737 * be different depending on what the calling application is trying to 1738 * accomplish. If copying the item they may want to add a full ACE as 1739 * the first element and then remove it when they are done. We no longer 1740 * inforce the order at our level. 1741 * 1742 * (SED, SEA, SID, SIA) is what we receive from the server. Those are: 1743 * SED - Server Explicit (defaulted) Deny 1744 * SEA - Server Explicit (defaulted) Allow 1745 * SID - Server Inherited Deny 1746 * SIA - Server Inherited Allow 1747 * 1748 * This is the canonical order the ACEs should have arrived in, but in 1749 * reality we should only get inherited ACE here. Now Samba will send 1750 * us a DIRECT ACE that represents the POSIX MODES. We always trust that 1751 * the server has these stored in the correct canonical. 1752 * 1753 * NOTE: Windows normally has an allow-all ACE for the object owner and 1754 * another allow ACE for Local System. 1755 * 1756 * NOTE: If we were going the put these in canonical orer this is what 1757 * we would need to do. We would take the (RED, REA, RID, RIA) and the 1758 * (SED, SEA, SID, SIA) and write back (SED, RED, SEA, REA, SID, RID, SIA, RIA) 1759 * All non-deny ACEs, for instance audit or alarm types, can be 1760 * treated the same w/r/t canonicalizing the ACE order. 1761 * 1762 * With that said this is what we do here. We create a new ACL that is large 1763 * enough to hold both ACLS. We remove any inherited ACEs that are in the 1764 * VNOP ACL. We then combind the two set of ACEs into one set VNOP ACEs first 1765 * followed by the SERVER ACEs. Since we are only adding direct ACEs and the 1766 * server ACEs should all be inherited this sould be correct. 1767 */ 1768int 1769smbfs_compose_create_acl(struct vnode_attr *vap, struct vnode_attr *svrva, 1770 kauth_acl_t *savedacl) 1771{ 1772 int32_t entries, allocated; 1773 struct kauth_ace *acep; 1774 kauth_acl_t newacl; 1775 uint32_t j; 1776 1777 allocated = vap->va_acl->acl_entrycount + svrva->va_acl->acl_entrycount; 1778 newacl = kauth_acl_alloc(allocated); 1779 if (newacl == NULL) { 1780 SMBERROR("kauth_acl_alloc, %d\n", allocated); 1781 return ENOMEM; 1782 } 1783 1784 newacl->acl_flags = svrva->va_acl->acl_flags; 1785 entries = 0; /* output index for ACL we're building */ 1786 1787 /* First add the vnop ACEs, skipping any inherited ACEs or dups */ 1788 for (j = 0; j < vap->va_acl->acl_entrycount; j++) { 1789 acep = &vap->va_acl->acl_ace[j]; 1790 if (acep->ace_flags & KAUTH_ACE_INHERITED) { 1791 SMBERROR("Skipping ACE becuase VNOP is trying to set an inherited ACE\n"); 1792 continue; 1793 } 1794 newacl->acl_ace[entries++] = *acep; 1795 if (entries > allocated) { 1796 kauth_acl_free(newacl); 1797 return EINVAL; 1798 } 1799 } 1800 1801 /* Now add the create ACE assume they are all inherited. */ 1802 for (j = 0; j < svrva->va_acl->acl_entrycount; j++) { 1803 acep = &svrva->va_acl->acl_ace[j]; 1804 newacl->acl_ace[entries++] = *acep; 1805 if (entries > allocated) { 1806 kauth_acl_free(newacl); 1807 return EINVAL; 1808 } 1809 } 1810 newacl->acl_entrycount = entries; 1811 *savedacl = vap->va_acl; 1812 vap->va_acl = newacl; 1813 return 0; 1814} 1815 1816/* 1817 * Check to see if Directory Service understands this sid 1818 */ 1819int 1820smbfs_is_sid_known(ntsid_t *sid) 1821{ 1822 int error; 1823 guid_t unique_identifier; 1824 ntsid_t sidFromUUID; 1825 1826 /* See if DS can translate the SID into a UUID */ 1827 error = kauth_cred_ntsid2guid(sid, &unique_identifier); 1828 if (error) { 1829 SMBDEBUG("kauth_cred_ntsid2guid failed error = %d\n", error); 1830 return FALSE; 1831 } 1832 /* See if DS gave us a temp UUID */ 1833 if (is_memberd_tempuuid(&unique_identifier)) { 1834 return FALSE; 1835 } 1836 /* See if DS can translate the UUID back into a SID */ 1837 error = kauth_cred_guid2ntsid(&unique_identifier, &sidFromUUID); 1838 if (error) { 1839 SMBDEBUG("kauth_cred_guid2ntsid failed error = %d\n", error); 1840 return FALSE; 1841 } 1842 /* Could we round trip the sid, nope the turn off ACLS */ 1843 if (memcmp(&sidFromUUID, sid, sizeof(sidFromUUID)) != 0) { 1844 SMBWARNING("Couldn't round trip the SID\n"); 1845 return FALSE; 1846 } 1847 return TRUE; 1848} 1849 1850/* 1851 * This items doesn't have any ACL, must only have posix modes. Just set the 1852 * posix ace. 1853 */ 1854static int 1855smbfs_set_default_nfs_ace(struct smb_share *share, struct smbnode *np, vfs_context_t context) 1856{ 1857 int error; 1858 SMBFID fid = 0; 1859 ntsid_t nfs_sid; 1860 size_t needed; 1861 uint32_t acecount = 1; 1862 struct ntacl *w_dacl = NULL; /* Wire DACL */ 1863 struct ntace *w_acep; /* Wire ACE */ 1864 1865 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 1866 /* Only open file if its SMB 1 */ 1867 error = smbfs_tmpopen(share, np, SMB2_READ_CONTROL | SMB2_WRITE_DAC, &fid, 1868 context); 1869 if (error) { 1870 return error; 1871 } 1872 } 1873 1874 needed = sizeof(struct ntacl) + acecount * (sizeof(struct ntace) + MAXSIDLEN); 1875 SMB_MALLOC(w_dacl, struct ntacl *, needed, M_TEMP, M_WAITOK | M_ZERO); 1876 w_dacl->acl_revision = 0x02; 1877 wset_aclacecount(w_dacl, acecount); 1878 1879 w_acep = aclace(w_dacl); 1880 nfs_sid.sid_kind = 1; 1881 nfs_sid.sid_authcount = 3; 1882 memcpy(nfs_sid.sid_authority, security_nt_authority, sizeof(security_nt_authority)); 1883 nfs_sid.sid_authorities[0] = SECURITY_NFS_ID_BASE_RID; 1884 /* Set the Windows nfs posix modes ace */ 1885 nfs_sid.sid_authorities[1] = NfsSidTypeModes; 1886 nfs_sid.sid_authorities[2] = np->n_mode; 1887 w_acep = set_nfs_ace(w_acep, &nfs_sid, needed); 1888 wset_acllen(w_dacl, ((char *)w_acep - (char *)w_dacl)); 1889 1890 error = smbfs_smb_setsec(share, np, SMB2_READ_CONTROL | SMB2_WRITE_DAC | SMB2_SYNCHRONIZE, 1891 fid, DACL_SECURITY_INFORMATION, 0, NULL, NULL, 1892 NULL, w_dacl, context); 1893 1894 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 1895 /* Only close file if its SMB 1 */ 1896 (void)smbfs_tmpclose(share, np, fid, context); 1897 } 1898 1899 SMB_FREE(w_dacl, M_TEMP); 1900 1901 /* The current cache is out of date clear it */ 1902 smbfs_clear_acl_cache(np); 1903 return error; 1904} 1905 1906/* 1907 * Use the Windows NFS ACE to hold the Posix modes. Should we store the UID and 1908 * GID? Currently no, we only care about the posix modes, use the OWNER and 1909 * GROUP ACE to handle the uid/gid. 1910 */ 1911int 1912smbfs_set_ace_modes(struct smb_share *share, struct smbnode *np, uint64_t vamode, vfs_context_t context) 1913{ 1914 int error; 1915 struct vnode_attr va; 1916 mode_t save_mode = np->n_mode; 1917 1918 /* Get the ACL from the server, so we can do the set */ 1919 memset(&va, 0, sizeof(va)); 1920 VATTR_INIT(&va); 1921 VATTR_SET_ACTIVE(&va, va_acl); 1922 error = smbfs_getsecurity(share, np, &va, context); 1923 if (error) { 1924 return error; 1925 } 1926 /* 1927 * Set that we have a Windows NFS posix mode ace, so the set acl routine 1928 * will add them to the ACL. 1929 */ 1930 np->n_flag |= NHAS_POSIXMODES; 1931 np->n_mode &= ~ACCESSPERMS; 1932 np->n_mode |= (mode_t)(vamode & ACCESSPERMS); 1933 if (va.va_acl == NULL) { 1934 error = smbfs_set_default_nfs_ace(share, np,context); 1935 } else { 1936 VATTR_SET_ACTIVE(&va, va_acl); 1937 error = smbfs_setsecurity(share, np->n_vnode, &va, context); 1938 } 1939 1940 if (error) { 1941 /* Reset the posix modes back since we failed. */ 1942 np->n_mode &= ~ACCESSPERMS; 1943 np->n_mode |= (mode_t)(save_mode & ACCESSPERMS); 1944 } 1945 /* Free any ACL we got from the smbfs_getsecurity routine */ 1946 if (va.va_acl) { 1947 kauth_acl_free(va.va_acl); 1948 } 1949 return error; 1950} 1951