mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Add hash values to the xattr ACLS to determine when
an underlying POSIX ACL is changed out from under us. Passes RAW-ACL test up to "invalid owner" problem when trying to create a file owned by Everyone. Now needs porting to modules/vfs_acl_tdb.c Jeremy.
This commit is contained in:
parent
afc6f607d5
commit
361aa19e69
@ -27,13 +27,45 @@
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_VFS
|
||||
|
||||
static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
|
||||
DATA_BLOB *pblob,
|
||||
uint8_t hash[16]);
|
||||
|
||||
#define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \
|
||||
GROUP_SECURITY_INFORMATION | \
|
||||
DACL_SECURITY_INFORMATION | \
|
||||
SACL_SECURITY_INFORMATION)
|
||||
|
||||
/*******************************************************************
|
||||
Hash a security descriptor.
|
||||
*******************************************************************/
|
||||
|
||||
static NTSTATUS hash_sd(struct security_descriptor *psd,
|
||||
uint8_t hash[16])
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
struct MD5Context tctx;
|
||||
NTSTATUS status;
|
||||
|
||||
memset(hash, '\0', 16);
|
||||
status = create_acl_blob(psd, &blob, hash);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, blob.data, blob.length);
|
||||
MD5Final(hash, &tctx);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Parse out a struct security_descriptor from a DATA_BLOB.
|
||||
*******************************************************************/
|
||||
|
||||
static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
|
||||
uint32 security_info,
|
||||
struct security_descriptor **ppdesc)
|
||||
struct security_descriptor **ppdesc,
|
||||
uint8_t hash[16])
|
||||
{
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
struct xattr_NTACL xacl;
|
||||
@ -64,6 +96,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
|
||||
? xacl.info.sd_hs->sd->dacl : NULL,
|
||||
&sd_size);
|
||||
|
||||
memcpy(hash, xacl.info.sd_hs->hash, 16);
|
||||
TALLOC_FREE(xacl.info.sd);
|
||||
|
||||
return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
|
||||
@ -131,7 +164,9 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
|
||||
Create a DATA_BLOB from a security descriptor.
|
||||
*******************************************************************/
|
||||
|
||||
static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob)
|
||||
static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
|
||||
DATA_BLOB *pblob,
|
||||
uint8_t hash[16])
|
||||
{
|
||||
struct xattr_NTACL xacl;
|
||||
struct security_descriptor_hash sd_hs;
|
||||
@ -144,7 +179,7 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB
|
||||
xacl.version = 2;
|
||||
xacl.info.sd_hs = &sd_hs;
|
||||
xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd);
|
||||
memset(&xacl.info.sd_hs->hash[0], '\0', 16);
|
||||
memcpy(&xacl.info.sd_hs->hash[0], hash, 16);
|
||||
|
||||
ndr_err = ndr_push_struct_blob(
|
||||
pblob, ctx, NULL, &xacl,
|
||||
@ -242,9 +277,11 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
|
||||
uint32 security_info,
|
||||
struct security_descriptor **ppdesc)
|
||||
{
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
DATA_BLOB blob;
|
||||
NTSTATUS status;
|
||||
uint8_t hash[16];
|
||||
uint8_t hash_tmp[16];
|
||||
struct security_descriptor *pdesc_next = NULL;
|
||||
|
||||
if (fsp && name == NULL) {
|
||||
name = fsp->fsp_name;
|
||||
@ -252,19 +289,74 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
|
||||
|
||||
DEBUG(10, ("get_nt_acl_xattr_internal: name=%s\n", name));
|
||||
|
||||
status = get_acl_blob(ctx, handle, fsp, name, &blob);
|
||||
status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status)));
|
||||
return status;
|
||||
}
|
||||
|
||||
status = parse_acl_blob(&blob, security_info, ppdesc);
|
||||
status = parse_acl_blob(&blob, security_info, ppdesc, &hash[0]);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10, ("parse_acl_blob returned %s\n",
|
||||
nt_errstr(status)));
|
||||
return status;
|
||||
}
|
||||
|
||||
/* If there was no stored hash, don't check. */
|
||||
memset(&hash_tmp[0], '\0', 16);
|
||||
if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) {
|
||||
/* No hash, goto return blob sd. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the full underlying sd, then hash. */
|
||||
if (fsp) {
|
||||
status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
|
||||
fsp,
|
||||
HASH_SECURITY_INFO,
|
||||
&pdesc_next);
|
||||
} else {
|
||||
status = SMB_VFS_NEXT_GET_NT_ACL(handle,
|
||||
name,
|
||||
HASH_SECURITY_INFO,
|
||||
&pdesc_next);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = hash_sd(pdesc_next, hash_tmp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) {
|
||||
TALLOC_FREE(pdesc_next);
|
||||
/* Hash matches, return blob sd. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Hash doesn't match, return underlying sd. */
|
||||
|
||||
if (!(security_info & OWNER_SECURITY_INFORMATION)) {
|
||||
pdesc_next->owner_sid = NULL;
|
||||
}
|
||||
if (!(security_info & GROUP_SECURITY_INFORMATION)) {
|
||||
pdesc_next->group_sid = NULL;
|
||||
}
|
||||
if (!(security_info & DACL_SECURITY_INFORMATION)) {
|
||||
pdesc_next->dacl = NULL;
|
||||
}
|
||||
if (!(security_info & SACL_SECURITY_INFORMATION)) {
|
||||
pdesc_next->sacl = NULL;
|
||||
}
|
||||
|
||||
TALLOC_FREE(*ppdesc);
|
||||
*ppdesc = pdesc_next;
|
||||
|
||||
out:
|
||||
|
||||
TALLOC_FREE(blob.data);
|
||||
return status;
|
||||
}
|
||||
@ -324,9 +416,11 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
|
||||
NTSTATUS status;
|
||||
struct security_descriptor *parent_desc = NULL;
|
||||
struct security_descriptor *psd = NULL;
|
||||
struct security_descriptor *pdesc_next = NULL;
|
||||
DATA_BLOB blob;
|
||||
size_t size;
|
||||
char *parent_name;
|
||||
uint8_t hash[16];
|
||||
|
||||
if (!parent_dirname(ctx, fname, &parent_name, NULL)) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
@ -382,11 +476,9 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
|
||||
ret = SMB_VFS_FSTAT(fsp, &sbuf);
|
||||
} else {
|
||||
if (fsp && fsp->posix_open) {
|
||||
ret = vfs_lstat_smb_fname(handle->conn, fname,
|
||||
&sbuf);
|
||||
ret = vfs_lstat_smb_fname(handle->conn,fname, &sbuf);
|
||||
} else {
|
||||
ret = vfs_stat_smb_fname(handle->conn, fname,
|
||||
&sbuf);
|
||||
ret = vfs_stat_smb_fname(handle->conn,fname, &sbuf);
|
||||
}
|
||||
}
|
||||
if (ret == -1) {
|
||||
@ -403,7 +495,28 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
|
||||
}
|
||||
}
|
||||
|
||||
status = create_acl_blob(psd, &blob);
|
||||
/* Object exists. Read the current SD to get the hash. */
|
||||
if (fsp) {
|
||||
status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
|
||||
fsp,
|
||||
HASH_SECURITY_INFO,
|
||||
&pdesc_next);
|
||||
} else {
|
||||
status = SMB_VFS_NEXT_GET_NT_ACL(handle,
|
||||
fname,
|
||||
HASH_SECURITY_INFO,
|
||||
&pdesc_next);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = hash_sd(pdesc_next, hash);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
status = create_acl_blob(psd, &blob, hash);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
@ -430,6 +543,13 @@ static int open_acl_xattr(vfs_handle_struct *handle,
|
||||
char *fname = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (fsp->base_fsp) {
|
||||
/* Stream open. Base filename open already did the ACL check. */
|
||||
DEBUG(10,("open_acl_xattr: stream open on %s\n",
|
||||
smb_fname_str_dbg(smb_fname) ));
|
||||
return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
|
||||
}
|
||||
|
||||
status = get_full_smb_filename(talloc_tos(), smb_fname,
|
||||
&fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -497,23 +617,8 @@ static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t m
|
||||
static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
uint32 security_info, struct security_descriptor **ppdesc)
|
||||
{
|
||||
NTSTATUS status = get_nt_acl_xattr_internal(handle, fsp,
|
||||
return get_nt_acl_xattr_internal(handle, fsp,
|
||||
NULL, security_info, ppdesc);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
if (DEBUGLEVEL >= 10) {
|
||||
DEBUG(10,("fget_nt_acl_xattr: returning xattr sd for file %s\n",
|
||||
fsp->fsp_name));
|
||||
NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
DEBUG(10,("fget_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
|
||||
fsp->fsp_name,
|
||||
nt_errstr(status) ));
|
||||
|
||||
return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp,
|
||||
security_info, ppdesc);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
@ -523,23 +628,8 @@ static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
|
||||
const char *name, uint32 security_info, struct security_descriptor **ppdesc)
|
||||
{
|
||||
NTSTATUS status = get_nt_acl_xattr_internal(handle, NULL,
|
||||
return get_nt_acl_xattr_internal(handle, NULL,
|
||||
name, security_info, ppdesc);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
if (DEBUGLEVEL >= 10) {
|
||||
DEBUG(10,("get_nt_acl_xattr: returning xattr sd for file %s\n",
|
||||
name));
|
||||
NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
DEBUG(10,("get_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
|
||||
name,
|
||||
nt_errstr(status) ));
|
||||
|
||||
return SMB_VFS_NEXT_GET_NT_ACL(handle, name,
|
||||
security_info, ppdesc);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
@ -551,6 +641,8 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
{
|
||||
NTSTATUS status;
|
||||
DATA_BLOB blob;
|
||||
struct security_descriptor *pdesc_next = NULL;
|
||||
uint8_t hash[16];
|
||||
|
||||
if (DEBUGLEVEL >= 10) {
|
||||
DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
|
||||
@ -559,11 +651,6 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
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;
|
||||
@ -576,13 +663,9 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
}
|
||||
if (fsp->is_directory || fsp->fh->fd == -1) {
|
||||
if (fsp->posix_open) {
|
||||
ret = vfs_lstat_smb_fname(fsp->conn,
|
||||
fsp->fsp_name,
|
||||
&sbuf);
|
||||
ret = vfs_lstat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf);
|
||||
} else {
|
||||
ret = vfs_stat_smb_fname(fsp->conn,
|
||||
fsp->fsp_name,
|
||||
&sbuf);
|
||||
ret = vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf);
|
||||
}
|
||||
} else {
|
||||
ret = SMB_VFS_FSTAT(fsp, &sbuf);
|
||||
@ -600,6 +683,26 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
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(pdesc_next, hash);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
|
||||
psd->dacl != NULL &&
|
||||
@ -624,7 +727,7 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
|
||||
NDR_PRINT_DEBUG(security_descriptor,
|
||||
CONST_DISCARD(struct security_descriptor *,psd));
|
||||
}
|
||||
create_acl_blob(psd, &blob);
|
||||
create_acl_blob(psd, &blob, hash);
|
||||
store_acl_blob_fsp(handle, fsp, &blob);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user