s3/smbd: make make_default_filesystem_acl public
[kai/samba-autobuild/.git] / source3 / smbd / posix_acls.c
index 7bd653904065771061692dc41c34c02674c176b2..7337c5e8ecb31a210b327a9286219dcf32bf6f3c 100644 (file)
@@ -4857,3 +4857,219 @@ int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle,
        TALLOC_FREE(frame);
        return 0;
 }
+
+static NTSTATUS make_default_acl_posix(TALLOC_CTX *ctx,
+                                      const char *name,
+                                      SMB_STRUCT_STAT *psbuf,
+                                      struct security_descriptor **ppdesc)
+{
+       struct dom_sid owner_sid, group_sid;
+       size_t size = 0;
+       struct security_ace aces[4];
+       uint32_t access_mask = 0;
+       mode_t mode = psbuf->st_ex_mode;
+       struct security_acl *new_dacl = NULL;
+       int idx = 0;
+
+       DBG_DEBUG("file %s mode = 0%o\n",name, (int)mode);
+
+       uid_to_sid(&owner_sid, psbuf->st_ex_uid);
+       gid_to_sid(&group_sid, psbuf->st_ex_gid);
+
+       /*
+        We provide up to 4 ACEs
+               - Owner
+               - Group
+               - Everyone
+               - NT System
+       */
+
+       if (mode & S_IRUSR) {
+               if (mode & S_IWUSR) {
+                       access_mask |= SEC_RIGHTS_FILE_ALL;
+               } else {
+                       access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+               }
+       }
+       if (mode & S_IWUSR) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
+       }
+
+       init_sec_ace(&aces[idx],
+                       &owner_sid,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+       idx++;
+
+       access_mask = 0;
+       if (mode & S_IRGRP) {
+               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+       }
+       if (mode & S_IWGRP) {
+               /* note that delete is not granted - this matches posix behaviour */
+               access_mask |= SEC_RIGHTS_FILE_WRITE;
+       }
+       if (access_mask) {
+               init_sec_ace(&aces[idx],
+                       &group_sid,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+               idx++;
+       }
+
+       access_mask = 0;
+       if (mode & S_IROTH) {
+               access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+       }
+       if (mode & S_IWOTH) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE;
+       }
+       if (access_mask) {
+               init_sec_ace(&aces[idx],
+                       &global_sid_World,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       access_mask,
+                       0);
+               idx++;
+       }
+
+       init_sec_ace(&aces[idx],
+                       &global_sid_System,
+                       SEC_ACE_TYPE_ACCESS_ALLOWED,
+                       SEC_RIGHTS_FILE_ALL,
+                       0);
+       idx++;
+
+       new_dacl = make_sec_acl(ctx,
+                       NT4_ACL_REVISION,
+                       idx,
+                       aces);
+
+       if (!new_dacl) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *ppdesc = make_sec_desc(ctx,
+                       SECURITY_DESCRIPTOR_REVISION_1,
+                       SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
+                       &owner_sid,
+                       &group_sid,
+                       NULL,
+                       new_dacl,
+                       &size);
+       if (!*ppdesc) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx,
+                                        const char *name,
+                                        SMB_STRUCT_STAT *psbuf,
+                                        struct security_descriptor **ppdesc)
+{
+       struct dom_sid owner_sid, group_sid;
+       size_t size = 0;
+       struct security_ace aces[4];
+       uint32_t access_mask = 0;
+       mode_t mode = psbuf->st_ex_mode;
+       struct security_acl *new_dacl = NULL;
+       int idx = 0;
+
+       DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode);
+
+       uid_to_sid(&owner_sid, psbuf->st_ex_uid);
+       gid_to_sid(&group_sid, psbuf->st_ex_gid);
+
+       /*
+        * We provide 2 ACEs:
+        * - Owner
+        * - NT System
+        */
+
+       if (mode & S_IRUSR) {
+               if (mode & S_IWUSR) {
+                       access_mask |= SEC_RIGHTS_FILE_ALL;
+               } else {
+                       access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
+               }
+       }
+       if (mode & S_IWUSR) {
+               access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
+       }
+
+       init_sec_ace(&aces[idx],
+                    &owner_sid,
+                    SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    access_mask,
+                    0);
+       idx++;
+
+       init_sec_ace(&aces[idx],
+                    &global_sid_System,
+                    SEC_ACE_TYPE_ACCESS_ALLOWED,
+                    SEC_RIGHTS_FILE_ALL,
+                    0);
+       idx++;
+
+       new_dacl = make_sec_acl(ctx,
+                               NT4_ACL_REVISION,
+                               idx,
+                               aces);
+
+       if (!new_dacl) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *ppdesc = make_sec_desc(ctx,
+                               SECURITY_DESCRIPTOR_REVISION_1,
+                               SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
+                               &owner_sid,
+                               &group_sid,
+                               NULL,
+                               new_dacl,
+                               &size);
+       if (!*ppdesc) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       return NT_STATUS_OK;
+}
+
+static const struct enum_list default_acl_style_list[] = {
+       {DEFAULT_ACL_POSIX,     "posix"},
+       {DEFAULT_ACL_WINDOWS,   "windows"}
+};
+
+const struct enum_list *get_default_acl_style_list(void)
+{
+       return default_acl_style_list;
+}
+
+NTSTATUS make_default_filesystem_acl(
+       TALLOC_CTX *ctx,
+       enum default_acl_style acl_style,
+       const char *name,
+       SMB_STRUCT_STAT *psbuf,
+       struct security_descriptor **ppdesc)
+{
+       NTSTATUS status;
+
+       switch (acl_style) {
+       case DEFAULT_ACL_POSIX:
+               status =  make_default_acl_posix(ctx, name, psbuf, ppdesc);
+               break;
+
+       case DEFAULT_ACL_WINDOWS:
+               status =  make_default_acl_windows(ctx, name, psbuf, ppdesc);
+               break;
+
+       default:
+               DBG_ERR("unknown acl style %d", acl_style);
+               status = NT_STATUS_INTERNAL_ERROR;
+               break;
+       }
+
+       return status;
+}