Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com Message-ID: <36E051EE.B55AE1D4@cityweb.de> Date: Fri, 05 Mar 1999 22:51:42 +0100 From: Corinna Vinschen X-Mailer: Mozilla 4.04 [en] (WinNT; I) MIME-Version: 1.0 To: Geoffrey Noer CC: cygwin-developers AT sourceware DOT cygnus DOT com, DJ Delorie , Christopher Faylor , Sergey Okhapkin Subject: Re: Repost: Patch, Version 2: UNIX-like permissions on objects References: <01BE46C2 DOT 29B35190 AT sos> <36D8F66F DOT CB411F58 AT cityweb DOT de> <19990228222910 DOT A14921 AT cygnus DOT com> <36DDBD54 DOT 3B6417E8 AT cityweb DOT de> <36DE93A5 DOT 7BDF02CC AT cityweb DOT de> <19990305131623 DOT A746 AT cygnus DOT com> Content-Type: multipart/mixed; boundary="------------76F080FB75CF85B656CAA21C" This is a multi-part message in MIME format. --------------76F080FB75CF85B656CAA21C Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Geoffrey Noer wrote: > [...] > I have your original patch applied. The resulting cygwin1.dll builds > but doesn't run close to correctly on my NT 4 SP4 machine as expected. > Please send me the patch that gets around the two above problems in > the way you suggest and I'll try it out... Hello Geoffrey, the changes are only in security.cc. I attached a patch relativ to the original security.cc from the current snapshots. Regards, Corinna --------------76F080FB75CF85B656CAA21C Content-Type: text/plain; charset=us-ascii; name="sec-diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sec-diff" Index: security.cc =================================================================== RCS file: /src/cvsroot/winsup-990126/security.cc,v retrieving revision 1.1 diff -u -p -r1.1 security.cc --- security.cc 1999/01/29 09:33:43 1.1 +++ security.cc 1999/03/05 08:11:08 @@ -1,8 +1,9 @@ /* security.cc: NT security functions - Copyright 1997, 1998 Cygnus Solutions. + Copyright 1997, 1998, 1999 Cygnus Solutions. - Written by Gunther Ebert, gunther DOT ebert AT ixos-leipzig DOT de + Originaly written by Gunther Ebert, gunther DOT ebert AT ixos-leipzig DOT de + Extensions by Corinna Vinschen This file is part of Cygwin. @@ -13,23 +14,35 @@ details. */ #include #include #include +#include +#include +#include #include "winsup.h" -#if 0 +extern BOOL allow_ntea; +BOOL allow_ntsec = FALSE; + +extern PSID get_admin_sid (); + PSID get_world_sid () { - PSID world_sid; - SID_IDENTIFIER_AUTHORITY world_sid_auth = SECURITY_WORLD_SID_AUTHORITY; + static PSID world_sid; - world_sid = (PSID) LocalAlloc (LPTR,GetSidLengthRequired (1)); + if (! world_sid) + { + SID_IDENTIFIER_AUTHORITY world_sid_auth = SECURITY_WORLD_SID_AUTHORITY; + + world_sid = (PSID) LocalAlloc (LPTR,GetSidLengthRequired (1)); - InitializeSid (world_sid, &world_sid_auth, 1); - *(GetSidSubAuthority (world_sid, 0)) = SECURITY_WORLD_RID; + InitializeSid (world_sid, &world_sid_auth, 1); + *(GetSidSubAuthority (world_sid, 0)) = SECURITY_WORLD_RID; + } return world_sid; } +#if 0 int world_full_access (HANDLE h, int type) { @@ -153,22 +166,417 @@ get_id_from_sid (PSID psid) return id; } + +static BOOL +get_nt_attribute (const char *file, int *attribute) +{ + if (os_being_run != winNT) + return FALSE; + + syscall_printf ("file: %s", file); + + if (file[1] == ':') + { + static char drive[4] = "X:\\"; + char fs[32]; + + drive[0] = file[0]; + if (! GetVolumeInformation(drive, NULL, 0, NULL, NULL, NULL, fs, 32)) + { + debug_printf ("GetVolumeInformation(%s) %d", drive, GetLastError()); + return FALSE; + } + if (! strcmp (fs, "FAT")) + return FALSE; + } + + DWORD sd_size = 0; + DWORD bufdummy; + SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *) &bufdummy; + + if (! GetFileSecurity (file, OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION, + sd, 4, &sd_size)) + { + debug_printf ("GetFileSecuritySize %d", GetLastError()); + if (sd_size == 0) + return FALSE; + } + sd = (SECURITY_DESCRIPTOR *) malloc (sd_size); + if (! sd) + { + debug_printf ("malloc"); + return FALSE; + } + if (! GetFileSecurity (file, OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION, + sd, sd_size, &sd_size)) + { + free (sd); + debug_printf ("GetFileSecurity %d", GetLastError ()); + return FALSE; + } -/* - * File attribute stuff. FIXME: add NTFS security. - */ + PSID sidOwner; + PSID sidGroup; + BOOL dummy; + + if (! GetSecurityDescriptorOwner (sd, &sidOwner, &dummy)) + debug_printf ("GetSecurityDescriptorOwner %d", GetLastError ()); + if (! GetSecurityDescriptorGroup (sd, &sidGroup, &dummy)) + debug_printf ("GetSecurityDescriptorGroup %d", GetLastError ()); + + int owner_id = -1; + if (sidOwner) + owner_id = *GetSidSubAuthority(sidOwner, + *GetSidSubAuthorityCount(sidOwner) - 1); + int group_id = -1; + if (sidGroup) + group_id = *GetSidSubAuthority(sidGroup, + *GetSidSubAuthorityCount(sidGroup) - 1); + PACL acl; + BOOL acl_exists; + + if (! GetSecurityDescriptorDacl (sd, &acl_exists, &acl, &dummy) + || ! acl_exists) + { + free (sd); + debug_printf ("GetSecurityDescriptorDacl %d", GetLastError ()); + return FALSE; + } + + BOOL has_owner_bits = FALSE; + BOOL has_group_bits = FALSE; + BOOL has_world_bits = FALSE; + + for (DWORD i = 0; i < acl->AceCount; ++i) + { + ACCESS_ALLOWED_ACE *ace; + + if (GetAce (acl, i, (PVOID *) &ace)) + { + int ace_id = *GetSidSubAuthority((PSID) &ace->SidStart, + *GetSidSubAuthorityCount((PSID) &ace->SidStart) - 1); + switch (ace->Header.AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + if (owner_id >= 0 && ace_id == owner_id) + { + *attribute &= ~S_IRWXU; + has_owner_bits = TRUE; + if (ace->Mask & FILE_READ_DATA) + *attribute |= S_IRUSR; + if (ace->Mask & FILE_WRITE_DATA) + *attribute |= S_IWUSR; + if (ace->Mask & FILE_EXECUTE) + *attribute |= S_IXUSR; + } + else if (group_id && ace_id == group_id) + { + *attribute &= ~S_IRWXG; + has_group_bits = TRUE; + if (ace->Mask & FILE_READ_DATA) + *attribute |= S_IRGRP; + if (ace->Mask & FILE_WRITE_DATA) + *attribute |= S_IWGRP; + if (ace->Mask & FILE_EXECUTE) + *attribute |= S_IXGRP; + } + else if (ace_id == 0) + { + *attribute &= ~S_IRWXO; + has_world_bits = TRUE; + if (ace->Mask & FILE_READ_DATA) + { + *attribute |= S_IROTH; + if (! sidOwner || ! has_owner_bits) + *attribute |= S_IRUSR; + if (! sidGroup || ! has_group_bits) + *attribute |= S_IRGRP; + } + if (ace->Mask & FILE_WRITE_DATA) + { + *attribute |= S_IWOTH; + if (! sidOwner || ! has_owner_bits) + *attribute |= S_IWUSR; + if (! sidGroup || ! has_group_bits) + *attribute |= S_IWGRP; + } + if (ace->Mask & FILE_EXECUTE) + { + *attribute |= S_IXOTH; + if (! sidOwner || ! has_owner_bits) + *attribute |= S_IXUSR; + if (! sidGroup || ! has_group_bits) + *attribute |= S_IXGRP; + } + } + break; + case ACCESS_DENIED_ACE_TYPE: + // Still ignored! + break; + default: + break; + } + } + } + + free (sd); + syscall_printf ("file: %s %x", file, *attribute); + return TRUE; +} + BOOL get_file_attribute (const char *file, int *attribute) { + if (! attribute) + return FALSE; + int res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute)); - return res > 0; + + // symlinks are anything for everyone! + if ((*attribute & S_IFLNK) == S_IFLNK) + *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; + + if (!allow_ntsec) + return res > 0; + + return get_nt_attribute (file, attribute); +} + +static BOOL +set_nt_attribute (const char *file, uid_t uid, gid_t gid, int attribute) +{ + if (os_being_run != winNT) + return FALSE; + + DWORD sidlen, domlen; + char dom[100]; + char user[256]; + SID_NAME_USE acc_type; + + /* + * Caution! + * + * ID 513 is `none'. Giving explicit permissions + * to `none' will result in dubious problems! + * + * Uid 513 is definitely not allowed here! + */ + if (uid == 513) + return FALSE; + + struct passwd *pw = getpwuid (uid); + strcpy (user, pw ? pw->pw_name : getlogin ()); + PSID sidOwner = (PSID) malloc (1024); + if (! sidOwner) + { + debug_printf ("malloc 1"); + return FALSE; + } + if (! LookupAccountName (NULL, user, + sidOwner, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidOwner); + debug_printf ("LookupAccountName(%s) %d", user, GetLastError ()); + return FALSE; + } + else if (acc_type != SidTypeUser) + { + char domuser[356]; + strcpy (domuser, dom); + strcat (domuser, "\\"); + strcat (domuser, user); + if (! LookupAccountName (NULL, domuser, + sidOwner, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidOwner); + debug_printf ("LookupAccountName(%s) %d", domuser, GetLastError ()); + return FALSE; + } + } + sidOwner = (PSID) realloc (sidOwner, sidlen + 1); + debug_printf ("user: %s [%d]", user, + *GetSidSubAuthority((PSID) sidOwner, + *GetSidSubAuthorityCount((PSID) sidOwner) - 1)); + + struct group *grp = getgrgid (gid); + PSID sidGroup = NULL; + + /* + * Caution! + * + * ID 513 is `none'. Giving explicit permissions + * to `none' will result in dubious problems! + * + * Gid 513 will result in not setting group permissions here. + */ + if (grp && gid != 513) + { + sidGroup = (PSID) malloc (1024); + if (! sidGroup) + { + free (sidOwner); + free (sidGroup); + debug_printf ("malloc 2"); + return FALSE; + } + if (! LookupAccountName (NULL, grp->gr_name, + sidGroup, (sidlen = 1024, &sidlen), + dom, (domlen = 100, &domlen), + &acc_type)) + { + free (sidOwner); + free (sidGroup); + debug_printf ("LookupAccountName(%s) %d", grp->gr_name, + GetLastError ()); + return FALSE; + } + sidGroup = (PSID) realloc (sidGroup, sidlen + 1); + debug_printf ("group: %s [%d]", grp->gr_name, + *GetSidSubAuthority((PSID) sidGroup, + *GetSidSubAuthorityCount((PSID) sidGroup) - 1)); + } + else + debug_printf ("no group"); + + SECURITY_DESCRIPTOR sd; + + if (! InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION)) + debug_printf ("InitializeSecurityDescriptor %d", GetLastError ()); + if (! SetSecurityDescriptorOwner(&sd, sidOwner, FALSE)) + debug_printf ("SetSecurityDescriptorOwner %d", GetLastError ()); + if (sidGroup) + if (! SetSecurityDescriptorGroup(&sd, sidGroup, FALSE)) + debug_printf ("SetSecurityDescriptorGroup %d", GetLastError ()); + + size_t acl_len = sizeof (ACL) + + 3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + + GetLengthSid (sidOwner) + + GetLengthSid (get_admin_sid ()) + + GetLengthSid (get_world_sid ()); + if (sidGroup) + acl_len += sizeof (ACCESS_ALLOWED_ACE) + - sizeof (DWORD) + + GetLengthSid (sidGroup); + + PACL acl = (PACL) malloc (acl_len); + if (! acl) + { + free (sidOwner); + free (sidGroup); + debug_printf ("malloc 4"); + return FALSE; + } + if (! InitializeAcl (acl, acl_len, ACL_REVISION)) + debug_printf ("InitializeAcl %d", GetLastError ()); + + int ace_off = 0; + ACCESS_ALLOWED_ACE *ace; + + DWORD access = STANDARD_RIGHTS_ALL; + if (attribute & S_IRUSR) + access |= FILE_GENERIC_READ | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA; + if (attribute & S_IWUSR) + access |= FILE_GENERIC_WRITE | DELETE | FILE_DELETE_CHILD; + if (attribute & S_IXUSR) + access |= FILE_GENERIC_EXECUTE; + if (! AddAccessAllowedAce (acl, ACL_REVISION, access, sidOwner)) + debug_printf ("AddAccessAllowedAce(owner) %d", GetLastError ()); + if (GetAce(acl, 0, (PVOID *) &ace)) + ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + + if (! sidGroup || ! EqualSid (sidGroup, get_admin_sid ())) + { + if (! AddAccessAllowedAce (acl, ACL_REVISION, + SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL, + get_admin_sid ())) + debug_printf ("AddAccessAllowedAce(admin) %d", GetLastError ()); + if (GetAce(acl, 1, (PVOID *) &ace)) + ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + ace_off = 1; + } + + if (sidGroup) + { + access = 0; + if (attribute & S_IRGRP) + { + access |= FILE_GENERIC_READ; + if (EqualSid (sidGroup, get_admin_sid ())) + access |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA; + } + if (attribute & S_IWGRP) + access |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE + | DELETE | FILE_DELETE_CHILD; + if (attribute & S_IXGRP) + access |= FILE_GENERIC_EXECUTE; + if (! AddAccessAllowedAce (acl, ACL_REVISION, access, sidGroup)) + debug_printf ("AddAccessAllowedAce(group) %d", GetLastError ()); + if (GetAce(acl, 1 + ace_off, (PVOID *) &ace)) + ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + } + + access = 0; + if (attribute & S_IROTH) + access |= FILE_GENERIC_READ; + if (attribute & S_IWOTH) + access |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE + | DELETE | FILE_DELETE_CHILD; + if (attribute & S_IXOTH) + access |= FILE_GENERIC_EXECUTE; + if (! AddAccessAllowedAce (acl, ACL_REVISION, access, get_world_sid ())) + debug_printf ("AddAccessAllowedAce(world) %d", GetLastError ()); + if (GetAce(acl, 2 + ace_off, (PVOID *) &ace)) + ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; + + if (! SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE)) + debug_printf ("SetSecurityDescriptorDacl %d", GetLastError ()); + + if (! SetFileSecurity (file, + OWNER_SECURITY_INFORMATION + | (grp ? GROUP_SECURITY_INFORMATION : 0) + | DACL_SECURITY_INFORMATION, + &sd)) + debug_printf ("SetFileSecurity %d", GetLastError()); + + free (sidOwner); + free (sidGroup); + free (acl); + + return TRUE; +} + +BOOL +set_file_attribute (const char *file, uid_t uid, gid_t gid, int attribute) +{ + // symlinks are anything for everyone! + if ((attribute & S_IFLNK) == S_IFLNK) + attribute |= S_IRWXU | S_IRWXG | S_IRWXO; + + BOOL ret = NTWriteEA (file, ".UNIXATTR", + (char *) &attribute, sizeof (attribute)); + + if (!allow_ntsec) + return ret; + + ret = set_nt_attribute (file, uid, gid, attribute); + + syscall_printf ("%d = set_file_attribute (%s, %d, %d, %p)", ret, file, uid, gid, attribute); + + return ret; } BOOL set_file_attribute (const char *file, int attribute) { - return NTWriteEA (file, ".UNIXATTR", (char *) &attribute, - sizeof (attribute)); + return set_file_attribute (file, myself->uid, myself->gid, attribute); } --------------76F080FB75CF85B656CAA21C--