Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sec_acl.cc')
-rw-r--r--winsup/cygwin/sec_acl.cc256
1 files changed, 61 insertions, 195 deletions
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index 51f1c9964..2f7ac278d 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -1,7 +1,7 @@
/* sec_acl.cc: Sun compatible ACL functions.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011, 2012, 2014 Red Hat, Inc.
+ 2011, 2012 Red Hat, Inc.
Written by Corinna Vinschen <corinna@vinschen.de>
@@ -22,6 +22,7 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "ntdll.h"
+#include "pwdgrp.h"
#include "tls_pbuf.h"
static int
@@ -36,7 +37,6 @@ searchace (aclent_t *aclp, int nentries, int type, uid_t id = ILLEGAL_UID)
return -1;
}
-/* This function *requires* an acl list sorted with aclsort{32}. */
int
setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
bool &writable)
@@ -48,8 +48,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
return -1;
NTSTATUS status;
- PACL acl;
- BOOLEAN acl_exists, dummy;
+ BOOLEAN dummy;
/* Get owner SID. */
PSID owner_sid;
@@ -71,32 +70,9 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
cygsid group (group_sid);
- /* Search for NULL ACE and store state of SUID, SGID and VTX bits. */
- DWORD null_mask = 0;
- if (NT_SUCCESS (RtlGetDaclSecurityDescriptor (sd_ret, &acl_exists, &acl,
- &dummy)))
- for (USHORT i = 0; i < acl->AceCount; ++i)
- {
- ACCESS_ALLOWED_ACE *ace;
- if (NT_SUCCESS (RtlGetAce (acl, i, (PVOID *) &ace)))
- {
- cygpsid ace_sid ((PSID) &ace->SidStart);
- if (ace_sid == well_known_null_sid)
- {
- null_mask = ace->Mask;
- break;
- }
- }
- }
-
/* Initialize local security descriptor. */
SECURITY_DESCRIPTOR sd;
RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
-
- /* As in alloc_sd, set SE_DACL_PROTECTED to prevent the DACL from being
- modified by inheritable ACEs. */
- RtlSetControlSecurityDescriptor (&sd, SE_DACL_PROTECTED, SE_DACL_PROTECTED);
-
status = RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE);
if (!NT_SUCCESS (status))
{
@@ -111,7 +87,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
/* Fill access control list. */
- acl = (PACL) tp.w_get ();
+ PACL acl = (PACL) tp.w_get ();
size_t acl_len = sizeof (ACL);
int ace_off = 0;
@@ -119,102 +95,22 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
struct passwd *pw;
struct group *gr;
int pos;
- cyg_ldap cldap;
RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION);
writable = false;
- /* Pre-compute owner, group, and other permissions to allow creating
- matching deny ACEs as in alloc_sd. */
- DWORD owner_allow = 0, group_allow = 0, other_allow = 0;
- PDWORD allow;
- for (int i = 0; i < nentries; ++i)
- {
- switch (aclbufp[i].a_type)
- {
- case USER_OBJ:
- allow = &owner_allow;
- *allow = STANDARD_RIGHTS_ALL;
- break;
- case GROUP_OBJ:
- allow = &group_allow;
- break;
- case OTHER_OBJ:
- allow = &other_allow;
- break;
- default:
- continue;
- }
- *allow |= STANDARD_RIGHTS_READ | SYNCHRONIZE
- | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
- if (aclbufp[i].a_perm & S_IROTH)
- *allow |= FILE_GENERIC_READ;
- if (aclbufp[i].a_perm & S_IWOTH)
- {
- *allow |= FILE_GENERIC_WRITE;
- writable = true;
- }
- if (aclbufp[i].a_perm & S_IXOTH)
- *allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
- /* Keep S_ISVTX rule in sync with alloc_sd. */
- if (pc.isdir ()
- && (aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
- && (aclbufp[i].a_type == USER_OBJ
- || !(null_mask & FILE_READ_DATA)))
- *allow |= FILE_DELETE_CHILD;
- aclbufp[i].a_type = 0;
- }
- bool isownergroup = (owner_sid == group_sid);
- DWORD owner_deny = ~owner_allow & (group_allow | other_allow);
- owner_deny &= ~(STANDARD_RIGHTS_READ
- | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES);
- DWORD group_deny = ~group_allow & other_allow;
- group_deny &= ~(STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES);
-
- /* Set deny ACE for owner. */
- if (owner_deny
- && !add_access_denied_ace (acl, ace_off++, owner_deny,
- owner_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set deny ACE for group here to respect the canonical order,
- if this does not impact owner */
- if (group_deny && !(group_deny & owner_allow) && !isownergroup
- && !add_access_denied_ace (acl, ace_off++, group_deny,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for owner. */
- if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
- owner_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set deny ACE for group, if still needed. */
- if (group_deny & owner_allow && !isownergroup
- && !add_access_denied_ace (acl, ace_off++, group_deny,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for group. */
- if (!isownergroup
- && !add_access_allowed_ace (acl, ace_off++, group_allow,
- group_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* Set allow ACE for everyone. */
- if (!add_access_allowed_ace (acl, ace_off++, other_allow,
- well_known_world_sid, acl_len, NO_INHERITANCE))
- return -1;
- /* If a NULL ACE exists, copy it verbatim. */
- if (null_mask)
- if (!add_access_allowed_ace (acl, ace_off++, null_mask, well_known_null_sid,
- acl_len, NO_INHERITANCE))
- return -1;
for (int i = 0; i < nentries; ++i)
{
DWORD allow;
- /* Skip invalidated entries. */
- if (!aclbufp[i].a_type)
- continue;
-
- allow = STANDARD_RIGHTS_READ
- | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
+ /* Owner has more standard rights set. */
+ if ((aclbufp[i].a_type & ~ACL_DEFAULT) == USER_OBJ)
+ allow = STANDARD_RIGHTS_ALL
+ | (pc.fs_is_samba ()
+ ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES));
+ else
+ allow = STANDARD_RIGHTS_READ
+ | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
if (aclbufp[i].a_perm & S_IROTH)
allow |= FILE_GENERIC_READ;
if (aclbufp[i].a_perm & S_IWOTH)
@@ -224,10 +120,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
}
if (aclbufp[i].a_perm & S_IXOTH)
allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
- /* Keep S_ISVTX rule in sync with alloc_sd. */
- if (pc.isdir ()
- && (aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)
- && !(null_mask & FILE_READ_DATA))
+ if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH))
allow |= FILE_DELETE_CHILD;
/* Set inherit property. */
DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
@@ -240,7 +133,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
* inheritance bits is created.
*/
if (!(aclbufp[i].a_type & ACL_DEFAULT)
- && aclbufp[i].a_type & (USER|GROUP)
+ && aclbufp[i].a_type & (USER|GROUP|OTHER_OBJ)
&& (pos = searchace (aclbufp + i + 1, nentries - i - 1,
aclbufp[i].a_type | ACL_DEFAULT,
(aclbufp[i].a_type & (USER|GROUP))
@@ -248,11 +141,16 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
&& aclbufp[i].a_perm == aclbufp[i + 1 + pos].a_perm)
{
inheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
- /* invalidate the corresponding default entry. */
- aclbufp[i + 1 + pos].a_type = 0;
+ /* This invalidates the corresponding default entry. */
+ aclbufp[i + 1 + pos].a_type = USER|GROUP|ACL_DEFAULT;
}
switch (aclbufp[i].a_type)
{
+ case USER_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ owner, acl_len, inheritance))
+ return -1;
+ break;
case DEF_USER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_owner_sid, acl_len, inheritance))
@@ -260,7 +158,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
break;
case USER:
case DEF_USER:
- if (!(pw = internal_getpwuid (aclbufp[i].a_id, &cldap))
+ if (!(pw = internal_getpwuid (aclbufp[i].a_id))
|| !sid.getfrompw (pw))
{
set_errno (EINVAL);
@@ -270,6 +168,11 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
sid, acl_len, inheritance))
return -1;
break;
+ case GROUP_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ group, acl_len, inheritance))
+ return -1;
+ break;
case DEF_GROUP_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_group_sid, acl_len, inheritance))
@@ -277,7 +180,7 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
break;
case GROUP:
case DEF_GROUP:
- if (!(gr = internal_getgrgid (aclbufp[i].a_id, &cldap))
+ if (!(gr = internal_getgrgid (aclbufp[i].a_id))
|| !sid.getfromgr (gr))
{
set_errno (EINVAL);
@@ -287,11 +190,13 @@ setacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp,
sid, acl_len, inheritance))
return -1;
break;
+ case OTHER_OBJ:
case DEF_OTHER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_world_sid,
acl_len, inheritance))
return -1;
+ break;
}
}
/* Set AclSize to computed value. */
@@ -378,7 +283,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
BOOLEAN dummy;
uid_t uid;
gid_t gid;
- cyg_ldap cldap;
status = RtlGetOwnerSecurityDescriptor (sd, (PSID *) &owner_sid, &dummy);
if (!NT_SUCCESS (status))
@@ -386,7 +290,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
__seterrno_from_nt_status (status);
return -1;
}
- uid = owner_sid.get_uid (&cldap);
+ uid = owner_sid.get_uid ();
status = RtlGetGroupSecurityDescriptor (sd, (PSID *) &group_sid, &dummy);
if (!NT_SUCCESS (status))
@@ -394,7 +298,7 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
__seterrno_from_nt_status (status);
return -1;
}
- gid = group_sid.get_gid (&cldap);
+ gid = group_sid.get_gid ();
aclent_t lacl[MAX_ACL_ENTRIES];
memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t));
@@ -404,6 +308,9 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[1].a_id = gid;
lacl[2].a_type = OTHER_OBJ;
lacl[2].a_id = ILLEGAL_GID;
+ lacl[3].a_type = CLASS_OBJ;
+ lacl[3].a_id = ILLEGAL_GID;
+ lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
PACL acl;
BOOLEAN acl_exists;
@@ -416,11 +323,9 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
}
int pos, i, types_def = 0;
- int pgrp_pos = 1, def_pgrp_pos = -1;
- mode_t class_perm = 0, def_class_perm = 0;
if (!acl_exists || !acl)
- for (pos = 0; pos < 3; ++pos)
+ for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */
lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
else
{
@@ -435,11 +340,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
int id;
int type = 0;
- if (ace_sid == well_known_null_sid)
- {
- /* Simply ignore. */
- continue;
- }
if (ace_sid == well_known_world_sid)
{
type = OTHER_OBJ;
@@ -457,30 +357,25 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
}
else if (ace_sid == well_known_creator_group_sid)
{
- type = DEF_GROUP_OBJ;
+ type = GROUP_OBJ | ACL_DEFAULT;
types_def |= type;
id = ILLEGAL_GID;
}
else if (ace_sid == well_known_creator_owner_sid)
{
- type = DEF_USER_OBJ;
+ type = USER_OBJ | ACL_DEFAULT;
types_def |= type;
id = ILLEGAL_GID;
}
else
- id = ace_sid.get_id (TRUE, &type, &cldap);
+ id = ace_sid.get_id (true, &type);
if (!type)
continue;
if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE || type & ACL_DEFAULT))
{
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- {
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- /* Fix up CLASS_OBJ value. */
- if (type == USER || type == GROUP)
- class_perm |= lacl[pos].a_perm;
- }
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
if ((ace->Header.AceFlags
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
@@ -493,31 +388,13 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
type |= ACL_DEFAULT;
types_def |= type;
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- {
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- /* Fix up DEF_CLASS_OBJ value. */
- if (type == DEF_USER || type == DEF_GROUP)
- def_class_perm |= lacl[pos].a_perm;
- /* And note the position of the DEF_GROUP_OBJ entry. */
- else if (type == DEF_GROUP_OBJ)
- def_pgrp_pos = pos;
- }
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
}
- /* If secondary user and group entries exist in the ACL, fake a matching
- CLASS_OBJ entry. The CLASS_OBJ permissions are the or'ed permissions
- of the primary group permissions and all secondary user and group
- permissions. */
- if (class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
- {
- lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
- lacl[pos].a_perm = class_perm | lacl[pgrp_pos].a_perm;
- }
- /* Ensure that the default acl contains at least
- DEF_(USER|GROUP|OTHER)_OBJ entries. */
if (types_def && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
{
+ /* Ensure that the default acl contains at
+ least DEF_(USER|GROUP|OTHER)_OBJ entries. */
if (!(types_def & USER_OBJ))
{
lacl[pos].a_type = DEF_USER_OBJ;
@@ -530,8 +407,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[pos].a_type = DEF_GROUP_OBJ;
lacl[pos].a_id = gid;
lacl[pos].a_perm = lacl[1].a_perm;
- /* Note the position of the DEF_GROUP_OBJ entry. */
- def_pgrp_pos = pos;
pos++;
}
if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES)
@@ -541,18 +416,13 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp)
lacl[pos].a_perm = lacl[2].a_perm;
pos++;
}
- }
- /* If secondary user default and group default entries exist in the ACL,
- fake a matching DEF_CLASS_OBJ entry. The DEF_CLASS_OBJ permissions are
- the or'ed permissions of the primary group default permissions and all
- secondary user and group default permissions. */
- if (def_class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
- {
- lacl[pos].a_type = DEF_CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
- lacl[pos].a_perm = def_class_perm;
- if (def_pgrp_pos >= 0)
- lacl[pos].a_perm |= lacl[def_pgrp_pos].a_perm;
+ /* Include DEF_CLASS_OBJ if any named default ace exists. */
+ if ((types_def & (USER|GROUP)) && pos < MAX_ACL_ENTRIES)
+ {
+ lacl[pos].a_type = DEF_CLASS_OBJ;
+ lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
+ }
}
}
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
@@ -628,7 +498,6 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
bool has_other_obj = false;
bool has_class_obj = false;
bool has_ug_objs __attribute__ ((unused)) = false;
- bool has_def_objs __attribute__ ((unused)) = false;
bool has_def_user_obj __attribute__ ((unused)) = false;
bool has_def_group_obj = false;
bool has_def_other_obj = false;
@@ -693,7 +562,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return USER_ERROR;
}
- has_def_objs = has_def_user_obj = true;
+ has_def_user_obj = true;
break;
case DEF_GROUP_OBJ:
if (has_def_group_obj)
@@ -702,7 +571,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return GRP_ERROR;
}
- has_def_objs = has_def_group_obj = true;
+ has_def_group_obj = true;
break;
case DEF_OTHER_OBJ:
if (has_def_other_obj)
@@ -711,7 +580,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return OTHER_ERROR;
}
- has_def_objs = has_def_other_obj = true;
+ has_def_other_obj = true;
break;
case DEF_CLASS_OBJ:
if (has_def_class_obj)
@@ -720,7 +589,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos;
return CLASS_ERROR;
}
- has_def_objs = has_def_class_obj = true;
+ has_def_class_obj = true;
break;
case DEF_USER:
case DEF_GROUP:
@@ -731,7 +600,7 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
*which = pos2;
return DUPLICATE_ERROR;
}
- has_def_objs = has_def_ug_objs = true;
+ has_def_ug_objs = true;
break;
default:
return ENTRY_ERROR;
@@ -739,10 +608,11 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
if (!has_user_obj
|| !has_group_obj
|| !has_other_obj
- || (has_def_objs
- && (!has_def_user_obj || !has_def_group_obj || !has_def_other_obj))
+#if 0
+ /* These checks are not ok yet since CLASS_OBJ isn't fully implemented. */
|| (has_ug_objs && !has_class_obj)
|| (has_def_ug_objs && !has_def_class_obj)
+#endif
)
{
if (which)
@@ -767,10 +637,7 @@ extern "C" int
aclsort32 (int nentries, int, aclent_t *aclbufp)
{
if (aclcheck32 (aclbufp, nentries, NULL))
- {
- set_errno (EINVAL);
- return -1;
- }
+ return -1;
if (!aclbufp || nentries < 1)
{
set_errno (EINVAL);
@@ -970,7 +837,6 @@ aclfromtext32 (char *acltextp, int *)
int pos = 0;
strcpy (buf, acltextp);
char *lasts;
- cyg_ldap cldap;
for (char *c = strtok_r (buf, ",", &lasts);
c;
c = strtok_r (NULL, ",", &lasts))
@@ -990,7 +856,7 @@ aclfromtext32 (char *acltextp, int *)
c += 5;
if (isalpha (*c))
{
- struct passwd *pw = internal_getpwnam (c, &cldap);
+ struct passwd *pw = internal_getpwnam (c);
if (!pw)
{
set_errno (EINVAL);
@@ -1018,7 +884,7 @@ aclfromtext32 (char *acltextp, int *)
c += 5;
if (isalpha (*c))
{
- struct group *gr = internal_getgrnam (c, &cldap);
+ struct group *gr = internal_getgrnam (c);
if (!gr)
{
set_errno (EINVAL);