mirror of
https://github.com/samba-team/samba.git
synced 2025-12-03 04:23:50 +03:00
680 lines
16 KiB
C
680 lines
16 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
SMB NT Security Descriptor / Unix permission conversion.
|
|
Copyright (C) Jeremy Allison 1994-2000
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "rpc_parse.h"
|
|
#include "sids.h"
|
|
|
|
#ifndef WITH_SURS
|
|
extern DOM_SID global_sid_World;
|
|
#define global_sid_everyone &global_sid_World
|
|
#endif
|
|
|
|
|
|
/****************************************************************************
|
|
Map unix perms to NT.
|
|
****************************************************************************/
|
|
|
|
static SEC_ACCESS map_unix_perms(int *pacl_type, mode_t perm, int r_mask,
|
|
int w_mask, int x_mask, BOOL is_directory)
|
|
{
|
|
SEC_ACCESS sa;
|
|
uint32 nt_mask = 0;
|
|
|
|
*pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
|
|
|
|
if ((perm & (r_mask | w_mask | x_mask)) == (r_mask | w_mask | x_mask))
|
|
{
|
|
nt_mask = UNIX_ACCESS_RWX;
|
|
}
|
|
else if ((perm & (r_mask | w_mask | x_mask)) == 0)
|
|
{
|
|
nt_mask = UNIX_ACCESS_NONE;
|
|
}
|
|
else
|
|
{
|
|
nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0;
|
|
if (is_directory)
|
|
nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0;
|
|
else
|
|
nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0;
|
|
nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0;
|
|
}
|
|
make_sec_access(&sa, nt_mask);
|
|
return sa;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
|
|
****************************************************************************/
|
|
|
|
static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf,
|
|
DOM_SID *powner_sid, DOM_SID *pgroup_sid)
|
|
{
|
|
extern DOM_SID global_sam_sid;
|
|
|
|
sid_copy(powner_sid, &global_sam_sid);
|
|
sid_copy(pgroup_sid, &global_sam_sid);
|
|
sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid));
|
|
sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid));
|
|
return True;
|
|
}
|
|
|
|
#ifdef WITH_SURS
|
|
static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf,
|
|
DOM_SID *powner_sid, DOM_SID *pgroup_sid)
|
|
{
|
|
SURS_POSIX_ID id;
|
|
|
|
ZERO_STRUCTP(powner_sid);
|
|
ZERO_STRUCTP(pgroup_sid);
|
|
DEBUG(0, ("TODO: create_file_sids: not ok "
|
|
"to assume gid is NT group\n"));
|
|
|
|
id.type = SURS_POSIX_UID;
|
|
id.id = (uint32)psbuf->st_uid;
|
|
|
|
if (!surs_unixid_to_sam_sid(&id, powner_sid, False))
|
|
{
|
|
DEBUG(3, ("create_file_sids: map uid %d failed\n",
|
|
(int)psbuf->st_uid));
|
|
return False;
|
|
}
|
|
|
|
id.type = SURS_POSIX_GID;
|
|
id.id = (uint32)psbuf->st_gid;
|
|
|
|
if (!surs_unixid_to_sam_sid(&id, pgroup_sid, False))
|
|
{
|
|
DEBUG(3, ("create_file_sids: map gid %d failed\n",
|
|
(int)psbuf->st_gid));
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Reply to query a security descriptor from an fsp. If it succeeds it allocates
|
|
the space for the return elements and returns True.
|
|
****************************************************************************/
|
|
|
|
size_t convertperms_unix_to_sd(const SMB_STRUCT_STAT * sbuf,
|
|
BOOL is_directory, mode_t mode,
|
|
SEC_DESC ** ppdesc)
|
|
{
|
|
SEC_ACE *ace_list = NULL;
|
|
DOM_SID owner_sid;
|
|
DOM_SID group_sid;
|
|
size_t sec_desc_size;
|
|
SEC_ACL *psa = NULL;
|
|
SEC_ACCESS owner_access;
|
|
int owner_acl_type;
|
|
SEC_ACCESS group_access;
|
|
int grp_acl_type;
|
|
SEC_ACCESS other_access;
|
|
int other_acl_type;
|
|
int num_acls = 0;
|
|
|
|
(*ppdesc) = NULL;
|
|
|
|
if (!lp_nt_acl_support())
|
|
{
|
|
sid_copy(&owner_sid, global_sid_everyone);
|
|
sid_copy(&group_sid, global_sid_everyone);
|
|
}
|
|
else
|
|
{
|
|
if (!create_file_sids(sbuf, &owner_sid, &group_sid))
|
|
{
|
|
DEBUG(3, ("create_file_sids: uid or gid "
|
|
"not mapped to SIDS\n"));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Create the generic 3 element UNIX acl.
|
|
*/
|
|
|
|
owner_access = map_unix_perms(&owner_acl_type, sbuf->st_mode,
|
|
S_IRUSR, S_IWUSR, S_IXUSR,
|
|
is_directory);
|
|
group_access = map_unix_perms(&grp_acl_type, sbuf->st_mode,
|
|
S_IRGRP, S_IWGRP, S_IXGRP,
|
|
is_directory);
|
|
other_access = map_unix_perms(&other_acl_type, sbuf->st_mode,
|
|
S_IROTH, S_IWOTH, S_IXOTH,
|
|
is_directory);
|
|
|
|
if (owner_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
make_sec_ace(&ace_list[num_acls++], &owner_sid,
|
|
owner_acl_type, owner_access, 0);
|
|
}
|
|
|
|
if (group_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
make_sec_ace(&ace_list[num_acls++], &group_sid,
|
|
grp_acl_type, group_access, 0);
|
|
}
|
|
|
|
if (other_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
make_sec_ace(&ace_list[num_acls++],
|
|
global_sid_everyone, other_acl_type,
|
|
other_access, 0);
|
|
}
|
|
|
|
if (is_directory)
|
|
{
|
|
/*
|
|
* For directory ACLs we also add in the
|
|
* inherited permissions ACE entries. These
|
|
* are the permissions a file would get when
|
|
* being created in the directory.
|
|
*/
|
|
|
|
owner_access = map_unix_perms(&owner_acl_type, mode,
|
|
S_IRUSR, S_IWUSR,
|
|
S_IXUSR, is_directory);
|
|
group_access = map_unix_perms(&grp_acl_type,
|
|
mode, S_IRGRP,
|
|
S_IWGRP, S_IXGRP,
|
|
is_directory);
|
|
other_access = map_unix_perms(&other_acl_type,
|
|
mode, S_IROTH,
|
|
S_IWOTH, S_IXOTH,
|
|
is_directory);
|
|
|
|
if (owner_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list,
|
|
num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
make_sec_ace(&ace_list[num_acls++],
|
|
&owner_sid, owner_acl_type,
|
|
owner_access,
|
|
SEC_ACE_FLAG_OBJECT_INHERIT |
|
|
SEC_ACE_FLAG_INHERIT_ONLY);
|
|
}
|
|
|
|
if (group_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list,
|
|
num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
make_sec_ace(&ace_list[num_acls++],
|
|
&group_sid, grp_acl_type,
|
|
group_access,
|
|
SEC_ACE_FLAG_OBJECT_INHERIT |
|
|
SEC_ACE_FLAG_INHERIT_ONLY);
|
|
}
|
|
|
|
if (other_access.mask)
|
|
{
|
|
ace_list = g_renew(SEC_ACE, ace_list,
|
|
num_acls + 1);
|
|
if (ace_list == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
make_sec_ace(&ace_list[num_acls++],
|
|
global_sid_everyone,
|
|
other_acl_type, other_access,
|
|
SEC_ACE_FLAG_OBJECT_INHERIT |
|
|
SEC_ACE_FLAG_INHERIT_ONLY);
|
|
}
|
|
}
|
|
|
|
if (num_acls)
|
|
{
|
|
psa = g_new(SEC_ACL, 1);
|
|
if (psa == NULL)
|
|
{
|
|
safe_free(ace_list);
|
|
}
|
|
if (!make_sec_acl(psa, 2, num_acls, ace_list))
|
|
{
|
|
DEBUG(0, ("get_nt_acl: Unable to malloc "
|
|
"space for acl.\n"));
|
|
safe_free(ace_list);
|
|
safe_free(psa);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
(*ppdesc) = g_new(SEC_DESC, 1);
|
|
|
|
if ((*ppdesc) == NULL)
|
|
{
|
|
DEBUG(0, ("get_nt_acl: Unable to malloc space "
|
|
"for security descriptor.\n"));
|
|
sec_desc_size = 0;
|
|
free_sec_acl(psa);
|
|
safe_free(psa);
|
|
return 0;
|
|
}
|
|
|
|
sec_desc_size = make_sec_desc((*ppdesc), 1,
|
|
SEC_DESC_SELF_RELATIVE |
|
|
SEC_DESC_DACL_PRESENT,
|
|
sid_dup(&owner_sid),
|
|
sid_dup(&group_sid), NULL, psa);
|
|
|
|
return sec_desc_size;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Map NT perms to UNIX.
|
|
****************************************************************************/
|
|
|
|
#define FILE_SPECIFIC_READ_BITS \
|
|
(FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
|
|
#define FILE_SPECIFIC_WRITE_BITS \
|
|
(FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
|
|
#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
|
|
|
|
#define PRINT_SPECIFIC_READ_BITS (PRINTER_READ)
|
|
#define PRINT_SPECIFIC_WRITE_BITS (PRINTER_READ)
|
|
#define PRINT_SPECIFIC_EXECUTE_BITS (PRINTER_ALL_ACCESS)
|
|
|
|
static mode_t map_nt_perms(SEC_ACCESS sec_access, int type)
|
|
{
|
|
uint32 write_bits;
|
|
uint32 read_bits;
|
|
uint32 execute_bits;
|
|
mode_t mode = 0;
|
|
|
|
write_bits = FILE_SPECIFIC_WRITE_BITS;
|
|
read_bits = FILE_SPECIFIC_READ_BITS;
|
|
execute_bits = FILE_SPECIFIC_EXECUTE_BITS;
|
|
|
|
switch (type)
|
|
{
|
|
case S_IRUSR:
|
|
if (sec_access.mask & GENERIC_ALL_ACCESS)
|
|
mode = S_IRUSR | S_IWUSR | S_IXUSR;
|
|
else
|
|
{
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_READ_ACCESS |
|
|
read_bits)) ? S_IRUSR : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_WRITE_ACCESS |
|
|
write_bits)) ? S_IWUSR : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_EXECUTE_ACCESS |
|
|
execute_bits)) ? S_IXUSR : 0;
|
|
}
|
|
break;
|
|
case S_IRGRP:
|
|
if (sec_access.mask & GENERIC_ALL_ACCESS)
|
|
mode = S_IRGRP | S_IWGRP | S_IXGRP;
|
|
else
|
|
{
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_READ_ACCESS |
|
|
read_bits)) ? S_IRGRP : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_WRITE_ACCESS |
|
|
write_bits)) ? S_IWGRP : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_EXECUTE_ACCESS |
|
|
execute_bits)) ? S_IXGRP : 0;
|
|
}
|
|
break;
|
|
case S_IROTH:
|
|
if (sec_access.mask & GENERIC_ALL_ACCESS)
|
|
mode = S_IROTH | S_IWOTH | S_IXOTH;
|
|
else
|
|
{
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_READ_ACCESS |
|
|
read_bits)) ? S_IROTH : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_WRITE_ACCESS |
|
|
write_bits)) ? S_IWOTH : 0;
|
|
mode |=
|
|
(sec_access.mask &
|
|
(GENERIC_EXECUTE_ACCESS |
|
|
execute_bits)) ? S_IXOTH : 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return mode;
|
|
}
|
|
|
|
#ifndef WITH_SURS
|
|
/****************************************************************************
|
|
Validate a SID.
|
|
****************************************************************************/
|
|
static BOOL validate_unix_sid(DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid)
|
|
{
|
|
extern DOM_SID global_sam_sid;
|
|
DOM_SID sid;
|
|
|
|
if (!sd_sid)
|
|
{
|
|
DEBUG(5, ("validate_unix_sid: sid missing.\n"));
|
|
return False;
|
|
}
|
|
|
|
sid_copy(psid, sd_sid);
|
|
sid_copy(&sid, sd_sid);
|
|
|
|
if (!sid_split_rid(&sid, prid))
|
|
{
|
|
DEBUG(5, ("validate_unix_sid: cannot get RID from sid.\n"));
|
|
return False;
|
|
}
|
|
|
|
if (!sid_equal(&sid, &global_sam_sid))
|
|
{
|
|
DEBUG(5, ("validate_unix_sid: sid is not ours.\n"));
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
Unpack a SEC_DESC into a owner, group and set of UNIX permissions.
|
|
****************************************************************************/
|
|
|
|
BOOL convertperms_sd_to_unix(SMB_STRUCT_STAT * psbuf, uid_t * puser,
|
|
gid_t * pgrp, mode_t * pmode,
|
|
uint32 security_info_sent, SEC_DESC * psd,
|
|
BOOL is_directory)
|
|
{
|
|
DOM_SID file_owner_sid;
|
|
DOM_SID file_grp_sid;
|
|
SEC_ACL *dacl = psd->dacl;
|
|
BOOL all_aces_are_inherit_only = (is_directory ? True : False);
|
|
int i;
|
|
#ifdef WITH_SURS
|
|
SURS_POSIX_ID id;
|
|
#else
|
|
DOM_SID owner_sid;
|
|
DOM_SID grp_sid;
|
|
uint32 owner_rid;
|
|
uint32 grp_rid;
|
|
#endif
|
|
|
|
*pmode = 0;
|
|
*puser = (uid_t) - 1;
|
|
*pgrp = (gid_t) - 1;
|
|
|
|
if (security_info_sent == 0)
|
|
{
|
|
DEBUG(0, ("unpack_nt_permissions: "
|
|
"no security info sent !\n"));
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* Windows 2000 sends the owner and group SIDs as the logged in
|
|
* user, not the connected user. But it still sends the file
|
|
* owner SIDs on an ACL set. So we need to check for the file
|
|
* owner and group SIDs as well as the owner SIDs. JRA.
|
|
*/
|
|
|
|
if (!create_file_sids(psbuf, &file_owner_sid, &file_grp_sid))
|
|
{
|
|
DEBUG(3, ("create_file_sids: uid or gid "
|
|
"not mapped to SIDS\n"));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Don't immediately fail if the owner sid cannot be validated.
|
|
* This may be a group chown only set.
|
|
*/
|
|
|
|
DEBUG(0, ("TODO: LsaLookupSids to find type of owner_sid\n"));
|
|
|
|
#ifdef WITH_SURS
|
|
if (security_info_sent & OWNER_SECURITY_INFORMATION &&
|
|
surs_sam_sid_to_unixid(psd->owner_sid, &id, False) &&
|
|
id.type == SURS_POSIX_UID)
|
|
{
|
|
*puser = (uid_t) id.id;
|
|
}
|
|
|
|
#else
|
|
if (!validate_unix_sid(&owner_sid, &owner_rid, psd->owner_sid))
|
|
DEBUG(3,
|
|
("unpack_nt_permissions: unable to validate owner sid.\n"));
|
|
else if (security_info_sent & OWNER_SECURITY_INFORMATION)
|
|
*puser = pdb_user_rid_to_uid(owner_rid);
|
|
|
|
if (security_info_sent & OWNER_SECURITY_INFORMATION)
|
|
{
|
|
*puser = pdb_user_rid_to_uid(owner_rid);
|
|
}
|
|
|
|
#endif
|
|
/*
|
|
* Don't immediately fail if the group sid cannot be validated.
|
|
* This may be an owner chown only set.
|
|
*/
|
|
|
|
#ifdef WITH_SURS
|
|
if (security_info_sent & GROUP_SECURITY_INFORMATION &&
|
|
surs_sam_sid_to_unixid(psd->grp_sid, &id, False) &&
|
|
(id.type == SURS_POSIX_GID))
|
|
{
|
|
*pgrp = (gid_t) id.id;
|
|
}
|
|
#else
|
|
if (!validate_unix_sid(&grp_sid, &grp_rid, psd->grp_sid))
|
|
DEBUG(3,
|
|
("unpack_nt_permissions: unable to validate group sid.\n"));
|
|
else if (security_info_sent & GROUP_SECURITY_INFORMATION)
|
|
*pgrp = pdb_user_rid_to_gid(grp_rid);
|
|
|
|
#endif
|
|
/*
|
|
* If no DACL then this is a chown only security descriptor.
|
|
*/
|
|
|
|
if (!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl)
|
|
{
|
|
*pmode = 0;
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* Now go through the DACL and ensure that
|
|
* any owner/group sids match.
|
|
*/
|
|
|
|
for (i = 0; i < dacl->num_aces; i++)
|
|
{
|
|
DOM_SID ace_sid;
|
|
SEC_ACE *psa = &dacl->ace[i];
|
|
|
|
if ((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) &&
|
|
(psa->type != SEC_ACE_TYPE_ACCESS_DENIED))
|
|
{
|
|
DEBUG(3, ("unpack_nt_permissions: "
|
|
"unable to set anything but an "
|
|
"ALLOW or DENY ACE.\n"));
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* Ignore or remove bits we don't care about on a directory ACE.
|
|
*/
|
|
|
|
if (is_directory)
|
|
{
|
|
if (psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)
|
|
{
|
|
DEBUG(3, ("unpack_nt_permissions: "
|
|
"ignoring inherit only ACE.\n"));
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* At least one of the ACE entries wasn't inherit only.
|
|
* Flag this so we know the returned mode is valid.
|
|
*/
|
|
|
|
all_aces_are_inherit_only = False;
|
|
}
|
|
|
|
/*
|
|
* Windows 2000 sets these flags even on *file* ACE's.
|
|
* This is wrong but we can ignore them for now.
|
|
* Revisit this when we go to POSIX ACLs on directories.
|
|
*/
|
|
|
|
psa->flags &=
|
|
~(SEC_ACE_FLAG_OBJECT_INHERIT |
|
|
SEC_ACE_FLAG_CONTAINER_INHERIT);
|
|
|
|
if (psa->flags != 0)
|
|
{
|
|
DEBUG(1,
|
|
("unpack_nt_permissions: unable to set ACE flags (%x).\n",
|
|
(unsigned int)psa->flags));
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* The security mask may be UNIX_ACCESS_NONE which
|
|
* should map into no permissions (we overload the
|
|
* WRITE_OWNER bit for this) or it should be one of
|
|
* the ALL/EXECUTE/READ/WRITE bits. Arrange for this
|
|
* to be so. Any other bits override the
|
|
* UNIX_ACCESS_NONE bit.
|
|
*/
|
|
|
|
psa->info.mask &=
|
|
(GENERIC_ALL_ACCESS | GENERIC_EXECUTE_ACCESS |
|
|
GENERIC_WRITE_ACCESS | GENERIC_READ_ACCESS |
|
|
UNIX_ACCESS_NONE | FILE_ALL_ATTRIBUTES);
|
|
|
|
if (psa->info.mask != UNIX_ACCESS_NONE)
|
|
psa->info.mask &= ~UNIX_ACCESS_NONE;
|
|
|
|
sid_copy(&ace_sid, &psa->sid);
|
|
|
|
if (sid_equal(&ace_sid, &file_owner_sid))
|
|
{
|
|
/*
|
|
* Map the desired permissions into owner perms.
|
|
*/
|
|
|
|
if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
|
|
*pmode |= map_nt_perms(psa->info, S_IRUSR);
|
|
else
|
|
*pmode &= ~(map_nt_perms(psa->info, S_IRUSR));
|
|
|
|
}
|
|
else if (sid_equal(&ace_sid, &file_grp_sid))
|
|
{
|
|
/*
|
|
* Map the desired permissions into group perms.
|
|
*/
|
|
|
|
if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
|
|
*pmode |= map_nt_perms(psa->info, S_IRGRP);
|
|
else
|
|
*pmode &= ~(map_nt_perms(psa->info, S_IRGRP));
|
|
|
|
}
|
|
else if (sid_equal(&ace_sid, global_sid_everyone))
|
|
{
|
|
/*
|
|
* Map the desired permissions into other perms.
|
|
*/
|
|
|
|
if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED)
|
|
*pmode |= map_nt_perms(psa->info, S_IROTH);
|
|
else
|
|
*pmode &= ~(map_nt_perms(psa->info, S_IROTH));
|
|
|
|
}
|
|
else
|
|
{
|
|
DEBUG(0, ("unpack_nt_permissions: "
|
|
"unknown SID used in ACL.\n"));
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if (is_directory && all_aces_are_inherit_only)
|
|
{
|
|
/*
|
|
* Windows 2000 is doing one of these weird 'inherit acl'
|
|
* traverses to conserve NTFS ACL resources. Just pretend
|
|
* there was no DACL sent. JRA.
|
|
*/
|
|
|
|
DEBUG(10, ("unpack_nt_permissions: "
|
|
"Win2k inherit acl traverse. "
|
|
"Ignoring DACL.\n"));
|
|
free_sec_acl(psd->dacl);
|
|
safe_free(psd->dacl);
|
|
psd->dacl = NULL;
|
|
}
|
|
|
|
return True;
|
|
}
|