Repost: Patch, Version 2: UNIX-like permissions on objects

Corinna Vinschen corinna.vinschen@cityweb.de
Fri Mar 5 13:54:00 GMT 1999


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
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.ebert@ixos-leipzig.de
+   Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
+   Extensions by Corinna Vinschen <corinna.vinschen@cityweb.de>
 
 This file is part of Cygwin.
 
@@ -13,23 +14,35 @@ details. */
 #include <grp.h>
 #include <pwd.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #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);
 }



More information about the Cygwin-developers mailing list