This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project. See the Cygwin home page for more information.
[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index] [Subject Index] [Author Index] [Thread Index]

Patch, Version 3: Unix-like permissions on objects



Hi Geoffrey, hi Sergey, hi all,

I have a new version of the patch, which I have attached relative to
winsup-990303. It now seems to work fine on SP3 and SP4. The major
problem was the implementation of `get_world_sid()' in security.cc,
which wasn't stable enough. The intermediate patch, not to use
`EqualSid()', was a dead end, because it was only a symptom, not the
reason.

The attached version doesn't contain anymore the patches to
exception.cc and strace.cc, which were too dangerous.

New is the patch to grp.cc, which now reads the world group with
`LookupAccountSid(get_world_sid (),...)' from NT security database 
as the default group, for the case a group isn't found or the group
file doesn't exist. It seems to work now, if neither /etc/group,
nor /etc/passwd exist, too.

Moreover new is the patch to fhandler.cc, which only calls
`set_file_attribute()', if the opened file is a disk file.
SP4 seems to be irritated, if you try to set file security
on "nul".

I also have tested (again and again), if the ./configure runs without
core dump, as I described as problem yesterday.

If we want to use NT security without /etc/passwd and /etc/group file,
somebody should explain, how to create a SID, if you only know a
computername or domain and a RID, e.g. 500 or 544.

Regards,
Corinna

ChangeLog:
==========

Sat Mar  6 18:30:00  Corinna Vinschen  <corinna.vinschen@cityweb.de>

	* security.cc (get_world_sid): Rewritten.

	* security.cc (world_full_access): Deleted.

	* grp.cc: Use gid 0 as default gid.

	* grp.cc (read_etc_group): Look for account name of world group.

	* fhandler.cc (fhandler_base::open): Call `set_file_attribute'
	only in case of disk file.

Fri Feb 26 00:44:00  Corinna Vinschen  <corinna.vinschen@cityweb.de>

	* security.cc (get_file_attribute): Patched incorrect test
	for symlink.

	* security.cc (set_file_attribute): ditto.

Sat Jan 30 02:12:00  Corinna Vinschen  <corinna.vinschen@cityweb.de>

        * security.cc: Special handling for user and/or administrators
        permissions to write (extended) attributes.

Fri Jan 29 02:12:00  Corinna Vinschen  <corinna.vinschen@cityweb.de>

        * security.cc: Don't allow 513(nobody) as user or group.

Thu Jan 28 11:00:00  Corinna Vinschen  <corinna.vinschen@cityweb.de>

        * security.cc: new functions `set_nt_attribute()', `get_nt_attribute()'
        and `set_file_attribute()' with additional parameters `uid' and `gid',
        to support real NT security.

        * winsup.h: Prototype for `set_file_attribute()' with four
        parameters.

        * dir.cc (mkdir): Calls `set_file_attribute()' now.

        * syscalls.cc (chown): ditto.

        * syscalls.cc (chmod): ditto, with correct uid/gid.

