+static NTSTATUS append_ugw_ace(files_struct *fsp,
+ SMB_STRUCT_STAT *psbuf,
+ mode_t unx_mode,
+ int ugw,
+ SEC_ACE *se)
+{
+ mode_t perms;
+ SEC_ACCESS acc;
+ int nt_acl_type;
+ DOM_SID trustee;
+
+ switch (ugw) {
+ case S_IRUSR:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IRUSR,
+ S_IWUSR,
+ S_IXUSR);
+ uid_to_sid(&trustee, psbuf->st_uid );
+ break;
+ case S_IRGRP:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IRGRP,
+ S_IWGRP,
+ S_IXGRP);
+ gid_to_sid(&trustee, psbuf->st_gid );
+ break;
+ case S_IROTH:
+ perms = unix_perms_to_acl_perms(unx_mode,
+ S_IROTH,
+ S_IWOTH,
+ S_IXOTH);
+ sid_copy(&trustee, &global_sid_World);
+ break;
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ acc = map_canon_ace_perms(SNUM(fsp->conn),
+ &nt_acl_type,
+ perms,
+ fsp->is_directory);
+
+ init_sec_ace(se,
+ &trustee,
+ nt_acl_type,
+ acc,
+ 0);
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ If this is an
+****************************************************************************/
+
+static NTSTATUS append_parent_acl(files_struct *fsp,
+ SMB_STRUCT_STAT *psbuf,
+ SEC_DESC *psd,
+ SEC_DESC **pp_new_sd)
+{
+ SEC_DESC *parent_sd = NULL;
+ files_struct *parent_fsp = NULL;
+ TALLOC_CTX *mem_ctx = talloc_parent(psd);
+ char *parent_name = NULL;
+ SEC_ACE *new_ace = NULL;
+ unsigned int num_aces = psd->dacl->num_aces;
+ SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
+ int info;
+ size_t sd_size;
+ unsigned int i, j;
+ mode_t unx_mode;
+
+ ZERO_STRUCT(sbuf);
+
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!parent_dirname_talloc(mem_ctx,
+ fsp->fsp_name,
+ &parent_name,
+ NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Create a default mode for u/g/w. */
+ unx_mode = unix_mode(fsp->conn,
+ aARCH | (fsp->is_directory ? aDIR : 0),
+ fsp->fsp_name,
+ parent_name);
+
+ status = open_directory(fsp->conn,
+ NULL,
+ parent_name,
+ &sbuf,
+ FILE_READ_ATTRIBUTES, /* Just a stat open */
+ FILE_SHARE_NONE, /* Ignored for stat opens */
+ FILE_OPEN,
+ 0,
+ INTERNAL_OPEN_ONLY,
+ &info,
+ &parent_fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ sd_size = SMB_VFS_GET_NT_ACL(parent_fsp, parent_fsp->fsp_name,
+ DACL_SECURITY_INFORMATION, &parent_sd );
+
+ close_file(parent_fsp, NORMAL_CLOSE);
+
+ if (!sd_size) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /*
+ * Make room for potentially all the ACLs from
+ * the parent, plus the user/group/other triple.
+ */
+
+ num_aces += parent_sd->dacl->num_aces + 3;
+
+ if((new_ace = TALLOC_ZERO_ARRAY(mem_ctx, SEC_ACE,
+ num_aces)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10,("append_parent_acl: parent ACL has %u entries. New "
+ "ACL has %u entries\n",
+ parent_sd->dacl->num_aces, num_aces ));
+
+ /* Start by copying in all the given ACE entries. */
+ for (i = 0; i < psd->dacl->num_aces; i++) {
+ sec_ace_copy(&new_ace[i], &psd->dacl->aces[i]);
+ }
+
+ /*
+ * Note that we're ignoring "inherit permissions" here
+ * as that really only applies to newly created files. JRA.
+ */
+
+ /*
+ * Append u/g/w.
+ */
+
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRUSR, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IRGRP, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = append_ugw_ace(fsp, psbuf, unx_mode, S_IROTH, &new_ace[i++]);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Finally append any inherited ACEs. */
+ for (j = 0; j < parent_sd->dacl->num_aces; j++) {
+ SEC_ACE *se = &parent_sd->dacl->aces[j];
+ uint32 i_flags = se->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
+ SEC_ACE_FLAG_CONTAINER_INHERIT|
+ SEC_ACE_FLAG_INHERIT_ONLY);
+
+ if (fsp->is_directory) {
+ if (i_flags == SEC_ACE_FLAG_OBJECT_INHERIT) {
+ /* Should only apply to a file - ignore. */
+ continue;
+ }
+ } else {
+ if ((i_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
+ SEC_ACE_FLAG_INHERIT_ONLY)) !=
+ SEC_ACE_FLAG_OBJECT_INHERIT) {
+ /* Should not apply to a file - ignore. */
+ continue;
+ }
+ }
+ sec_ace_copy(&new_ace[i], se);
+ if (se->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
+ new_ace[i].flags &= ~(SEC_ACE_FLAG_VALID_INHERIT);
+ }
+ new_ace[i].flags |= SEC_ACE_FLAG_INHERITED_ACE;
+ i++;
+ }
+
+ parent_sd->dacl->aces = new_ace;
+ parent_sd->dacl->num_aces = i;
+
+ *pp_new_sd = parent_sd;
+ return status;
+}
+