static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd) { NTSTATUS status; DATA_BLOB blob; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", fsp->fsp_name)); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { return status; } /* Ensure owner and group are set. */ if (!psd->owner_sid || !psd->group_sid) { int ret; SMB_STRUCT_STAT sbuf; DOM_SID owner_sid, group_sid; struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd); if (!nc_psd) { return NT_STATUS_OK; } if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf); } else { ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf); } } else { ret = SMB_VFS_FSTAT(fsp, &sbuf); } if (ret == -1) { /* Lower level acl set succeeded, * so still return OK. */ return NT_STATUS_OK; } create_file_sids(&sbuf, &owner_sid, &group_sid); /* This is safe as nc_psd is discarded at fn exit. */ nc_psd->owner_sid = &owner_sid; nc_psd->group_sid = &group_sid; security_info_sent |= (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION); psd = nc_psd; } #if 0 if ((security_info_sent & DACL_SECURITY_INFORMATION) && psd->dacl != NULL && (psd->type & (SE_DESC_DACL_AUTO_INHERITED| SE_DESC_DACL_AUTO_INHERIT_REQ))== (SE_DESC_DACL_AUTO_INHERITED| SE_DESC_DACL_AUTO_INHERIT_REQ) ) { struct security_descriptor *new_psd = NULL; status = append_parent_acl(fsp, psd, &new_psd); if (!NT_STATUS_IS_OK(status)) { /* Lower level acl set succeeded, * so still return OK. */ return NT_STATUS_OK; } psd = new_psd; } #endif if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", fsp->fsp_name)); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } create_acl_blob(psd, &blob); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; }
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd) { NTSTATUS status; DATA_BLOB blob; struct security_descriptor *pdesc_next = NULL; uint8_t hash[XATTR_SD_HASH_SIZE]; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } /* Ensure we have OWNER/GROUP/DACL set. */ if ((security_info_sent & (OWNER_SECURITY_INFORMATION| GROUP_SECURITY_INFORMATION| DACL_SECURITY_INFORMATION)) != (OWNER_SECURITY_INFORMATION| GROUP_SECURITY_INFORMATION| DACL_SECURITY_INFORMATION)) { /* No we don't - read from the existing SD. */ struct security_descriptor *nc_psd = NULL; status = get_nt_acl_internal(handle, fsp, NULL, (OWNER_SECURITY_INFORMATION| GROUP_SECURITY_INFORMATION| DACL_SECURITY_INFORMATION), &nc_psd); if (!NT_STATUS_IS_OK(status)) { return status; } /* This is safe as nc_psd is discarded at fn exit. */ if (security_info_sent & OWNER_SECURITY_INFORMATION) { nc_psd->owner_sid = psd->owner_sid; } security_info_sent |= OWNER_SECURITY_INFORMATION; if (security_info_sent & GROUP_SECURITY_INFORMATION) { nc_psd->group_sid = psd->group_sid; } security_info_sent |= GROUP_SECURITY_INFORMATION; if (security_info_sent & DACL_SECURITY_INFORMATION) { nc_psd->dacl = dup_sec_acl(talloc_tos(), psd->dacl); if (nc_psd->dacl == NULL) { return NT_STATUS_NO_MEMORY; } } security_info_sent |= DACL_SECURITY_INFORMATION; psd = nc_psd; } status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { return status; } /* Get the full underlying sd, then hash. */ status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, HASH_SECURITY_INFO, &pdesc_next); if (!NT_STATUS_IS_OK(status)) { return status; } status = hash_sd_sha256(pdesc_next, hash); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; }
static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, const char *fname, files_struct *fsp, bool container) { TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status; struct security_descriptor *parent_desc = NULL; struct security_descriptor *psd = NULL; DATA_BLOB blob; size_t size; char *parent_name; if (!parent_dirname(ctx, fname, &parent_name, NULL)) { return NT_STATUS_NO_MEMORY; } DEBUG(10,("inherit_new_acl: check directory %s\n", parent_name)); status = get_nt_acl_xattr_internal(handle, NULL, parent_name, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), &parent_desc); if (NT_STATUS_IS_OK(status)) { /* Create an inherited descriptor from the parent. */ if (DEBUGLEVEL >= 10) { DEBUG(10,("inherit_new_acl: parent acl is:\n")); NDR_PRINT_DEBUG(security_descriptor, parent_desc); } status = se_create_child_secdesc(ctx, &psd, &size, parent_desc, &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX], &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX], container); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("inherit_new_acl: child acl is:\n")); NDR_PRINT_DEBUG(security_descriptor, psd); } } else { DEBUG(10,("inherit_new_acl: directory %s failed " "to get acl %s\n", parent_name, nt_errstr(status) )); } if (!psd || psd->dacl == NULL) { SMB_STRUCT_STAT sbuf; int ret; TALLOC_FREE(psd); if (fsp && !fsp->is_directory && fsp->fh->fd != -1) { ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { if (fsp && fsp->posix_open) { ret = SMB_VFS_LSTAT(handle->conn,fname, &sbuf); } else { ret = SMB_VFS_STAT(handle->conn,fname, &sbuf); } } if (ret == -1) { return map_nt_error_from_unix(errno); } psd = default_file_sd(ctx, &sbuf); if (!psd) { return NT_STATUS_NO_MEMORY; } if (DEBUGLEVEL >= 10) { DEBUG(10,("inherit_new_acl: default acl is:\n")); NDR_PRINT_DEBUG(security_descriptor, psd); } } status = create_acl_blob(psd, &blob); if (!NT_STATUS_IS_OK(status)) { return status; } if (fsp) { return store_acl_blob_fsp(handle, fsp, &blob); } else { return store_acl_blob_pathname(handle, fname, &blob); } }
static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *orig_psd) { NTSTATUS status; DATA_BLOB blob; struct security_descriptor *pdesc_next = NULL; struct security_descriptor *psd = NULL; uint8_t hash[XATTR_SD_HASH_SIZE]; bool chown_needed = false; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, discard_const_p(struct security_descriptor, orig_psd)); } status = get_nt_acl_internal(handle, fsp, NULL, SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL, &psd); if (!NT_STATUS_IS_OK(status)) { return status; } psd->revision = orig_psd->revision; /* All our SD's are self relative. */ psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE; if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) { if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) { /* We're changing the owner. */ chown_needed = true; } psd->owner_sid = orig_psd->owner_sid; } if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) { if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) { /* We're changing the group. */ chown_needed = true; } psd->group_sid = orig_psd->group_sid; } if (security_info_sent & SECINFO_DACL) { psd->dacl = orig_psd->dacl; psd->type |= SEC_DESC_DACL_PRESENT; } if (security_info_sent & SECINFO_SACL) { psd->sacl = orig_psd->sacl; psd->type |= SEC_DESC_SACL_PRESENT; } status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { return status; } /* We got access denied here. If we're already root, or we didn't need to do a chown, or the fsp isn't open with WRITE_OWNER access, just return. */ if (get_current_uid(handle->conn) == 0 || chown_needed == false || !(fsp->access_mask & SEC_STD_WRITE_OWNER)) { return NT_STATUS_ACCESS_DENIED; } DEBUG(10,("fset_nt_acl_common: overriding chown on file %s " "for sid %s\n", fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid) )); /* Ok, we failed to chown and we have SEC_STD_WRITE_OWNER access - override. */ become_root(); status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; } } /* Get the full underlying sd, then hash. */ status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, HASH_SECURITY_INFO, &pdesc_next); if (!NT_STATUS_IS_OK(status)) { return status; } status = hash_sd_sha256(pdesc_next, hash); if (!NT_STATUS_IS_OK(status)) { return status; } if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, discard_const_p(struct security_descriptor, psd)); } create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; }