21 Jan 12:30:00 1999  Corinna Vinschen  <corinna.vinschen@cityweb.de>

        * shared.cc: New function `get_admin_sid()' to get a SID
        of the administrators group or of administrator.
        New functions `sec_user()' and `sec_user_nih()' to get
        SECURITY_ATTRIBUTES with all permissions for the user and
        the administtrator group.

        * shared.h: Prototypes for the above new functions `sec_user()'
        and `sec_user_nih()'.

        * sigproc.cc (getsem): Create process semaphore with
        permissions set by `sec_user()'.
Index: dir.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/dir.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 dir.cc
--- dir.cc	1999/03/05 22:26:48	1.1
+++ dir.cc	1999/03/05 23:11:13
@@ -273,3 +273,7 @@ mkdir (const char *dir, mode_t mode)
   if (CreateDirectoryA (real_dir.get_win32 (), 0))
-    res = 0;
+    {
+      set_file_attribute (real_dir.get_win32 (),
+                          (mode & 0777) & ~myself->umask);
+      res = 0;
+    }
   else
Index: environ.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/environ.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 environ.cc
--- environ.cc	1999/03/05 22:26:48	1.1
+++ environ.cc	1999/03/05 23:17:34
@@ -19,2 +19,3 @@ extern BOOL allow_glob;
 extern BOOL allow_ntea;
+extern BOOL allow_ntsec;
 extern BOOL strip_title_path;
@@ -379,2 +380,3 @@ parse_options (char *buf)
       add ("ntea", &allow_ntea, justset, FALSE, TRUE);
+      add ("ntsec", &allow_ntsec, justset, FALSE, TRUE);
       add ("reset_com", &reset_com, justset, FALSE, TRUE);
Index: fhandler.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/fhandler.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 fhandler.cc
--- fhandler.cc	1999/03/05 22:26:48	1.1
+++ fhandler.cc	1999/03/06 08:54:11
@@ -300,3 +300,4 @@ fhandler_base::open (int flags, mode_t m
 
-  if (flags & O_CREAT)
+  if ((flags & O_CREAT) == O_CREAT
+      && (get_device () == FH_DISK))
     {
Index: grp.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/grp.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 grp.cc
--- grp.cc	1999/03/05 22:26:49	1.1
+++ grp.cc	1999/03/06 16:23:46
@@ -34,4 +34,4 @@ static int grp_pos = 0;
 /* Default values used if accessing /etc/group isn't possible */
-static char def_gr_name[] = "everyone";
-static int def_gr_gid = 500;
+static char def_gr_name[64];
+static int def_gr_gid = 0;
 static struct group defgroup;
@@ -97,2 +97,14 @@ read_etc_group ()
 {
+  extern PSID get_world_sid ();
+  DWORD nlen, dlen;
+  char dom[256];
+  SID_NAME_USE acc_type;
+
+  if (! LookupAccountSid (NULL, get_world_sid (),
+                          def_gr_name, (nlen = 64, &nlen),
+                          dom, (dlen = 256, &dlen),
+			  &acc_type))
+    strcpy (def_gr_name, "everyone");
+  debug_printf("def_gr_name: <%s>", def_gr_name);
+
   FILE *f = fopen (etc_group, "r");
@@ -112,3 +124,7 @@ read_etc_group ()
   else /* /etc/group doesn't exist -- create default one in memory */
-    add_grp_line ("everyone::500:\n");
+    {
+      strcpy (dom, def_gr_name);
+      strcat (dom, "::0:\n");
+      //add_grp_line ("everyone::500:\n");
+    }
 
Index: security.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/security.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 security.cc
--- security.cc	1999/03/05 22:26:50	1.1
+++ security.cc	1999/03/06 17:49:52
@@ -2,5 +2,6 @@
 
-   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>
 
@@ -15,77 +16,28 @@ details. */
 #include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "winsup.h"
 
-#if 0
-PSID
-get_world_sid ()
-{
-  PSID world_sid;
-  SID_IDENTIFIER_AUTHORITY world_sid_auth = SECURITY_WORLD_SID_AUTHORITY;
-
-  world_sid = (PSID) LocalAlloc (LPTR,GetSidLengthRequired (1));
+extern BOOL allow_ntea;
+BOOL allow_ntsec = FALSE;
 
-  InitializeSid (world_sid, &world_sid_auth, 1);
-  *(GetSidSubAuthority (world_sid, 0)) = SECURITY_WORLD_RID;
+extern PSID get_admin_sid ();
 
-  return world_sid;
-}
-
-int
-world_full_access (HANDLE h, int type)
+PSID
+get_world_sid ()
 {
-  PSID world_sid = NULL;
-  PSECURITY_DESCRIPTOR psd = NULL;
-  PACL pacl = NULL;
-  DWORD acl_size = 1024;
-
-  world_sid = get_world_sid();
-
-  if (!world_sid)
-    goto clean_on_error;
-
-  psd = (PSECURITY_DESCRIPTOR) LocalAlloc (LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
-
-  if (!psd)
-    goto clean_on_error;
-
-  if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION))
-    goto clean_on_error;
+  static NO_COPY PSID sidBuf;
 
-  pacl = (PACL) LocalAlloc (LPTR, acl_size);
-
-  if (!pacl)
-    goto clean_on_error;
-
-  /* FIXME: the 3rd parameter is actually ACL_REVISION which is
-     not defined in Scott Christley's header files. */
-  if (!InitializeAcl (pacl, acl_size, 2))
-    goto clean_on_error;
-
-  if (!AddAccessAllowedAce (pacl, 2, type, world_sid))
-    goto clean_on_error;
-
-  if (!SetSecurityDescriptorDacl (psd, TRUE, pacl, FALSE))
-    goto clean_on_error;
-
-  if(!SetKernelObjectSecurity (h, DACL_SECURITY_INFORMATION, psd))
-    goto clean_on_error;
-
-  LocalFree ((HANDLE) world_sid);
-  LocalFree ((HANDLE) psd);
-  LocalFree ((HANDLE) pacl);
-  return TRUE;
-
-clean_on_error:
-    if (world_sid)
-	LocalFree ((HANDLE) world_sid);
-
-    if (psd)
-	LocalFree ((HANDLE) psd);
-
-    if (pacl)
-	LocalFree ((HANDLE) pacl);
-
-    return FALSE;
+  if (! sidBuf)
+    {
+      SID_IDENTIFIER_AUTHORITY world_sid_auth = SECURITY_WORLD_SID_AUTHORITY;
+      
+      AllocateAndInitializeSid (&world_sid_auth, 1,
+                                SECURITY_WORLD_RID, 0, 0, 0,
+				0, 0, 0, 0,
+				&sidBuf);
+    }
+  return sidBuf;
 }
-#endif
 
@@ -155,6 +107,153 @@ get_id_from_sid (PSID psid)
 }
+
+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;
+    }
+
+  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 ());
+
+  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))
+	{
+	  switch (ace->Header.AceType)
+	    {
+	    case ACCESS_ALLOWED_ACE_TYPE:
+              if (sidOwner && EqualSid ((PSID) &ace->SidStart, sidOwner))
+	        {
+		  *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 (sidGroup && EqualSid ((PSID) &ace->SidStart, sidGroup))
+	        {
+		  *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 (EqualSid ((PSID) &ace->SidStart, get_world_sid ()))
+	        {
+		  *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;
+	    }
+        }
+    }
 
-/*
- * File attribute stuff. FIXME: add NTFS security.
- */
+  free (sd);
+  syscall_printf ("file: %s %x", file, *attribute);
+  return TRUE;
+}
 
@@ -163,5 +262,243 @@ get_file_attribute (const char *file, in
 {
+  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;
 }
@@ -171,4 +508,3 @@ set_file_attribute (const char *file, in
 {
-  return NTWriteEA (file, ".UNIXATTR", (char *) &attribute,
-		    sizeof (attribute));
+  return set_file_attribute (file, myself->uid, myself->gid, attribute);
 }
Index: shared.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/shared.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 shared.cc
--- shared.cc	1999/03/05 22:26:50	1.1
+++ shared.cc	1999/03/06 16:34:01
@@ -12,2 +12,5 @@ details. */
 #include <stdio.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <pwd.h>
 #include "winsup.h"
@@ -186,2 +189,172 @@ SECURITY_DESCRIPTOR *get_null_sd ()
   return null_sdp;
+}
+
+PSID
+get_admin_sid ()
+{
+  static NO_COPY PSID sidBuf;
+
+  if (! sidBuf)
+    {
+      struct group *gr_ptr;
+      struct passwd *pw_ptr;
+      char user[32], dom[100];
+      DWORD sidlen, domlen;
+      SID_NAME_USE acc_type;
+
+      sidBuf = (PSID) malloc (1024);
+
+      // Get name of administrator group from /etc/group
+
+      if ((gr_ptr = getgrgid (544)) != NULL
+          && strcmp (gr_ptr->gr_name, "everyone"))
+        strcpy (user, gr_ptr->gr_name);
+
+      // else get name of administrator group from /etc/passwd
+
+      else if ((pw_ptr = getpwuid (544)) != NULL)
+        strcpy (user, pw_ptr->pw_name);
+
+      // else get name of administrator from /etc/passwd
+
+      else if ((pw_ptr = getpwuid (500)) != NULL)
+        strcpy (user, pw_ptr->pw_name);
+
+      // else try "administrator"
+
+      else
+        strcpy (user, "administrator");
+
+      if (! LookupAccountName (NULL, user,
+                               sidBuf, (sidlen = 1024, &sidlen),
+                               dom, (domlen = 100, &domlen),
+                               &acc_type))
+        {
+          free (sidBuf);
+          sidBuf = NULL;
+        }
+      else
+        sidBuf = (PSID) realloc (sidBuf, sidlen + 1);
+    }
+  return sidBuf;
+}
+
+struct user_sa {
+  char                user[32];
+  SECURITY_ATTRIBUTES sa;
+  SECURITY_ATTRIBUTES sa_nih;
+  SECURITY_DESCRIPTOR sd;
+  PACL                acl;
+};
+
+static NO_COPY int sa_cnt = 0;
+static NO_COPY user_sa *sa_list;
+
+SECURITY_ATTRIBUTES *
+sec_user (BOOL inherit)
+{
+  for (int i = 0; i < sa_cnt; ++i)
+    if (! strcmp (sa_list[i].user, getlogin ()))
+      {
+        debug_printf("user not found: %s", getlogin());
+        return inherit ? &sa_list[i].sa_nih : &sa_list[i].sa;
+      }
+
+  PSID sidBuf;
+
+  sidBuf = (PSID) malloc (1024);
+  if (! sidBuf)
+	{
+      debug_printf("malloc 1");
+      return inherit ? &sec_none_nih : &sec_none;
+    }
+
+  DWORD sidlen, domlen;
+  char dom[100];
+  SID_NAME_USE acc_type;
+
+  if (! LookupAccountName (NULL, getlogin (),
+			   sidBuf, (sidlen = 1024, &sidlen),
+			   dom, (domlen = 100, &domlen),
+			   &acc_type))
+    {
+      debug_printf("LookupAccountName(%s) %E", getlogin());
+      free (sidBuf);
+      return inherit ? &sec_none_nih : &sec_none;
+    }
+  else if (acc_type != SidTypeUser)
+    {
+      char domuser[356];
+      strcpy (domuser, dom);
+      strcat (domuser, "\\");
+      strcat (domuser, getlogin ());
+      if (! LookupAccountName (NULL, domuser,
+			       sidBuf, (sidlen = 1024, &sidlen),
+			       dom, (domlen = 100, &domlen),
+			       &acc_type))
+	{
+          debug_printf("LookupAccountName(%s) %E", domuser);
+	  free (sidBuf);
+	  return inherit ? &sec_none_nih : &sec_none;
+	}
+    }
+  sidBuf = (PSID) realloc (sidBuf, sidlen + 1);
+
+  size_t acl_len = sizeof (ACL)
+                   + 2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD))
+	           + GetLengthSid (sidBuf)
+	           + GetLengthSid (get_admin_sid ());
+  PACL acl = (PACL) malloc (acl_len);
+  if (! acl)
+    {
+      debug_printf("malloc 2");
+      free (sidBuf);
+      return inherit ? &sec_none_nih : &sec_none;
+    }
+  if (! InitializeAcl (acl, acl_len, ACL_REVISION))
+    debug_printf("InitializeAcl %E");
+  if (! AddAccessAllowedAce (acl, ACL_REVISION,
+                             SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
+	                     sidBuf))
+    debug_printf("AddAccessAllowedAce(%s) %E", getlogin());
+
+  if (! AddAccessAllowedAce (acl, ACL_REVISION,
+                             SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
+	                     get_admin_sid ()))
+    debug_printf("AddAccessAllowedAce(admin) %E");
+
+  user_sa *tmp_sa_list = (user_sa *) realloc (sa_list,
+                                              (sa_cnt + 1) * sizeof (user_sa));
+  if (! tmp_sa_list)
+    {
+      debug_printf("malloc 3");
+      free (acl);
+      free (sidBuf);
+      return inherit ? &sec_none_nih : &sec_none;
+    }
+  sa_list = tmp_sa_list;
+
+  sa_list[sa_cnt].acl = acl;
+  if (! InitializeSecurityDescriptor (&sa_list[sa_cnt].sd,
+                                      SECURITY_DESCRIPTOR_REVISION))
+    debug_printf("InitializeSecurityDescriptor %E");
+  if (! SetSecurityDescriptorOwner (&sa_list[sa_cnt].sd, sidBuf, FALSE))
+    debug_printf("SetSecurityDescriptorOwner %E");
+  if (! SetSecurityDescriptorDacl (&sa_list[sa_cnt].sd, TRUE, acl, FALSE))
+    debug_printf("SetSecurityDescriptorDacl %E");
+  sa_list[sa_cnt].sa.nLength =
+  sa_list[sa_cnt].sa_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
+  sa_list[sa_cnt].sa.lpSecurityDescriptor =
+  sa_list[sa_cnt].sa_nih.lpSecurityDescriptor = &sa_list[sa_cnt].sd;
+  sa_list[sa_cnt].sa.bInheritHandle = TRUE;
+  sa_list[sa_cnt].sa_nih.bInheritHandle = FALSE;
+  strcpy (sa_list[sa_cnt].user, getlogin ());
+  ++sa_cnt;
+  return inherit ? &sa_list[sa_cnt - 1].sa : &sa_list[sa_cnt - 1].sa_nih;
+}
+
+SECURITY_ATTRIBUTES *
+sec_user_nih ()
+{
+  return sec_user (FALSE);
 }
Index: shared.h
===================================================================
RCS file: /src/cvsroot/winsup-990303/shared.h,v
retrieving revision 1.1
diff -u -p -1 -r1.1 shared.h
--- shared.h	1999/03/05 22:26:50	1.1
+++ shared.h	1999/03/05 22:57:33
@@ -465,2 +465,4 @@ public:
 extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih;
+extern SECURITY_ATTRIBUTES *sec_user (BOOL inherit = TRUE);
+extern SECURITY_ATTRIBUTES *sec_user_nih ();
 
Index: sigproc.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/sigproc.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 sigproc.cc
--- sigproc.cc	1999/03/05 22:26:50	1.1
+++ sigproc.cc	1999/03/05 23:08:56
@@ -1070,3 +1070,3 @@ getsem (pinfo *p, const char *str, int i
       DWORD winpid = GetCurrentProcessId ();
-      h = CreateSemaphore (&sec_none_nih, init, max, str = shared_name (str, winpid));
+      h = CreateSemaphore (sec_user (), init, max, str = shared_name (str, winpid));
       p = myself;
Index: syscalls.cc
===================================================================
RCS file: /src/cvsroot/winsup-990303/syscalls.cc,v
retrieving revision 1.1
diff -u -p -1 -r1.1 syscalls.cc
--- syscalls.cc	1999/03/05 22:26:50	1.1
+++ syscalls.cc	1999/03/05 23:16:20
@@ -880,2 +880,7 @@ retry:
 
+		  int attrib;
+		  BOOL a_ok;
+
+		  a_ok = get_file_attribute (win32_path.get_win32 (), &attrib);
+
 		  /* open the file again for write owner and dac */
@@ -926,2 +931,6 @@ retry:
 		  syscall_printf ("0 = chown (%s,...)", name);
+
+		  if (a_ok)
+		    set_file_attribute (win32_path.get_win32 (),
+		                        uid, gid, attrib);
 		  return 0;
Index: winsup.h
===================================================================
RCS file: /src/cvsroot/winsup-990303/winsup.h,v
retrieving revision 1.1
diff -u -p -1 -r1.1 winsup.h
--- winsup.h	1999/03/05 22:26:51	1.1
+++ winsup.h	1999/03/05 23:09:20
@@ -355,2 +355,3 @@ BOOL get_file_attribute (const char *, i
 BOOL set_file_attribute (const char *, int);
+BOOL set_file_attribute (const char *, uid_t, gid_t, int);
 void set_std_handle (int);