From 3a157c0d0d8aa3d9f004fb460bdb925b181c536a Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sun, 15 Jul 2001 22:40:07 +0000 Subject: Change well_known_admin_sid to well_known_admins_sid throughout. * sec_acl.cc (setacl): Never set DELETE permission. Set FILE_DELETE_CHILD only on readable and executable directories. * sec_helper.cc: Add constructor for `well_known_null_sid'. * security.cc (get_nt_attribute): Set S_ISVTX for directories if FILE_WRITE_DATA and FILE_EXECUTE but not FILE_DELETE_CHILD is set. Add evaluation of S_ISVTX, S_ISGID and S_ISUID from NULL ACE. (alloc_sd): Never set DELETE permission. Set FILE_DELETE_CHILD only on readable and executable directories. Add creation of NULL ACE for S_ISVTX, S_ISGID and S_ISUID permissions. * security.h: Add extern declaration for `well_known_null_sid'. --- winsup/cygwin/ChangeLog | 14 +++++++++ winsup/cygwin/grp.cc | 2 +- winsup/cygwin/sec_acl.cc | 5 +-- winsup/cygwin/sec_helper.cc | 3 +- winsup/cygwin/security.cc | 77 ++++++++++++++++++++++++++++----------------- winsup/cygwin/security.h | 3 +- winsup/cygwin/shared.cc | 4 +-- 7 files changed, 73 insertions(+), 35 deletions(-) (limited to 'winsup') diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6d7fd7741..e311289b6 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +Mon 16 Jul 2001 00:11:00 Corinna Vinschen + + Change well_known_admin_sid to well_known_admins_sid throughout. + * sec_acl.cc (setacl): Never set DELETE permission. Set + FILE_DELETE_CHILD only on readable and executable directories. + * sec_helper.cc: Add constructor for `well_known_null_sid'. + * security.cc (get_nt_attribute): Set S_ISVTX for directories if + FILE_WRITE_DATA and FILE_EXECUTE but not FILE_DELETE_CHILD is set. + Add evaluation of S_ISVTX, S_ISGID and S_ISUID from NULL ACE. + (alloc_sd): Never set DELETE permission. Set FILE_DELETE_CHILD + only on readable and executable directories. + Add creation of NULL ACE for S_ISVTX, S_ISGID and S_ISUID permissions. + * security.h: Add extern declaration for `well_known_null_sid'. + Fri 13 Jul 2001 08:08:49 PM EDT Christopher Faylor * syscalls.cc (stat_worker): Simplify previous change. diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 604f1a8d6..70817470b 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -174,7 +174,7 @@ read_etc_group () SID_NAME_USE acType; debug_printf ("Emulating /etc/group"); if (! LookupAccountSidA (NULL , - well_known_admin_sid, + well_known_admins_sid, group_name, &group_name_len, domain_name, diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index cd5722f0c..6b9b7cc31 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -121,10 +121,11 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) if (aclbufp[i].a_perm & S_IROTH) allow |= FILE_GENERIC_READ; if (aclbufp[i].a_perm & S_IWOTH) - allow |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE - | DELETE | FILE_DELETE_CHILD; + allow |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE; if (aclbufp[i].a_perm & S_IXOTH) allow |= FILE_GENERIC_EXECUTE; + 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) ? INHERIT_ONLY : DONT_INHERIT; diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 4789732a4..6a6867c48 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -44,6 +44,7 @@ SID_IDENTIFIER_AUTHORITY sid_auth[] = { {SECURITY_NT_AUTHORITY} }; +cygsid well_known_null_sid ("S-1-0-0"); cygsid well_known_world_sid ("S-1-1-0"); cygsid well_known_local_sid ("S-1-2-0"); cygsid well_known_creator_owner_sid ("S-1-3-0"); @@ -54,7 +55,7 @@ cygsid well_known_interactive_sid ("S-1-5-4"); cygsid well_known_service_sid ("S-1-5-6"); cygsid well_known_authenticated_users_sid ("S-1-5-11"); cygsid well_known_system_sid ("S-1-5-18"); -cygsid well_known_admin_sid ("S-1-5-32-544"); +cygsid well_known_admins_sid ("S-1-5-32-544"); char * cygsid::string (char *nsidstr) const diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 0a843c7a0..6a5b86b27 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -456,7 +456,7 @@ get_group_sidlist (const char *logonserver, cygsidlist &grp_list, if (usersid == well_known_system_sid) { grp_list += well_known_system_sid; - grp_list += well_known_admin_sid; + grp_list += well_known_admins_sid; } else { @@ -626,10 +626,10 @@ get_dacl (PACL acl, cygsid usersid, cygsidlist &grp_list) __seterrno (); return FALSE; } - if (grp_list.contains (well_known_admin_sid)) + if (grp_list.contains (well_known_admins_sid)) { if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL, - well_known_admin_sid)) + well_known_admins_sid)) { __seterrno (); return FALSE; @@ -1162,15 +1162,24 @@ get_nt_attribute (const char *file, int *attribute, *flags |= S_IXOTH | ((!(*anti & S_IXGRP)) ? S_IXGRP : 0) | ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); - /* Sticky bit for directories according to linux rules. */ - if (!(ace->Mask & FILE_DELETE_CHILD) - && S_ISDIR(*attribute) - && !(*anti & S_ISVTX)) - *flags |= S_ISVTX; } + if ((*attribute & S_IFDIR) && + (ace->Mask & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD)) + == (FILE_WRITE_DATA | FILE_EXECUTE)) + *flags |= S_ISVTX; + } + else if (ace_sid == well_known_null_sid) + { + /* Read SUID, SGID and VTX bits from NULL ACE. */ + if (ace->Mask & FILE_READ_DATA) + *flags |= S_ISVTX; + if (ace->Mask & FILE_WRITE_DATA) + *flags |= S_ISGID; + if (ace->Mask & FILE_APPEND_DATA) + *flags |= S_ISUID; } } - *attribute &= ~(S_IRWXU|S_IRWXG|S_IRWXO|S_ISVTX); + *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); *attribute |= allow; *attribute &= ~deny; syscall_printf ("file: %s %x, uid %d, gid %d", file, *attribute, uid, gid); @@ -1335,16 +1344,6 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, return NULL; } - /* - * VTX bit may only be set if executable for `other' is set. - * For correct handling under WinNT, FILE_DELETE_CHILD has to - * be (un)set in each ACE. - */ - if (!(attribute & S_IXOTH)) - attribute &= ~S_ISVTX; - if (!(attribute & S_IFDIR)) - attribute |= S_ISVTX; - /* From here fill ACL. */ size_t acl_len = sizeof (ACL); int ace_off = 0; @@ -1355,10 +1354,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IRUSR) owner_allow |= FILE_GENERIC_READ; if (attribute & S_IWUSR) - owner_allow |= FILE_GENERIC_WRITE | DELETE; + owner_allow |= FILE_GENERIC_WRITE; if (attribute & S_IXUSR) owner_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWUSR | S_IXUSR)) + == (S_IFDIR | S_IWUSR | S_IXUSR)) owner_allow |= FILE_DELETE_CHILD; /* Construct allow attribute for group. */ @@ -1367,10 +1367,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IRGRP) group_allow |= FILE_GENERIC_READ; if (attribute & S_IWGRP) - group_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; + group_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE; if (attribute & S_IXGRP) group_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP)) + == (S_IFDIR | S_IWGRP | S_IXGRP)) group_allow |= FILE_DELETE_CHILD; /* Construct allow attribute for everyone. */ @@ -1379,12 +1380,26 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IROTH) other_allow |= FILE_GENERIC_READ; if (attribute & S_IWOTH) - other_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; + other_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE; if (attribute & S_IXOTH) other_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWOTH | S_IXOTH)) + == (S_IFDIR | S_IWOTH | S_IXOTH) + && !(attribute & S_ISVTX)) other_allow |= FILE_DELETE_CHILD; + /* Construct SUID, SGID and VTX bits in NULL ACE. */ + DWORD null_allow = 0L; + if (attribute & (S_ISUID | S_ISGID | S_ISVTX)) + { + if (attribute & S_ISUID) + null_allow |= FILE_APPEND_DATA; + if (attribute & S_ISGID) + null_allow |= FILE_WRITE_DATA; + if (attribute & S_ISVTX) + null_allow |= FILE_READ_DATA; + } + /* Construct deny attributes for owner and group. */ DWORD owner_deny = 0; if (is_grp_member (uid, gid)) @@ -1420,7 +1435,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (owner_deny && !add_access_denied_ace (acl, ace_off++, owner_deny, owner_sid, acl_len, inherit)) - return NULL; + return NULL; /* Set allow ACE for owner. */ if (!add_access_allowed_ace (acl, ace_off++, owner_allow, owner_sid, acl_len, inherit)) @@ -1429,7 +1444,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (group_deny && !add_access_denied_ace (acl, ace_off++, group_deny, group_sid, acl_len, inherit)) - return NULL; + return NULL; /* Set allow ACE for group. */ if (!add_access_allowed_ace (acl, ace_off++, group_allow, group_sid, acl_len, inherit)) @@ -1439,6 +1454,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (!add_access_allowed_ace (acl, ace_off++, other_allow, well_known_world_sid, acl_len, inherit)) return NULL; + /* Set null ACE for special bits. */ + if (null_allow + && !add_access_allowed_ace (acl, ace_off++, null_allow, + well_known_null_sid, acl_len, inherit)) + return NULL; /* Get owner and group from current security descriptor. */ PSID cur_owner_sid = NULL; @@ -1463,7 +1483,8 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, || (owner_sid && ace_sid == owner_sid) || (cur_group_sid && ace_sid == cur_group_sid) || (group_sid && ace_sid == group_sid) - || (ace_sid == well_known_world_sid)) + || (ace_sid == well_known_world_sid) + || (ace_sid == well_known_null_sid)) continue; /* * Add unrelated ACCESS_DENIED_ACE to the beginning but diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 5289a29d1..49c41c8cb 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -131,6 +131,7 @@ public: } }; +extern cygsid well_known_null_sid; extern cygsid well_known_world_sid; extern cygsid well_known_local_sid; extern cygsid well_known_creator_owner_sid; @@ -141,7 +142,7 @@ extern cygsid well_known_interactive_sid; extern cygsid well_known_service_sid; extern cygsid well_known_authenticated_users_sid; extern cygsid well_known_system_sid; -extern cygsid well_known_admin_sid; +extern cygsid well_known_admins_sid; inline BOOL legal_sid_type (SID_NAME_USE type) diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 28fbf4ceb..be93cfed2 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -249,7 +249,7 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit) size_t acl_len = sizeof (ACL) + 4 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + GetLengthSid (sid) - + GetLengthSid (well_known_admin_sid) + + GetLengthSid (well_known_admins_sid) + GetLengthSid (well_known_system_sid) + GetLengthSid (well_known_creator_owner_sid); if (sid2) @@ -266,7 +266,7 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit) if (! AddAccessAllowedAce (acl, ACL_REVISION, SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, - well_known_admin_sid)) + well_known_admins_sid)) debug_printf ("AddAccessAllowedAce(admin) %E"); if (! AddAccessAllowedAce (acl, ACL_REVISION, -- cgit v1.2.3