summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/open.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 95b980f99a..5cda44c930 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3185,6 +3185,109 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
return status;
}
+/*********************************************************************
+ Create a default ACL by inheriting from the parent. If no inheritance
+ from the parent available, don't set anything. This will leave the actual
+ permissions the new file or directory already got from the filesystem
+ as the NT ACL when read.
+*********************************************************************/
+
+static NTSTATUS inherit_new_acl(files_struct *fsp)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ char *parent_name = NULL;
+ struct security_descriptor *parent_desc = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+ struct security_descriptor *psd = NULL;
+ struct dom_sid *owner_sid = NULL;
+ struct dom_sid *group_sid = NULL;
+ uint32_t security_info_sent = (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL);
+ bool inherit_owner = lp_inherit_owner(SNUM(fsp->conn));
+ bool inheritable_components = false;
+ size_t size = 0;
+
+ if (!parent_dirname(ctx, fsp->fsp_name->base_name, &parent_name, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = SMB_VFS_GET_NT_ACL(fsp->conn,
+ parent_name,
+ (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL),
+ &parent_desc);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ inheritable_components = sd_has_inheritable_components(parent_desc,
+ fsp->is_directory);
+
+ if (!inheritable_components && !inherit_owner) {
+ /* Nothing to inherit and not setting owner. */
+ return NT_STATUS_OK;
+ }
+
+ /* Create an inherited descriptor from the parent. */
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("inherit_new_acl: parent acl for %s is:\n",
+ fsp_str_dbg(fsp) ));
+ NDR_PRINT_DEBUG(security_descriptor, parent_desc);
+ }
+
+ /* Inherit from parent descriptor if "inherit owner" set. */
+ if (inherit_owner) {
+ owner_sid = parent_desc->owner_sid;
+ group_sid = parent_desc->group_sid;
+ }
+
+ if (owner_sid == NULL) {
+ owner_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
+ }
+ if (group_sid == NULL) {
+ group_sid = &fsp->conn->session_info->security_token->sids[PRIMARY_GROUP_SID_INDEX];
+ }
+
+ status = se_create_child_secdesc(ctx,
+ &psd,
+ &size,
+ parent_desc,
+ owner_sid,
+ group_sid,
+ fsp->is_directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* If inheritable_components == false,
+ se_create_child_secdesc()
+ creates a security desriptor with a NULL dacl
+ entry, but with SEC_DESC_DACL_PRESENT. We need
+ to remove that flag. */
+
+ if (!inheritable_components) {
+ security_info_sent &= ~SECINFO_DACL;
+ psd->type &= ~SEC_DESC_DACL_PRESENT;
+ }
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("inherit_new_acl: child acl for %s is:\n",
+ fsp_str_dbg(fsp) ));
+ NDR_PRINT_DEBUG(security_descriptor, psd);
+ }
+
+ if (inherit_owner) {
+ /* We need to be root to force this. */
+ become_root();
+ }
+ status = SMB_VFS_FSET_NT_ACL(fsp,
+ security_info_sent,
+ psd);
+ if (inherit_owner) {
+ unbecome_root();
+ }
+ return status;
+}
+
/*
* Wrapper around open_file_ntcreate and open_directory
*/
@@ -3495,7 +3598,13 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
goto fail;
}
} else if (lp_inherit_acls(SNUM(conn))) {
- /* Inherit from parent. */
+ /* Inherit from parent. Errors here are not fatal. */
+ status = inherit_new_acl(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("inherit_new_acl: failed for %s with %s\n",
+ fsp_str_dbg(fsp),
+ nt_errstr(status) ));
+ }
}
}