aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog18
-rw-r--r--winsup/cygwin/Makefile.in2
-rw-r--r--winsup/cygwin/grp.cc99
-rw-r--r--winsup/cygwin/sec_acl.cc1060
-rw-r--r--winsup/cygwin/sec_helper.cc399
-rw-r--r--winsup/cygwin/security.cc1417
-rw-r--r--winsup/cygwin/security.h43
7 files changed, 1575 insertions, 1463 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index c8789b7..5b5f048 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,21 @@
+Fri Apr 20 14:50:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in: Add object files `sec_helper.cc' and `sec_acl.cc'.
+ * security.cc: Swap out several functions.
+ * sec_acl.cc: New file. Move Sun compatibel ACL functions from
+ `security.cc' to here.
+ * sec_helper.cc: New file. Move security helper functions from
+ `security.cc' to here.
+ * security.h: Changed to accomodate the above changes.
+
+Fri Apr 20 14:12:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * grp.cc: Replace `group_in_memory_p' by `group_state'.
+ Eliminate group_sem throughout.
+ (enum grp_state): New enumeration type.
+ (read_etc_group): Make race safe.
+ * security.cc: Eliminate group_sem throughout.
+
Thu Apr 19 9:40:00 2001 Corinna Vinschen <corinna@vinschen.de>
* mmap.cc (mmap): Drop usage of the same memory area if the same
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index 438ff5f..7eeaf12 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -122,7 +122,7 @@ DLL_OFILES:=assert.o autoload.o cygheap.o dcrt0.o debug.o delqueue.o dir.o \
fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \
miscfuncs.o mmap.o net.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \
pthread.o regexp.o regerror.o regsub.o registry.o resource.o scandir.o \
- sched.o security.o select.o shared.o shortcut.o signal.o sigproc.o \
+ sched.o sec_acl.o sec_helper.o security.o select.o shared.o shortcut.o signal.o sigproc.o \
smallprint.o spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o \
syslog.o termios.o thread.o times.o tty.o uinfo.o uname.o wait.o \
window.o \
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index ed6091f..2b1b598 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -42,12 +42,17 @@ static int max_lines = 0;
static int grp_pos = 0;
#endif
-/* Set to 1 when /etc/group has been read in by read_etc_group (). */
-/* Functions in this file need to check the value of group_in_memory_p
- and read in the group file if it isn't set. */
-/* FIXME: This should be static but this is called in uinfo_init outside
- this file */
-int group_in_memory_p = 0;
+/* Set to loaded when /etc/passwd has been read in by read_etc_passwd ().
+ Set to emulated if passwd is emulated. */
+/* Functions in this file need to check the value of passwd_state
+ and read in the password file if it isn't set. */
+enum grp_state {
+ uninitialized = 0,
+ initializing,
+ emulated,
+ loaded
+};
+static grp_state group_state = uninitialized;
static int
parse_grp (struct group &grp, const char *line)
@@ -132,50 +137,64 @@ extern PSID get_admin_sid ();
void
read_etc_group ()
{
- extern int group_sem;
char linebuf [200];
char group_name [MAX_USER_NAME];
DWORD group_name_len = MAX_USER_NAME;
strncpy (group_name, "Administrators", sizeof (group_name));
- ++group_sem;
- FILE *f = fopen (etc_group, "rt");
- --group_sem;
+ static pthread_mutex_t etc_group_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock (&etc_group_mutex);
- if (f)
+ /* if we got blocked by the mutex, then etc_group may have been processed */
+ if (group_state != uninitialized)
{
- while (fgets (linebuf, sizeof (linebuf), f) != NULL)
- {
- if (strlen (linebuf))
- add_grp_line (linebuf);
- }
-
- fclose (f);
+ pthread_mutex_unlock(&etc_group_mutex);
+ return;
}
- else /* /etc/group doesn't exist -- create default one in memory */
+
+ if (group_state != initializing)
{
- char domain_name [MAX_DOMAIN_NAME];
- DWORD domain_name_len = MAX_DOMAIN_NAME;
- SID_NAME_USE acType;
- debug_printf ("Emulating /etc/group");
- if (! LookupAccountSidA (NULL ,
- get_admin_sid () ,
- group_name,
- &group_name_len,
- domain_name,
- &domain_name_len,
- &acType))
+ group_state = initializing;
+
+ FILE *f = fopen (etc_group, "rt");
+
+ if (f)
{
- strcpy (group_name, "unknown");
- debug_printf ("Failed to get local admins group name. %E");
- }
+ while (fgets (linebuf, sizeof (linebuf), f) != NULL)
+ {
+ if (strlen (linebuf))
+ add_grp_line (linebuf);
+ }
- snprintf (linebuf, sizeof (linebuf), "%s::%u:\n", group_name, DEFAULT_GID);
- add_grp_line (linebuf);
+ fclose (f);
+ group_state = loaded;
+ }
+ else /* /etc/group doesn't exist -- create default one in memory */
+ {
+ char domain_name [MAX_DOMAIN_NAME];
+ DWORD domain_name_len = MAX_DOMAIN_NAME;
+ SID_NAME_USE acType;
+ debug_printf ("Emulating /etc/group");
+ if (! LookupAccountSidA (NULL ,
+ get_admin_sid () ,
+ group_name,
+ &group_name_len,
+ domain_name,
+ &domain_name_len,
+ &acType))
+ {
+ strcpy (group_name, "unknown");
+ debug_printf ("Failed to get local admins group name. %E");
+ }
+
+ snprintf (linebuf, sizeof (linebuf), "%s::%u:\n", group_name, DEFAULT_GID);
+ add_grp_line (linebuf);
+ group_state = emulated;
+ }
}
- group_in_memory_p = 1;
+ pthread_mutex_unlock(&etc_group_mutex);
}
extern "C"
@@ -183,7 +202,7 @@ struct group *
getgrgid (gid_t gid)
{
struct group * default_grp = NULL;
- if (!group_in_memory_p)
+ if (group_state <= initializing)
read_etc_group();
for (int i = 0; i < curr_lines; i++)
@@ -201,7 +220,7 @@ extern "C"
struct group *
getgrnam (const char *name)
{
- if (!group_in_memory_p)
+ if (group_state <= initializing)
read_etc_group();
for (int i = 0; i < curr_lines; i++)
@@ -223,7 +242,7 @@ extern "C"
struct group *
getgrent()
{
- if (!group_in_memory_p)
+ if (group_state <= initializing)
read_etc_group();
if (grp_pos < curr_lines)
@@ -247,7 +266,7 @@ getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username)
DWORD size;
int cnt = 0;
- if (!group_in_memory_p)
+ if (group_state <= initializing)
read_etc_group();
if (allow_ntsec &&
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
new file mode 100644
index 0000000..0ae0a69
--- /dev/null
+++ b/winsup/cygwin/sec_acl.cc
@@ -0,0 +1,1060 @@
+/* secacl.cc: Sun compatible ACL functions.
+
+ Copyright 2000, 2001 Cygnus Solutions.
+
+ Written by Corinna Vinschen <corinna@vinschen.de>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <grp.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/acl.h>
+#include <ctype.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include "cygerrno.h"
+#include "perprocess.h"
+#include "fhandler.h"
+#include "path.h"
+#include "dtable.h"
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "cygheap.h"
+#include "security.h"
+
+static int
+searchace (aclent_t *aclp, int nentries, int type, int id = -1)
+{
+ int i;
+
+ for (i = 0; i < nentries; ++i)
+ if ((aclp[i].a_type == type && (id < 0 || aclp[i].a_id == id))
+ || !aclp[i].a_type)
+ return i;
+ return -1;
+}
+
+static int
+setacl (const char *file, int nentries, aclent_t *aclbufp)
+{
+ DWORD sd_size = 4096;
+ char sd_buf[4096];
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
+
+ if (read_sd (file, psd, &sd_size) <= 0)
+ {
+ debug_printf ("read_sd %E");
+ return -1;
+ }
+
+ BOOL dummy;
+
+ /* Get owner SID. */
+ PSID owner_sid = NULL;
+ if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))
+ {
+ __seterrno ();
+ return -1;
+ }
+ char owner_buf[MAX_SID_LEN];
+ if (!CopySid (MAX_SID_LEN, (PSID) owner_buf, owner_sid))
+ {
+ __seterrno ();
+ return -1;
+ }
+ owner_sid = (PSID) owner_buf;
+
+ /* Get group SID. */
+ PSID group_sid = NULL;
+ if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))
+ {
+ __seterrno ();
+ return -1;
+ }
+ char group_buf[MAX_SID_LEN];
+ if (!CopySid (MAX_SID_LEN, (PSID) group_buf, group_sid))
+ {
+ __seterrno ();
+ return -1;
+ }
+ group_sid = (PSID) group_buf;
+
+ /* Initialize local security descriptor. */
+ SECURITY_DESCRIPTOR sd;
+ if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
+ {
+ __seterrno ();
+ return -1;
+ }
+ if (!SetSecurityDescriptorOwner(&sd, owner_sid, FALSE))
+ {
+ __seterrno ();
+ return -1;
+ }
+ if (group_sid
+ && !SetSecurityDescriptorGroup(&sd, group_sid, FALSE))
+ {
+ __seterrno ();
+ return -1;
+ }
+
+ /* Fill access control list. */
+ char acl_buf[3072];
+ PACL acl = (PACL) acl_buf;
+ size_t acl_len = sizeof (ACL);
+ int ace_off = 0;
+
+ char sidbuf[MAX_SID_LEN];
+ PSID sid = (PSID) sidbuf;
+ struct passwd *pw;
+ struct group *gr;
+ int pos;
+
+ if (!InitializeAcl (acl, 3072, ACL_REVISION))
+ {
+ __seterrno ();
+ return -1;
+ }
+ for (int i = 0; i < nentries; ++i)
+ {
+ DWORD allow = STANDARD_RIGHTS_READ
+ | FILE_READ_ATTRIBUTES | FILE_READ_EA;
+ 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;
+ if (aclbufp[i].a_perm & S_IXOTH)
+ allow |= FILE_GENERIC_EXECUTE;
+ /* Set inherit property. */
+ DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
+ ? INHERIT_ONLY : DONT_INHERIT;
+ /*
+ * If a specific acl contains a corresponding default entry with
+ * identical permissions, only one Windows ACE with proper
+ * inheritance bits is created.
+ */
+ if (!(aclbufp[i].a_type & ACL_DEFAULT)
+ && (pos = searchace (aclbufp, nentries,
+ aclbufp[i].a_type | ACL_DEFAULT,
+ (aclbufp[i].a_type & (USER|GROUP))
+ ? aclbufp[i].a_id : -1)) >= 0
+ && pos < nentries
+ && aclbufp[i].a_perm == aclbufp[pos].a_perm)
+ {
+ inheritance = INHERIT_ALL;
+ /* This eliminates the corresponding default entry. */
+ aclbufp[pos].a_type = 0;
+ }
+ switch (aclbufp[i].a_type)
+ {
+ case USER_OBJ:
+ case DEF_USER_OBJ:
+ allow |= STANDARD_RIGHTS_ALL & ~DELETE;
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ owner_sid, acl_len, inheritance))
+ return -1;
+ break;
+ case USER:
+ case DEF_USER:
+ if (!(pw = getpwuid (aclbufp[i].a_id))
+ || !get_pw_sid (sid, pw)
+ || !add_access_allowed_ace (acl, ace_off++, allow,
+ sid, acl_len, inheritance))
+ return -1;
+ break;
+ case GROUP_OBJ:
+ case DEF_GROUP_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ group_sid, acl_len, inheritance))
+ return -1;
+ break;
+ case GROUP:
+ case DEF_GROUP:
+ if (!(gr = getgrgid (aclbufp[i].a_id))
+ || !get_gr_sid (sid, gr)
+ || !add_access_allowed_ace (acl, ace_off++, allow,
+ sid, acl_len, inheritance))
+ return -1;
+ break;
+ case OTHER_OBJ:
+ case DEF_OTHER_OBJ:
+ if (!add_access_allowed_ace (acl, ace_off++, allow,
+ get_world_sid(), acl_len, inheritance))
+ return -1;
+ break;
+ }
+ }
+ /* Set AclSize to computed value. */
+ acl->AclSize = acl_len;
+ debug_printf ("ACL-Size: %d", acl_len);
+ /* Create DACL for local security descriptor. */
+ if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))
+ {
+ __seterrno ();
+ return -1;
+ }
+ /* Make self relative security descriptor in psd. */
+ sd_size = 0;
+ MakeSelfRelativeSD (&sd, psd, &sd_size);
+ if (sd_size <= 0)
+ {
+ __seterrno ();
+ return -1;
+ }
+ if (!MakeSelfRelativeSD (&sd, psd, &sd_size))
+ {
+ __seterrno ();
+ return -1;
+ }
+ debug_printf ("Created SD-Size: %d", sd_size);
+ return write_sd (file, psd, sd_size);
+}
+
+static void
+getace (aclent_t &acl, int type, int id, DWORD win_ace_mask, DWORD win_ace_type)
+{
+ acl.a_type = type;
+ acl.a_id = id;
+
+ if (win_ace_mask & FILE_READ_DATA)
+ if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
+ acl.a_perm |= (acl.a_perm & S_IRGRP) ? 0 : S_IRUSR;
+ else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
+ acl.a_perm &= ~S_IRGRP;
+
+ if (win_ace_mask & FILE_WRITE_DATA)
+ if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
+ acl.a_perm |= (acl.a_perm & S_IWGRP) ? 0 : S_IWUSR;
+ else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
+ acl.a_perm &= ~S_IWGRP;
+
+ if (win_ace_mask & FILE_EXECUTE)
+ if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
+ acl.a_perm |= (acl.a_perm & S_IXGRP) ? 0 : S_IXUSR;
+ else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
+ acl.a_perm &= ~S_IXGRP;
+}
+
+static int
+getacl (const char *file, DWORD attr, int nentries, aclent_t *aclbufp)
+{
+ DWORD sd_size = 4096;
+ char sd_buf[4096];
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
+
+ int ret;
+ if ((ret = read_sd (file, psd, &sd_size)) <= 0)
+ {
+ debug_printf ("read_sd %E");
+ return ret;
+ }
+
+ PSID owner_sid;
+ PSID group_sid;
+ BOOL dummy;
+ uid_t uid;
+ gid_t gid;
+
+ if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))
+ {
+ debug_printf ("GetSecurityDescriptorOwner %E");
+ __seterrno ();
+ return -1;
+ }
+ uid = get_uid_from_sid (owner_sid);
+
+ if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))
+ {
+ debug_printf ("GetSecurityDescriptorGroup %E");
+ __seterrno ();
+ return -1;
+ }
+ gid = get_gid_from_sid (group_sid);
+
+ aclent_t lacl[MAX_ACL_ENTRIES];
+ memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t));
+ lacl[0].a_type = USER_OBJ;
+ lacl[0].a_id = uid;
+ lacl[1].a_type = GROUP_OBJ;
+ lacl[1].a_id = gid;
+ lacl[2].a_type = OTHER_OBJ;
+
+ PACL acl;
+ BOOL acl_exists;
+
+ if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy))
+ {
+ __seterrno ();
+ debug_printf ("GetSecurityDescriptorDacl %E");
+ return -1;
+ }
+
+ int pos, i;
+
+ if (!acl_exists || !acl)
+ {
+ for (pos = 0; pos < MIN_ACL_ENTRIES; ++pos)
+ lacl[pos].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
+ pos = nentries < MIN_ACL_ENTRIES ? nentries : MIN_ACL_ENTRIES;
+ memcpy (aclbufp, lacl, pos * sizeof (aclent_t));
+ return pos;
+ }
+
+ for (i = 0; i < acl->AceCount && (!nentries || i < nentries); ++i)
+ {
+ ACCESS_ALLOWED_ACE *ace;
+
+ if (!GetAce (acl, i, (PVOID *) &ace))
+ continue;
+
+ PSID ace_sid = (PSID) &ace->SidStart;
+ int id;
+ int type = 0;
+
+ if (EqualSid (ace_sid, owner_sid))
+ {
+ type = USER_OBJ;
+ id = uid;
+ }
+ else if (EqualSid (ace_sid, group_sid))
+ {
+ type = GROUP_OBJ;
+ id = gid;
+ }
+ else if (EqualSid (ace_sid, get_world_sid ()))
+ {
+ type = OTHER_OBJ;
+ id = 0;
+ }
+ else
+ {
+ id = get_id_from_sid (ace_sid, FALSE, &type);
+ if (type != GROUP)
+ {
+ int type2 = 0;
+ int id2 = get_id_from_sid (ace_sid, TRUE, &type2);
+ if (type2 == GROUP)
+ {
+ id = id2;
+ type = GROUP;
+ }
+ }
+ }
+ if (!type)
+ continue;
+ if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE))
+ {
+ if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
+ }
+ if ((ace->Header.AceFlags & INHERIT_ALL)
+ && (attr & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ type |= ACL_DEFAULT;
+ if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
+ getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
+ }
+ }
+ if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
+ pos = MAX_ACL_ENTRIES;
+ for (i = 0; i < pos; ++i)
+ {
+ lacl[i].a_perm = (lacl[i].a_perm & S_IRWXU)
+ & ~((lacl[i].a_perm & S_IRWXG) << 3);
+ lacl[i].a_perm |= (lacl[i].a_perm & S_IRWXU) >> 3
+ | (lacl[i].a_perm & S_IRWXU) >> 6;
+ }
+ if ((searchace (lacl, MAX_ACL_ENTRIES, USER) >= 0
+ || searchace (lacl, MAX_ACL_ENTRIES, GROUP) >= 0)
+ && (pos = searchace (lacl, MAX_ACL_ENTRIES, CLASS_OBJ)) >= 0)
+ {
+ lacl[pos].a_type = CLASS_OBJ;
+ lacl[pos].a_perm =
+ lacl[searchace (lacl, MAX_ACL_ENTRIES, GROUP_OBJ)].a_perm;
+ }
+ int dgpos;
+ if ((searchace (lacl, MAX_ACL_ENTRIES, DEF_USER) >= 0
+ || searchace (lacl, MAX_ACL_ENTRIES, DEF_GROUP) >= 0)
+ && (dgpos = searchace (lacl, MAX_ACL_ENTRIES, DEF_GROUP_OBJ)) >= 0
+ && (pos = searchace (lacl, MAX_ACL_ENTRIES, DEF_CLASS_OBJ)) >= 0
+ && (attr & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ lacl[pos].a_type = DEF_CLASS_OBJ;
+ lacl[pos].a_perm = lacl[dgpos].a_perm;
+ }
+ if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
+ pos = MAX_ACL_ENTRIES;
+ if (pos > nentries)
+ pos = nentries;
+ if (aclbufp)
+ memcpy (aclbufp, lacl, pos * sizeof (aclent_t));
+ aclsort (pos, 0, aclbufp);
+ syscall_printf ("%d = getacl (%s)", pos, file);
+ return pos;
+}
+
+int
+acl_access (const char *path, int flags)
+{
+ aclent_t acls[MAX_ACL_ENTRIES];
+ int cnt;
+
+ if ((cnt = acl (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)
+ return -1;
+
+ /* Only check existance. */
+ if (!(flags & (R_OK|W_OK|X_OK)))
+ return 0;
+
+ for (int i = 0; i < cnt; ++i)
+ {
+ switch (acls[i].a_type)
+ {
+ case USER_OBJ:
+ case USER:
+ if (acls[i].a_id != myself->uid)
+ {
+ /*
+ * Check if user is a NT group:
+ * Take SID from passwd, search SID in group, check is_grp_member.
+ */
+ char owner_sidbuf[MAX_SID_LEN];
+ PSID owner_sid = (PSID) owner_sidbuf;
+ char group_sidbuf[MAX_SID_LEN];
+ PSID group_sid = (PSID) group_sidbuf;
+ struct passwd *pw;
+ struct group *gr = NULL;
+
+ if ((pw = getpwuid (acls[i].a_id)) != NULL
+ && get_pw_sid (owner_sid, pw))
+ {
+ while ((gr = getgrent ()))
+ if (get_gr_sid (group_sid, gr)
+ && EqualSid (owner_sid, group_sid)
+ && is_grp_member (myself->uid, gr->gr_gid))
+ break;
+ endgrent ();
+ }
+ if (!gr)
+ continue;
+ }
+ break;
+ case GROUP_OBJ:
+ case GROUP:
+ if (acls[i].a_id != myself->gid &&
+ !is_grp_member (myself->uid, acls[i].a_id))
+ continue;
+ break;
+ case OTHER_OBJ:
+ break;
+ default:
+ continue;
+ }
+ if ((!(flags & R_OK) || (acls[i].a_perm & S_IREAD))
+ && (!(flags & W_OK) || (acls[i].a_perm & S_IWRITE))
+ && (!(flags & X_OK) || (acls[i].a_perm & S_IEXEC)))
+ return 0;
+ }
+ set_errno (EACCES);
+ return -1;
+}
+
+static
+int
+acl_worker (const char *path, int cmd, int nentries, aclent_t *aclbufp,
+ int nofollow)
+{
+ extern suffix_info stat_suffixes[];
+ path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes);
+ if (real_path.error)
+ {
+ set_errno (real_path.error);
+ syscall_printf ("-1 = acl (%s)", path);
+ return -1;
+ }
+ if (!real_path.has_acls ())
+ {
+ struct stat st;
+ int ret = -1;
+
+ switch (cmd)
+ {
+ case SETACL:
+ set_errno (ENOSYS);
+ break;
+ case GETACL:
+ if (nentries < 1)
+ set_errno (EINVAL);
+ else if ((nofollow && !lstat (path, &st))
+ || (!nofollow && !stat (path, &st)))
+ {
+ aclent_t lacl[4];
+ if (nentries > 0)
+ {
+ lacl[0].a_type = USER_OBJ;
+ lacl[0].a_id = st.st_uid;
+ lacl[0].a_perm = (st.st_mode & S_IRWXU)
+ | (st.st_mode & S_IRWXU) >> 3
+ | (st.st_mode & S_IRWXU) >> 6;
+ }
+ if (nentries > 1)
+ {
+ lacl[1].a_type = GROUP_OBJ;
+ lacl[1].a_id = st.st_gid;
+ lacl[1].a_perm = (st.st_mode & S_IRWXG)
+ | (st.st_mode & S_IRWXG) << 3
+ | (st.st_mode & S_IRWXG) >> 3;
+ }
+ if (nentries > 2)
+ {
+ lacl[2].a_type = OTHER_OBJ;
+ lacl[2].a_id = 0;
+ lacl[2].a_perm = (st.st_mode & S_IRWXO)
+ | (st.st_mode & S_IRWXO) << 6
+ | (st.st_mode & S_IRWXO) << 3;
+ }
+ if (nentries > 3)
+ {
+ lacl[3].a_type = CLASS_OBJ;
+ lacl[3].a_id = 0;
+ lacl[3].a_perm = (st.st_mode & S_IRWXG)
+ | (st.st_mode & S_IRWXG) << 3
+ | (st.st_mode & S_IRWXG) >> 3;
+ }
+ if (nentries > 4)
+ nentries = 4;
+ if (aclbufp)
+ memcpy (aclbufp, lacl, nentries * sizeof (aclent_t));
+ ret = nentries;
+ }
+ break;
+ case GETACLCNT:
+ ret = 4;
+ break;
+ }
+ syscall_printf ("%d = acl (%s)", ret, path);
+ return ret;
+ }
+ switch (cmd)
+ {
+ case SETACL:
+ if (!aclsort(nentries, 0, aclbufp))
+ return setacl (real_path.get_win32 (),
+ nentries, aclbufp);
+ break;
+ case GETACL:
+ if (nentries < 1)
+ break;
+ return getacl (real_path.get_win32 (),
+ real_path.file_attributes (),
+ nentries, aclbufp);
+ case GETACLCNT:
+ return getacl (real_path.get_win32 (),
+ real_path.file_attributes (),
+ 0, NULL);
+ default:
+ break;
+ }
+ set_errno (EINVAL);
+ syscall_printf ("-1 = acl (%s)", path);
+ return -1;
+}
+
+extern "C"
+int
+acl (const char *path, int cmd, int nentries, aclent_t *aclbufp)
+{
+ return acl_worker (path, cmd, nentries, aclbufp, 0);
+}
+
+extern "C"
+int
+lacl (const char *path, int cmd, int nentries, aclent_t *aclbufp)
+{
+ return acl_worker (path, cmd, nentries, aclbufp, 1);
+}
+
+extern "C"
+int
+facl (int fd, int cmd, int nentries, aclent_t *aclbufp)
+{
+ if (cygheap->fdtab.not_open (fd))
+ {
+ syscall_printf ("-1 = facl (%d)", fd);
+ set_errno (EBADF);
+ return -1;
+ }
+ const char *path = cygheap->fdtab[fd]->get_name ();
+ if (path == NULL)
+ {
+ syscall_printf ("-1 = facl (%d) (no name)", fd);
+ set_errno (ENOSYS);
+ return -1;
+ }
+ syscall_printf ("facl (%d): calling acl (%s)", fd, path);
+ return acl_worker (path, cmd, nentries, aclbufp, 0);
+}
+
+extern "C"
+int
+aclcheck (aclent_t *aclbufp, int nentries, int *which)
+{
+ BOOL has_user_obj = FALSE;
+ BOOL has_group_obj = FALSE;
+ BOOL has_other_obj = FALSE;
+ BOOL has_class_obj = FALSE;
+ BOOL has_ug_objs = FALSE;
+ BOOL has_def_user_obj = FALSE;
+ BOOL has_def_group_obj = FALSE;
+ BOOL has_def_other_obj = FALSE;
+ BOOL has_def_class_obj = FALSE;
+ BOOL has_def_ug_objs = FALSE;
+ int pos2;
+
+ for (int pos = 0; pos < nentries; ++pos)
+ switch (aclbufp[pos].a_type)
+ {
+ case USER_OBJ:
+ if (has_user_obj)
+ {
+ if (which)
+ *which = pos;
+ return USER_ERROR;
+ }
+ has_user_obj = TRUE;
+ break;
+ case GROUP_OBJ:
+ if (has_group_obj)
+ {
+ if (which)
+ *which = pos;
+ return GRP_ERROR;
+ }
+ has_group_obj = TRUE;
+ break;
+ case OTHER_OBJ:
+ if (has_other_obj)
+ {
+ if (which)
+ *which = pos;
+ return OTHER_ERROR;
+ }
+ has_other_obj = TRUE;
+ break;
+ case CLASS_OBJ:
+ if (has_class_obj)
+ {
+ if (which)
+ *which = pos;
+ return CLASS_ERROR;
+ }
+ has_class_obj = TRUE;
+ break;
+ case USER:
+ case GROUP:
+ if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
+ aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
+ {
+ if (which)
+ *which = pos2;
+ return DUPLICATE_ERROR;
+ }
+ has_ug_objs = TRUE;
+ break;
+ case DEF_USER_OBJ:
+ if (has_def_user_obj)
+ {
+ if (which)
+ *which = pos;
+ return USER_ERROR;
+ }
+ has_def_user_obj = TRUE;
+ break;
+ case DEF_GROUP_OBJ:
+ if (has_def_group_obj)
+ {
+ if (which)
+ *which = pos;
+ return GRP_ERROR;
+ }
+ has_def_group_obj = TRUE;
+ break;
+ case DEF_OTHER_OBJ:
+ if (has_def_other_obj)
+ {
+ if (which)
+ *which = pos;
+ return OTHER_ERROR;
+ }
+ has_def_other_obj = TRUE;
+ break;
+ case DEF_CLASS_OBJ:
+ if (has_def_class_obj)
+ {
+ if (which)
+ *which = pos;
+ return CLASS_ERROR;
+ }
+ has_def_class_obj = TRUE;
+ break;
+ case DEF_USER:
+ case DEF_GROUP:
+ if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
+ aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
+ {
+ if (which)
+ *which = pos2;
+ return DUPLICATE_ERROR;
+ }
+ has_def_ug_objs = TRUE;
+ break;
+ default:
+ return ENTRY_ERROR;
+ }
+ if (!has_user_obj
+ || !has_group_obj
+ || !has_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)
+ *which = -1;
+ return MISS_ERROR;
+ }
+ return 0;
+}
+
+extern "C"
+int acecmp (const void *a1, const void *a2)
+{
+#define ace(i) ((const aclent_t *) a##i)
+ int ret = ace(1)->a_type - ace(2)->a_type;
+ if (!ret)
+ ret = ace(1)->a_id - ace(2)->a_id;
+ return ret;
+#undef ace
+}
+
+extern "C"
+int
+aclsort (int nentries, int, aclent_t *aclbufp)
+{
+ if (aclcheck (aclbufp, nentries, NULL))
+ return -1;
+ if (!aclbufp || nentries < 1)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ qsort((void *) aclbufp, nentries, sizeof (aclent_t), acecmp);
+ return 0;
+}
+
+extern "C"
+int
+acltomode (aclent_t *aclbufp, int nentries, mode_t *modep)
+{
+ int pos;
+
+ if (!aclbufp || nentries < 1 || !modep)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ *modep = 0;
+ if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ *modep |= aclbufp[pos].a_perm & S_IRWXU;
+ if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (searchace (aclbufp, nentries, CLASS_OBJ) < 0)
+ pos = searchace (aclbufp, nentries, CLASS_OBJ);
+ *modep |= (aclbufp[pos].a_perm & S_IRWXU) >> 3;
+ if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ *modep |= (aclbufp[pos].a_perm & S_IRWXU) >> 6;
+ return 0;
+}
+
+extern "C"
+int
+aclfrommode(aclent_t *aclbufp, int nentries, mode_t *modep)
+{
+ int pos;
+
+ if (!aclbufp || nentries < 1 || !modep)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ aclbufp[pos].a_perm = (*modep & S_IRWXU)
+ | (*modep & S_IRWXU) >> 3
+ | (*modep & S_IRWXU) >> 6;
+ if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (searchace (aclbufp, nentries, CLASS_OBJ) < 0)
+ pos = searchace (aclbufp, nentries, CLASS_OBJ);
+ aclbufp[pos].a_perm = (*modep & S_IRWXG)
+ | (*modep & S_IRWXG) << 3
+ | (*modep & S_IRWXG) >> 3;
+ if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ aclbufp[pos].a_perm = (*modep & S_IRWXO)
+ | (*modep & S_IRWXO) << 6
+ | (*modep & S_IRWXO) << 3;
+ return 0;
+}
+
+extern "C"
+int
+acltopbits (aclent_t *aclbufp, int nentries, mode_t *pbitsp)
+{
+ return acltomode (aclbufp, nentries, pbitsp);
+}
+
+extern "C"
+int
+aclfrompbits (aclent_t *aclbufp, int nentries, mode_t *pbitsp)
+{
+ return aclfrommode (aclbufp, nentries, pbitsp);
+}
+
+static char *
+permtostr (mode_t perm)
+{
+ static char pbuf[4];
+
+ pbuf[0] = (perm & S_IREAD) ? 'r' : '-';
+ pbuf[1] = (perm & S_IWRITE) ? 'w' : '-';
+ pbuf[2] = (perm & S_IEXEC) ? 'x' : '-';
+ pbuf[3] = '\0';
+ return pbuf;
+}
+
+extern "C"
+char *
+acltotext (aclent_t *aclbufp, int aclcnt)
+{
+ if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES
+ || aclcheck (aclbufp, aclcnt, NULL))
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ char buf[32000];
+ buf[0] = '\0';
+ BOOL first = TRUE;
+
+ for (int pos = 0; pos < aclcnt; ++pos)
+ {
+ if (!first)
+ strcat (buf, ",");
+ first = FALSE;
+ if (aclbufp[pos].a_type & ACL_DEFAULT)
+ strcat (buf, "default");
+ switch (aclbufp[pos].a_type)
+ {
+ case USER_OBJ:
+ __small_sprintf (buf + strlen (buf), "user::%s",
+ permtostr (aclbufp[pos].a_perm));
+ break;
+ case USER:
+ __small_sprintf (buf + strlen (buf), "user:%d:%s",
+ aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
+ break;
+ case GROUP_OBJ:
+ __small_sprintf (buf + strlen (buf), "group::%s",
+ permtostr (aclbufp[pos].a_perm));
+ break;
+ case GROUP:
+ __small_sprintf (buf + strlen (buf), "group:%d:%s",
+ aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
+ break;
+ case CLASS_OBJ:
+ __small_sprintf (buf + strlen (buf), "mask::%s",
+ permtostr (aclbufp[pos].a_perm));
+ break;
+ case OTHER_OBJ:
+ __small_sprintf (buf + strlen (buf), "other::%s",
+ permtostr (aclbufp[pos].a_perm));
+ break;
+ default:
+ set_errno (EINVAL);
+ return NULL;
+ }
+ }
+ return strdup (buf);
+}
+
+static mode_t
+permfromstr (char *perm)
+{
+ mode_t mode = 0;
+
+ if (strlen (perm) != 3)
+ return 01000;
+ if (perm[0] == 'r')
+ mode |= S_IRUSR | S_IRGRP | S_IROTH;
+ else if (perm[0] != '-')
+ return 01000;
+ if (perm[1] == 'w')
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ else if (perm[1] != '-')
+ return 01000;
+ if (perm[2] == 'x')
+ mode |= S_IXUSR | S_IXGRP | S_IXOTH;
+ else if (perm[2] != '-')
+ return 01000;
+ return mode;
+}
+
+extern "C"
+aclent_t *
+aclfromtext (char *acltextp, int *)
+{
+ if (!acltextp)
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ char buf[strlen (acltextp) + 1];
+ aclent_t lacl[MAX_ACL_ENTRIES];
+ memset (lacl, 0, sizeof lacl);
+ int pos = 0;
+ strcpy (buf, acltextp);
+ char *lasts;
+ for (char *c = strtok_r (buf, ",", &lasts);
+ c;
+ c = strtok_r (NULL, ",", &lasts))
+ {
+ if (!strncmp (c, "default", 7))
+ {
+ lacl[pos].a_type |= ACL_DEFAULT;
+ c += 7;
+ }
+ if (!strncmp (c, "user:", 5))
+ {
+ if (c[5] == ':')
+ lacl[pos].a_type |= USER_OBJ;
+ else
+ {
+ lacl[pos].a_type |= USER;
+ c += 5;
+ if (isalpha (*c))
+ {
+ struct passwd *pw = getpwnam (c);
+ if (!pw)
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ lacl[pos].a_id = pw->pw_uid;
+ c = strchr (c, ':');
+ }
+ else if (isdigit (*c))
+ lacl[pos].a_id = strtol (c, &c, 10);
+ if (!c || *c != ':')
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ }
+ }
+ else if (!strncmp (c, "group:", 6))
+ {
+ if (c[5] == ':')
+ lacl[pos].a_type |= GROUP_OBJ;
+ else
+ {
+ lacl[pos].a_type |= GROUP;
+ c += 5;
+ if (isalpha (*c))
+ {
+ struct group *gr = getgrnam (c);
+ if (!gr)
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ lacl[pos].a_id = gr->gr_gid;
+ c = strchr (c, ':');
+ }
+ else if (isdigit (*c))
+ lacl[pos].a_id = strtol (c, &c, 10);
+ if (!c || *c != ':')
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ }
+ }
+ else if (!strncmp (c, "mask:", 5))
+ {
+ if (c[5] == ':')
+ lacl[pos].a_type |= CLASS_OBJ;
+ else
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ }
+ else if (!strncmp (c, "other:", 6))
+ {
+ if (c[5] == ':')
+ lacl[pos].a_type |= OTHER_OBJ;
+ else
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ }
+ if ((lacl[pos].a_perm = permfromstr (c)) == 01000)
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
+ ++pos;
+ }
+ aclent_t *aclp = (aclent_t *) malloc (pos * sizeof (aclent_t));
+ if (aclp)
+ memcpy (aclp, lacl, pos * sizeof (aclent_t));
+ return aclp;
+}
+
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
new file mode 100644
index 0000000..1771d93
--- /dev/null
+++ b/winsup/cygwin/sec_helper.cc
@@ -0,0 +1,399 @@
+/* sec_helper.cc: NT security helper functions
+
+ Copyright 2000, 2001 Cygnus Solutions.
+
+ Written by Corinna Vinschen <corinna@vinschen.de>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <grp.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/acl.h>
+#include <ctype.h>
+#include <wingdi.h>
+#include <winuser.h>
+#include "cygerrno.h"
+#include "perprocess.h"
+#include "fhandler.h"
+#include "path.h"
+#include "dtable.h"
+#include "sync.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "cygheap.h"
+#include "security.h"
+
+SID_IDENTIFIER_AUTHORITY sid_auth[] = {
+ {SECURITY_NULL_SID_AUTHORITY},
+ {SECURITY_WORLD_SID_AUTHORITY},
+ {SECURITY_LOCAL_SID_AUTHORITY},
+ {SECURITY_CREATOR_SID_AUTHORITY},
+ {SECURITY_NON_UNIQUE_AUTHORITY},
+ {SECURITY_NT_AUTHORITY}
+};
+
+char *
+convert_sid_to_string_sid (PSID psid, char *sid_str)
+{
+ char t[32];
+ DWORD i;
+
+ if (!psid || !sid_str)
+ return NULL;
+ strcpy (sid_str, "S-1-");
+ __small_sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
+ strcat (sid_str, t);
+ for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
+ {
+ __small_sprintf(t, "-%lu", *GetSidSubAuthority (psid, i));
+ strcat (sid_str, t);
+ }
+ return sid_str;
+}
+
+PSID
+get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r)
+{
+ DWORD i;
+
+ if (!psid || s > 5 || cnt < 1 || cnt > 8)
+ return NULL;
+
+ InitializeSid(psid, &sid_auth[s], cnt);
+ for (i = 0; i < cnt; ++i)
+ memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
+ return psid;
+}
+
+PSID
+convert_string_sid_to_sid (PSID psid, const char *sid_str)
+{
+ char sid_buf[256];
+ char *t, *lasts;
+ DWORD cnt = 0;
+ DWORD s = 0;
+ DWORD i, r[8];
+
+ if (!sid_str || strncmp (sid_str, "S-1-", 4))
+ return NULL;
+
+ strcpy (sid_buf, sid_str);
+
+ for (t = sid_buf + 4, i = 0;
+ cnt < 8 && (t = strtok_r (t, "-", &lasts));
+ t = NULL, ++i)
+ if (i == 0)
+ s = strtoul (t, NULL, 10);
+ else
+ r[cnt++] = strtoul (t, NULL, 10);
+
+ return get_sid (psid, s, cnt, r);
+}
+
+BOOL
+get_pw_sid (PSID sid, struct passwd *pw)
+{
+ char *sp = pw->pw_gecos ? strrchr (pw->pw_gecos, ',') : NULL;
+
+ if (!sp)
+ return FALSE;
+ return convert_string_sid_to_sid (sid, ++sp) != NULL;
+}
+
+BOOL
+get_gr_sid (PSID sid, struct group *gr)
+{
+ return convert_string_sid_to_sid (sid, gr->gr_passwd) != NULL;
+}
+
+PSID
+get_admin_sid ()
+{
+ static NO_COPY char admin_sid_buf[MAX_SID_LEN];
+ static NO_COPY PSID admin_sid = NULL;
+
+ if (!admin_sid)
+ {
+ admin_sid = (PSID) admin_sid_buf;
+ convert_string_sid_to_sid (admin_sid, "S-1-5-32-544");
+ }
+ return admin_sid;
+}
+
+PSID
+get_system_sid ()
+{
+ static NO_COPY char system_sid_buf[MAX_SID_LEN];
+ static NO_COPY PSID system_sid = NULL;
+
+ if (!system_sid)
+ {
+ system_sid = (PSID) system_sid_buf;
+ convert_string_sid_to_sid (system_sid, "S-1-5-18");
+ }
+ return system_sid;
+}
+
+PSID
+get_creator_owner_sid ()
+{
+ static NO_COPY char owner_sid_buf[MAX_SID_LEN];
+ static NO_COPY PSID owner_sid = NULL;
+
+ if (!owner_sid)
+ {
+ owner_sid = (PSID) owner_sid_buf;
+ convert_string_sid_to_sid (owner_sid, "S-1-3-0");
+ }
+ return owner_sid;
+}
+
+PSID
+get_world_sid ()
+{
+ static NO_COPY char world_sid_buf[MAX_SID_LEN];
+ static NO_COPY PSID world_sid = NULL;
+
+ if (!world_sid)
+ {
+ world_sid = (PSID) world_sid_buf;
+ convert_string_sid_to_sid (world_sid, "S-1-1-0");
+ }
+ return world_sid;
+}
+
+int
+get_id_from_sid (PSID psid, BOOL search_grp, int *type)
+{
+ if (!IsValidSid (psid))
+ {
+ __seterrno ();
+ small_printf ("IsValidSid failed with %E");
+ return -1;
+ }
+
+ /* First try to get SID from passwd or group entry */
+ if (allow_ntsec)
+ {
+ char sidbuf[MAX_SID_LEN];
+ PSID sid = (PSID) sidbuf;
+ int id = -1;
+
+ if (!search_grp)
+ {
+ struct passwd *pw;
+ while ((pw = getpwent ()) != NULL)
+ {
+ if (get_pw_sid (sid, pw) && EqualSid (psid, sid))
+ {
+ id = pw->pw_uid;
+ break;
+ }
+ }
+ endpwent ();
+ if (id >= 0)
+ {
+ if (type)
+ *type = USER;
+ return id;
+ }
+ }
+ if (search_grp || type)
+ {
+ struct group *gr;
+ while ((gr = getgrent ()) != NULL)
+ {
+ if (get_gr_sid (sid, gr) && EqualSid (psid, sid))
+ {
+ id = gr->gr_gid;
+ break;
+ }
+ }
+ endgrent ();
+ if (id >= 0)
+ {
+ if (type)
+ *type = GROUP;
+ return id;
+ }
+ }
+ }
+
+ /* We use the RID as default UID/GID */
+ int id = *GetSidSubAuthority(psid, *GetSidSubAuthorityCount(psid) - 1);
+
+ /*
+ * The RID maybe -1 if accountname == computername.
+ * In this case we search for the accountname in the passwd and group files.
+ * If type is needed, we search in each case.
+ */
+ if (id == -1 || type)
+ {
+ char account[MAX_USER_NAME];
+ char domain[MAX_COMPUTERNAME_LENGTH+1];
+ DWORD acc_len = MAX_USER_NAME;
+ DWORD dom_len = MAX_COMPUTERNAME_LENGTH+1;
+ SID_NAME_USE acc_type;
+
+ if (!LookupAccountSid (NULL, psid, account, &acc_len,
+ domain, &dom_len, &acc_type))
+ {
+ __seterrno ();
+ return -1;
+ }
+
+ switch (acc_type)
+ {
+ case SidTypeGroup:
+ case SidTypeAlias:
+ case SidTypeWellKnownGroup:
+ if (type)
+ *type = GROUP;
+ if (id == -1)
+ {
+ struct group *gr = getgrnam (account);
+ if (gr)
+ id = gr->gr_gid;
+ }
+ break;
+ case SidTypeUser:
+ if (type)
+ *type = USER;
+ if (id == -1)
+ {
+ struct passwd *pw = getpwnam (account);
+ if (pw)
+ id = pw->pw_uid;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (id == -1)
+ id = getuid ();
+ return id;
+}
+
+int
+get_id_from_sid (PSID psid, BOOL search_grp)
+{
+ return get_id_from_sid (psid, search_grp, NULL);
+}
+
+BOOL
+legal_sid_type (SID_NAME_USE type)
+{
+ return type == SidTypeUser || type == SidTypeGroup
+ || SidTypeAlias || SidTypeWellKnownGroup;
+}
+
+BOOL
+is_grp_member (uid_t uid, gid_t gid)
+{
+ extern int getgroups (int, gid_t *, gid_t, const char *);
+ BOOL grp_member = TRUE;
+
+ struct passwd *pw = getpwuid (uid);
+ gid_t grps[NGROUPS_MAX];
+ int cnt = getgroups (NGROUPS_MAX, grps,
+ pw ? pw->pw_gid : myself->gid,
+ pw ? pw->pw_name : cygheap->user.name ());
+ int i;
+ for (i = 0; i < cnt; ++i)
+ if (grps[i] == gid)
+ break;
+ grp_member = (i < cnt);
+ return grp_member;
+}
+
+BOOL
+lookup_name (const char *name, const char *logsrv, PSID ret_sid)
+{
+ char sidbuf[MAX_SID_LEN];
+ PSID sid = (PSID) sidbuf;
+ DWORD sidlen;
+ char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1];
+ char dom[MAX_COMPUTERNAME_LENGTH+1];
+ DWORD domlen;
+ SID_NAME_USE acc_type;
+
+ debug_printf ("name : %s", name ? name : "NULL");
+
+ if (!name)
+ return FALSE;
+
+ if (cygheap->user.domain ())
+ {
+ strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name);
+ if (LookupAccountName (NULL, domuser,
+ sid, (sidlen = MAX_SID_LEN, &sidlen),
+ dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
+ &acc_type)
+ && legal_sid_type (acc_type))
+ goto got_it;
+ if (logsrv && *logsrv
+ && LookupAccountName (logsrv, domuser,
+ sid, (sidlen = MAX_SID_LEN, &sidlen),
+ dom, (domlen = MAX_COMPUTERNAME_LENGTH,&domlen),
+ &acc_type)
+ && legal_sid_type (acc_type))
+ goto got_it;
+ }
+ if (logsrv && *logsrv)
+ {
+ if (LookupAccountName (logsrv, name,
+ sid, (sidlen = MAX_SID_LEN, &sidlen),
+ dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
+ &acc_type)
+ && legal_sid_type (acc_type))
+ goto got_it;
+ if (acc_type == SidTypeDomain)
+ {
+ strcat (strcat (strcpy (domuser, dom), "\\"), name);
+ if (LookupAccountName (logsrv, domuser,
+ sid,(sidlen = MAX_SID_LEN, &sidlen),
+ dom,(domlen = MAX_COMPUTERNAME_LENGTH,&domlen),
+ &acc_type))
+ goto got_it;
+ }
+ }
+ if (LookupAccountName (NULL, name,
+ sid, (sidlen = MAX_SID_LEN, &sidlen),
+ dom, (domlen = 100, &domlen),
+ &acc_type)
+ && legal_sid_type (acc_type))
+ goto got_it;
+ if (acc_type == SidTypeDomain)
+ {
+ strcat (strcat (strcpy (domuser, dom), "\\"), name);
+ if (LookupAccountName (NULL, domuser,
+ sid, (sidlen = MAX_SID_LEN, &sidlen),
+ dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
+ &acc_type))
+ goto got_it;
+ }
+ debug_printf ("LookupAccountName(%s) %E", name);
+ __seterrno ();
+ return FALSE;
+
+got_it:
+ debug_printf ("sid : [%d]", *GetSidSubAuthority((PSID) sid,
+ *GetSidSubAuthorityCount((PSID) sid) - 1));
+
+ if (ret_sid)
+ memcpy (ret_sid, sid, sidlen);
+
+ return TRUE;
+}
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index d780103..38c741f 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -42,384 +42,6 @@ BOOL allow_ntsec = FALSE;
The default is TRUE to reflect the old behaviour. */
BOOL allow_smbntsec = TRUE;
-SID_IDENTIFIER_AUTHORITY sid_auth[] = {
- {SECURITY_NULL_SID_AUTHORITY},
- {SECURITY_WORLD_SID_AUTHORITY},
- {SECURITY_LOCAL_SID_AUTHORITY},
- {SECURITY_CREATOR_SID_AUTHORITY},
- {SECURITY_NON_UNIQUE_AUTHORITY},
- {SECURITY_NT_AUTHORITY}
-};
-
-#define DONT_INHERIT (0)
-#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
-#define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
-
-char *
-convert_sid_to_string_sid (PSID psid, char *sid_str)
-{
- char t[32];
- DWORD i;
-
- if (!psid || !sid_str)
- return NULL;
- strcpy (sid_str, "S-1-");
- __small_sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
- strcat (sid_str, t);
- for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
- {
- __small_sprintf(t, "-%lu", *GetSidSubAuthority (psid, i));
- strcat (sid_str, t);
- }
- return sid_str;
-}
-
-PSID
-get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r)
-{
- DWORD i;
-
- if (!psid || s > 5 || cnt < 1 || cnt > 8)
- return NULL;
-
- InitializeSid(psid, &sid_auth[s], cnt);
- for (i = 0; i < cnt; ++i)
- memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
- return psid;
-}
-
-PSID
-convert_string_sid_to_sid (PSID psid, const char *sid_str)
-{
- char sid_buf[256];
- char *t, *lasts;
- DWORD cnt = 0;
- DWORD s = 0;
- DWORD i, r[8];
-
- if (!sid_str || strncmp (sid_str, "S-1-", 4))
- return NULL;
-
- strcpy (sid_buf, sid_str);
-
- for (t = sid_buf + 4, i = 0;
- cnt < 8 && (t = strtok_r (t, "-", &lasts));
- t = NULL, ++i)
- if (i == 0)
- s = strtoul (t, NULL, 10);
- else
- r[cnt++] = strtoul (t, NULL, 10);
-
- return get_sid (psid, s, cnt, r);
-}
-
-BOOL
-get_pw_sid (PSID sid, struct passwd *pw)
-{
- char *sp = pw->pw_gecos ? strrchr (pw->pw_gecos, ',') : NULL;
-
- if (!sp)
- return FALSE;
- return convert_string_sid_to_sid (sid, ++sp) != NULL;
-}
-
-BOOL
-get_gr_sid (PSID sid, struct group *gr)
-{
- return convert_string_sid_to_sid (sid, gr->gr_passwd) != NULL;
-}
-
-PSID
-get_admin_sid ()
-{
- static NO_COPY char admin_sid_buf[MAX_SID_LEN];
- static NO_COPY PSID admin_sid = NULL;
-
- if (!admin_sid)
- {
- admin_sid = (PSID) admin_sid_buf;
- convert_string_sid_to_sid (admin_sid, "S-1-5-32-544");
- }
- return admin_sid;
-}
-
-PSID
-get_system_sid ()
-{
- static NO_COPY char system_sid_buf[MAX_SID_LEN];
- static NO_COPY PSID system_sid = NULL;
-
- if (!system_sid)
- {
- system_sid = (PSID) system_sid_buf;
- convert_string_sid_to_sid (system_sid, "S-1-5-18");
- }
- return system_sid;
-}
-
-PSID
-get_creator_owner_sid ()
-{
- static NO_COPY char owner_sid_buf[MAX_SID_LEN];
- static NO_COPY PSID owner_sid = NULL;
-
- if (!owner_sid)
- {
- owner_sid = (PSID) owner_sid_buf;
- convert_string_sid_to_sid (owner_sid, "S-1-3-0");
- }
- return owner_sid;
-}
-
-PSID
-get_world_sid ()
-{
- static NO_COPY char world_sid_buf[MAX_SID_LEN];
- static NO_COPY PSID world_sid = NULL;
-
- if (!world_sid)
- {
- world_sid = (PSID) world_sid_buf;
- convert_string_sid_to_sid (world_sid, "S-1-1-0");
- }
- return world_sid;
-}
-
-int group_sem = 0;
-
-static int
-get_id_from_sid (PSID psid, BOOL search_grp, int *type)
-{
- if (!IsValidSid (psid))
- {
- __seterrno ();
- small_printf ("IsValidSid failed with %E");
- return -1;
- }
-
- /* First try to get SID from passwd or group entry */
- if (allow_ntsec)
- {
- char sidbuf[MAX_SID_LEN];
- PSID sid = (PSID) sidbuf;
- int id = -1;
-
- if (!search_grp)
- {
- struct passwd *pw;
- while ((pw = getpwent ()) != NULL)
- {
- if (get_pw_sid (sid, pw) && EqualSid (psid, sid))
- {
- id = pw->pw_uid;
- break;
- }
- }
- endpwent ();
- if (id >= 0)
- {
- if (type)
- *type = USER;
- return id;
- }
- }
- if (search_grp || type)
- {
- if (group_sem > 0)
- return 0;
- ++group_sem;
-
- struct group *gr;
- while ((gr = getgrent ()) != NULL)
- {
- if (get_gr_sid (sid, gr) && EqualSid (psid, sid))
- {
- id = gr->gr_gid;
- break;
- }
- }
- endgrent ();
- --group_sem;
- if (id >= 0)
- {
- if (type)
- *type = GROUP;
- return id;
- }
- }
- }
-
- /* We use the RID as default UID/GID */
- int id = *GetSidSubAuthority(psid, *GetSidSubAuthorityCount(psid) - 1);
-
- /*
- * The RID maybe -1 if accountname == computername.
- * In this case we search for the accountname in the passwd and group files.
- * If type is needed, we search in each case.
- */
- if (id == -1 || type)
- {
- char account[MAX_USER_NAME];
- char domain[MAX_COMPUTERNAME_LENGTH+1];
- DWORD acc_len = MAX_USER_NAME;
- DWORD dom_len = MAX_COMPUTERNAME_LENGTH+1;
- SID_NAME_USE acc_type;
-
- if (!LookupAccountSid (NULL, psid, account, &acc_len,
- domain, &dom_len, &acc_type))
- {
- __seterrno ();
- return -1;
- }
-
- switch (acc_type)
- {
- case SidTypeGroup:
- case SidTypeAlias:
- case SidTypeWellKnownGroup:
- if (type)
- *type = GROUP;
- if (id == -1)
- {
- struct group *gr = getgrnam (account);
- if (gr)
- id = gr->gr_gid;
- }
- break;
- case SidTypeUser:
- if (type)
- *type = USER;
- if (id == -1)
- {
- struct passwd *pw = getpwnam (account);
- if (pw)
- id = pw->pw_uid;
- }
- break;
- default:
- break;
- }
- }
- if (id == -1)
- id = getuid ();
- return id;
-}
-
-int
-get_id_from_sid (PSID psid, BOOL search_grp)
-{
- return get_id_from_sid (psid, search_grp, NULL);
-}
-
-static BOOL
-legal_sid_type (SID_NAME_USE type)
-{
- return type == SidTypeUser || type == SidTypeGroup
- || SidTypeAlias || SidTypeWellKnownGroup;
-}
-
-BOOL
-is_grp_member (uid_t uid, gid_t gid)
-{
- extern int getgroups (int, gid_t *, gid_t, const char *);
- BOOL grp_member = TRUE;
-
- if (!group_sem)
- {
- struct passwd *pw = getpwuid (uid);
- gid_t grps[NGROUPS_MAX];
- int cnt = getgroups (NGROUPS_MAX, grps,
- pw ? pw->pw_gid : myself->gid,
- pw ? pw->pw_name : cygheap->user.name ());
- int i;
- for (i = 0; i < cnt; ++i)
- if (grps[i] == gid)
- break;
- grp_member = (i < cnt);
- }
- return grp_member;
-}
-
-BOOL
-lookup_name (const char *name, const char *logsrv, PSID ret_sid)
-{
- char sidbuf[MAX_SID_LEN];
- PSID sid = (PSID) sidbuf;
- DWORD sidlen;
- char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1];
- char dom[MAX_COMPUTERNAME_LENGTH+1];
- DWORD domlen;
- SID_NAME_USE acc_type;
-
- debug_printf ("name : %s", name ? name : "NULL");
-
- if (!name)
- return FALSE;
-
- if (cygheap->user.domain ())
- {
- strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name);
- if (LookupAccountName (NULL, domuser,
- sid, (sidlen = MAX_SID_LEN, &sidlen),
- dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
- &acc_type)
- && legal_sid_type (acc_type))
- goto got_it;
- if (logsrv && *logsrv
- && LookupAccountName (logsrv, domuser,
- sid, (sidlen = MAX_SID_LEN, &sidlen),
- dom, (domlen = MAX_COMPUTERNAME_LENGTH,&domlen),
- &acc_type)
- && legal_sid_type (acc_type))
- goto got_it;
- }
- if (logsrv && *logsrv)
- {
- if (LookupAccountName (logsrv, name,
- sid, (sidlen = MAX_SID_LEN, &sidlen),
- dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
- &acc_type)
- && legal_sid_type (acc_type))
- goto got_it;
- if (acc_type == SidTypeDomain)
- {
- strcat (strcat (strcpy (domuser, dom), "\\"), name);
- if (LookupAccountName (logsrv, domuser,
- sid,(sidlen = MAX_SID_LEN, &sidlen),
- dom,(domlen = MAX_COMPUTERNAME_LENGTH,&domlen),
- &acc_type))
- goto got_it;
- }
- }
- if (LookupAccountName (NULL, name,
- sid, (sidlen = MAX_SID_LEN, &sidlen),
- dom, (domlen = 100, &domlen),
- &acc_type)
- && legal_sid_type (acc_type))
- goto got_it;
- if (acc_type == SidTypeDomain)
- {
- strcat (strcat (strcpy (domuser, dom), "\\"), name);
- if (LookupAccountName (NULL, domuser,
- sid, (sidlen = MAX_SID_LEN, &sidlen),
- dom, (domlen = MAX_COMPUTERNAME_LENGTH, &domlen),
- &acc_type))
- goto got_it;
- }
- debug_printf ("LookupAccountName(%s) %E", name);
- __seterrno ();
- return FALSE;
-
-got_it:
- debug_printf ("sid : [%d]", *GetSidSubAuthority((PSID) sid,
- *GetSidSubAuthorityCount((PSID) sid) - 1));
-
- if (ret_sid)
- memcpy (ret_sid, sid, sidlen);
-
- return TRUE;
-}
-
extern "C"
void
cygwin_set_impersonation_token (const HANDLE hToken)
@@ -836,8 +458,9 @@ get_file_attribute (int use_ntsec, const char *file,
return res > 0 ? 0 : -1;
}
-BOOL add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
- PSID sid, size_t &len_add, DWORD inherit)
+BOOL
+add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
+ PSID sid, size_t &len_add, DWORD inherit)
{
if (!AddAccessAllowedAce (acl, ACL_REVISION, attributes, sid))
{
@@ -852,8 +475,9 @@ BOOL add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
return TRUE;
}
-BOOL add_access_denied_ace (PACL acl, int offset, DWORD attributes,
- PSID sid, size_t &len_add, DWORD inherit)
+BOOL
+add_access_denied_ace (PACL acl, int offset, DWORD attributes,
+ PSID sid, size_t &len_add, DWORD inherit)
{
if (!AddAccessDeniedAce (acl, ACL_REVISION, attributes, sid))
{
@@ -1177,1032 +801,3 @@ set_file_attribute (int use_ntsec, const char *file, int attribute)
myself->uid, myself->gid,
attribute, cygheap->user.logsrv ());
}
-
-static int
-searchace (aclent_t *aclp, int nentries, int type, int id = -1)
-{
- int i;
-
- for (i = 0; i < nentries; ++i)
- if ((aclp[i].a_type == type && (id < 0 || aclp[i].a_id == id))
- || !aclp[i].a_type)
- return i;
- return -1;
-}
-
-static int
-setacl (const char *file, int nentries, aclent_t *aclbufp)
-{
- DWORD sd_size = 4096;
- char sd_buf[4096];
- PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
-
- if (read_sd (file, psd, &sd_size) <= 0)
- {
- debug_printf ("read_sd %E");
- return -1;
- }
-
- BOOL dummy;
-
- /* Get owner SID. */
- PSID owner_sid = NULL;
- if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))
- {
- __seterrno ();
- return -1;
- }
- char owner_buf[MAX_SID_LEN];
- if (!CopySid (MAX_SID_LEN, (PSID) owner_buf, owner_sid))
- {
- __seterrno ();
- return -1;
- }
- owner_sid = (PSID) owner_buf;
-
- /* Get group SID. */
- PSID group_sid = NULL;
- if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))
- {
- __seterrno ();
- return -1;
- }
- char group_buf[MAX_SID_LEN];
- if (!CopySid (MAX_SID_LEN, (PSID) group_buf, group_sid))
- {
- __seterrno ();
- return -1;
- }
- group_sid = (PSID) group_buf;
-
- /* Initialize local security descriptor. */
- SECURITY_DESCRIPTOR sd;
- if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
- {
- __seterrno ();
- return -1;
- }
- if (!SetSecurityDescriptorOwner(&sd, owner_sid, FALSE))
- {
- __seterrno ();
- return -1;
- }
- if (group_sid
- && !SetSecurityDescriptorGroup(&sd, group_sid, FALSE))
- {
- __seterrno ();
- return -1;
- }
-
- /* Fill access control list. */
- char acl_buf[3072];
- PACL acl = (PACL) acl_buf;
- size_t acl_len = sizeof (ACL);
- int ace_off = 0;
-
- char sidbuf[MAX_SID_LEN];
- PSID sid = (PSID) sidbuf;
- struct passwd *pw;
- struct group *gr;
- int pos;
-
- if (!InitializeAcl (acl, 3072, ACL_REVISION))
- {
- __seterrno ();
- return -1;
- }
- for (int i = 0; i < nentries; ++i)
- {
- DWORD allow = STANDARD_RIGHTS_READ
- | FILE_READ_ATTRIBUTES | FILE_READ_EA;
- 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;
- if (aclbufp[i].a_perm & S_IXOTH)
- allow |= FILE_GENERIC_EXECUTE;
- /* Set inherit property. */
- DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
- ? INHERIT_ONLY : DONT_INHERIT;
- /*
- * If a specific acl contains a corresponding default entry with
- * identical permissions, only one Windows ACE with proper
- * inheritance bits is created.
- */
- if (!(aclbufp[i].a_type & ACL_DEFAULT)
- && (pos = searchace (aclbufp, nentries,
- aclbufp[i].a_type | ACL_DEFAULT,
- (aclbufp[i].a_type & (USER|GROUP))
- ? aclbufp[i].a_id : -1)) >= 0
- && pos < nentries
- && aclbufp[i].a_perm == aclbufp[pos].a_perm)
- {
- inheritance = INHERIT_ALL;
- /* This eliminates the corresponding default entry. */
- aclbufp[pos].a_type = 0;
- }
- switch (aclbufp[i].a_type)
- {
- case USER_OBJ:
- case DEF_USER_OBJ:
- allow |= STANDARD_RIGHTS_ALL & ~DELETE;
- if (!add_access_allowed_ace (acl, ace_off++, allow,
- owner_sid, acl_len, inheritance))
- return -1;
- break;
- case USER:
- case DEF_USER:
- if (!(pw = getpwuid (aclbufp[i].a_id))
- || !get_pw_sid (sid, pw)
- || !add_access_allowed_ace (acl, ace_off++, allow,
- sid, acl_len, inheritance))
- return -1;
- break;
- case GROUP_OBJ:
- case DEF_GROUP_OBJ:
- if (!add_access_allowed_ace (acl, ace_off++, allow,
- group_sid, acl_len, inheritance))
- return -1;
- break;
- case GROUP:
- case DEF_GROUP:
- if (!(gr = getgrgid (aclbufp[i].a_id))
- || !get_gr_sid (sid, gr)
- || !add_access_allowed_ace (acl, ace_off++, allow,
- sid, acl_len, inheritance))
- return -1;
- break;
- case OTHER_OBJ:
- case DEF_OTHER_OBJ:
- if (!add_access_allowed_ace (acl, ace_off++, allow,
- get_world_sid(), acl_len, inheritance))
- return -1;
- break;
- }
- }
- /* Set AclSize to computed value. */
- acl->AclSize = acl_len;
- debug_printf ("ACL-Size: %d", acl_len);
- /* Create DACL for local security descriptor. */
- if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))
- {
- __seterrno ();
- return -1;
- }
- /* Make self relative security descriptor in psd. */
- sd_size = 0;
- MakeSelfRelativeSD (&sd, psd, &sd_size);
- if (sd_size <= 0)
- {
- __seterrno ();
- return -1;
- }
- if (!MakeSelfRelativeSD (&sd, psd, &sd_size))
- {
- __seterrno ();
- return -1;
- }
- debug_printf ("Created SD-Size: %d", sd_size);
- return write_sd (file, psd, sd_size);
-}
-
-static void
-getace (aclent_t &acl, int type, int id, DWORD win_ace_mask, DWORD win_ace_type)
-{
- acl.a_type = type;
- acl.a_id = id;
-
- if (win_ace_mask & FILE_READ_DATA)
- if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
- acl.a_perm |= (acl.a_perm & S_IRGRP) ? 0 : S_IRUSR;
- else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
- acl.a_perm &= ~S_IRGRP;
-
- if (win_ace_mask & FILE_WRITE_DATA)
- if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
- acl.a_perm |= (acl.a_perm & S_IWGRP) ? 0 : S_IWUSR;
- else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
- acl.a_perm &= ~S_IWGRP;
-
- if (win_ace_mask & FILE_EXECUTE)
- if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
- acl.a_perm |= (acl.a_perm & S_IXGRP) ? 0 : S_IXUSR;
- else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
- acl.a_perm &= ~S_IXGRP;
-}
-
-static int
-getacl (const char *file, DWORD attr, int nentries, aclent_t *aclbufp)
-{
- DWORD sd_size = 4096;
- char sd_buf[4096];
- PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
-
- int ret;
- if ((ret = read_sd (file, psd, &sd_size)) <= 0)
- {
- debug_printf ("read_sd %E");
- return ret;
- }
-
- PSID owner_sid;
- PSID group_sid;
- BOOL dummy;
- uid_t uid;
- gid_t gid;
-
- if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))
- {
- debug_printf ("GetSecurityDescriptorOwner %E");
- __seterrno ();
- return -1;
- }
- uid = get_uid_from_sid (owner_sid);
-
- if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))
- {
- debug_printf ("GetSecurityDescriptorGroup %E");
- __seterrno ();
- return -1;
- }
- gid = get_gid_from_sid (group_sid);
-
- aclent_t lacl[MAX_ACL_ENTRIES];
- memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t));
- lacl[0].a_type = USER_OBJ;
- lacl[0].a_id = uid;
- lacl[1].a_type = GROUP_OBJ;
- lacl[1].a_id = gid;
- lacl[2].a_type = OTHER_OBJ;
-
- PACL acl;
- BOOL acl_exists;
-
- if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy))
- {
- __seterrno ();
- debug_printf ("GetSecurityDescriptorDacl %E");
- return -1;
- }
-
- int pos, i;
-
- if (!acl_exists || !acl)
- {
- for (pos = 0; pos < MIN_ACL_ENTRIES; ++pos)
- lacl[pos].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
- pos = nentries < MIN_ACL_ENTRIES ? nentries : MIN_ACL_ENTRIES;
- memcpy (aclbufp, lacl, pos * sizeof (aclent_t));
- return pos;
- }
-
- for (i = 0; i < acl->AceCount && (!nentries || i < nentries); ++i)
- {
- ACCESS_ALLOWED_ACE *ace;
-
- if (!GetAce (acl, i, (PVOID *) &ace))
- continue;
-
- PSID ace_sid = (PSID) &ace->SidStart;
- int id;
- int type = 0;
-
- if (EqualSid (ace_sid, owner_sid))
- {
- type = USER_OBJ;
- id = uid;
- }
- else if (EqualSid (ace_sid, group_sid))
- {
- type = GROUP_OBJ;
- id = gid;
- }
- else if (EqualSid (ace_sid, get_world_sid ()))
- {
- type = OTHER_OBJ;
- id = 0;
- }
- else
- {
- id = get_id_from_sid (ace_sid, FALSE, &type);
- if (type != GROUP)
- {
- int type2 = 0;
- int id2 = get_id_from_sid (ace_sid, TRUE, &type2);
- if (type2 == GROUP)
- {
- id = id2;
- type = GROUP;
- }
- }
- }
- if (!type)
- continue;
- if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE))
- {
- if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- }
- if ((ace->Header.AceFlags & INHERIT_ALL)
- && (attr & FILE_ATTRIBUTE_DIRECTORY))
- {
- type |= ACL_DEFAULT;
- if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
- getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
- }
- }
- if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
- pos = MAX_ACL_ENTRIES;
- for (i = 0; i < pos; ++i)
- {
- lacl[i].a_perm = (lacl[i].a_perm & S_IRWXU)
- & ~((lacl[i].a_perm & S_IRWXG) << 3);
- lacl[i].a_perm |= (lacl[i].a_perm & S_IRWXU) >> 3
- | (lacl[i].a_perm & S_IRWXU) >> 6;
- }
- if ((searchace (lacl, MAX_ACL_ENTRIES, USER) >= 0
- || searchace (lacl, MAX_ACL_ENTRIES, GROUP) >= 0)
- && (pos = searchace (lacl, MAX_ACL_ENTRIES, CLASS_OBJ)) >= 0)
- {
- lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_perm =
- lacl[searchace (lacl, MAX_ACL_ENTRIES, GROUP_OBJ)].a_perm;
- }
- int dgpos;
- if ((searchace (lacl, MAX_ACL_ENTRIES, DEF_USER) >= 0
- || searchace (lacl, MAX_ACL_ENTRIES, DEF_GROUP) >= 0)
- && (dgpos = searchace (lacl, MAX_ACL_ENTRIES, DEF_GROUP_OBJ)) >= 0
- && (pos = searchace (lacl, MAX_ACL_ENTRIES, DEF_CLASS_OBJ)) >= 0
- && (attr & FILE_ATTRIBUTE_DIRECTORY))
- {
- lacl[pos].a_type = DEF_CLASS_OBJ;
- lacl[pos].a_perm = lacl[dgpos].a_perm;
- }
- if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
- pos = MAX_ACL_ENTRIES;
- if (pos > nentries)
- pos = nentries;
- if (aclbufp)
- memcpy (aclbufp, lacl, pos * sizeof (aclent_t));
- aclsort (pos, 0, aclbufp);
- syscall_printf ("%d = getacl (%s)", pos, file);
- return pos;
-}
-
-int
-acl_access (const char *path, int flags)
-{
- aclent_t acls[MAX_ACL_ENTRIES];
- int cnt;
-
- if ((cnt = acl (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)
- return -1;
-
- /* Only check existance. */
- if (!(flags & (R_OK|W_OK|X_OK)))
- return 0;
-
- for (int i = 0; i < cnt; ++i)
- {
- switch (acls[i].a_type)
- {
- case USER_OBJ:
- case USER:
- if (acls[i].a_id != myself->uid)
- {
- /*
- * Check if user is a NT group:
- * Take SID from passwd, search SID in group, check is_grp_member.
- */
- char owner_sidbuf[MAX_SID_LEN];
- PSID owner_sid = (PSID) owner_sidbuf;
- char group_sidbuf[MAX_SID_LEN];
- PSID group_sid = (PSID) group_sidbuf;
- struct passwd *pw;
- struct group *gr = NULL;
-
- if (group_sem > 0)
- continue;
- ++group_sem;
- if ((pw = getpwuid (acls[i].a_id)) != NULL
- && get_pw_sid (owner_sid, pw))
- {
- while ((gr = getgrent ()))
- if (get_gr_sid (group_sid, gr)
- && EqualSid (owner_sid, group_sid)
- && is_grp_member (myself->uid, gr->gr_gid))
- break;
- endgrent ();
- }
- --group_sem;
- if (!gr)
- continue;
- }
- break;
- case GROUP_OBJ:
- case GROUP:
- if (acls[i].a_id != myself->gid &&
- !is_grp_member (myself->uid, acls[i].a_id))
- continue;
- break;
- case OTHER_OBJ:
- break;
- default:
- continue;
- }
- if ((!(flags & R_OK) || (acls[i].a_perm & S_IREAD))
- && (!(flags & W_OK) || (acls[i].a_perm & S_IWRITE))
- && (!(flags & X_OK) || (acls[i].a_perm & S_IEXEC)))
- return 0;
- }
- set_errno (EACCES);
- return -1;
-}
-
-static
-int
-acl_worker (const char *path, int cmd, int nentries, aclent_t *aclbufp,
- int nofollow)
-{
- extern suffix_info stat_suffixes[];
- path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes);
- if (real_path.error)
- {
- set_errno (real_path.error);
- syscall_printf ("-1 = acl (%s)", path);
- return -1;
- }
- if (!real_path.has_acls ())
- {
- struct stat st;
- int ret = -1;
-
- switch (cmd)
- {
- case SETACL:
- set_errno (ENOSYS);
- break;
- case GETACL:
- if (nentries < 1)
- set_errno (EINVAL);
- else if ((nofollow && !lstat (path, &st))
- || (!nofollow && !stat (path, &st)))
- {
- aclent_t lacl[4];
- if (nentries > 0)
- {
- lacl[0].a_type = USER_OBJ;
- lacl[0].a_id = st.st_uid;
- lacl[0].a_perm = (st.st_mode & S_IRWXU)
- | (st.st_mode & S_IRWXU) >> 3
- | (st.st_mode & S_IRWXU) >> 6;
- }
- if (nentries > 1)
- {
- lacl[1].a_type = GROUP_OBJ;
- lacl[1].a_id = st.st_gid;
- lacl[1].a_perm = (st.st_mode & S_IRWXG)
- | (st.st_mode & S_IRWXG) << 3
- | (st.st_mode & S_IRWXG) >> 3;
- }
- if (nentries > 2)
- {
- lacl[2].a_type = OTHER_OBJ;
- lacl[2].a_id = 0;
- lacl[2].a_perm = (st.st_mode & S_IRWXO)
- | (st.st_mode & S_IRWXO) << 6
- | (st.st_mode & S_IRWXO) << 3;
- }
- if (nentries > 3)
- {
- lacl[3].a_type = CLASS_OBJ;
- lacl[3].a_id = 0;
- lacl[3].a_perm = (st.st_mode & S_IRWXG)
- | (st.st_mode & S_IRWXG) << 3
- | (st.st_mode & S_IRWXG) >> 3;
- }
- if (nentries > 4)
- nentries = 4;
- if (aclbufp)
- memcpy (aclbufp, lacl, nentries * sizeof (aclent_t));
- ret = nentries;
- }
- break;
- case GETACLCNT:
- ret = 4;
- break;
- }
- syscall_printf ("%d = acl (%s)", ret, path);
- return ret;
- }
- switch (cmd)
- {
- case SETACL:
- if (!aclsort(nentries, 0, aclbufp))
- return setacl (real_path.get_win32 (),
- nentries, aclbufp);
- break;
- case GETACL:
- if (nentries < 1)
- break;
- return getacl (real_path.get_win32 (),
- real_path.file_attributes (),
- nentries, aclbufp);
- case GETACLCNT:
- return getacl (real_path.get_win32 (),
- real_path.file_attributes (),
- 0, NULL);
- default:
- break;
- }
- set_errno (EINVAL);
- syscall_printf ("-1 = acl (%s)", path);
- return -1;
-}
-
-extern "C"
-int
-acl (const char *path, int cmd, int nentries, aclent_t *aclbufp)
-{
- return acl_worker (path, cmd, nentries, aclbufp, 0);
-}
-
-extern "C"
-int
-lacl (const char *path, int cmd, int nentries, aclent_t *aclbufp)
-{
- return acl_worker (path, cmd, nentries, aclbufp, 1);
-}
-
-extern "C"
-int
-facl (int fd, int cmd, int nentries, aclent_t *aclbufp)
-{
- if (cygheap->fdtab.not_open (fd))
- {
- syscall_printf ("-1 = facl (%d)", fd);
- set_errno (EBADF);
- return -1;
- }
- const char *path = cygheap->fdtab[fd]->get_name ();
- if (path == NULL)
- {
- syscall_printf ("-1 = facl (%d) (no name)", fd);
- set_errno (ENOSYS);
- return -1;
- }
- syscall_printf ("facl (%d): calling acl (%s)", fd, path);
- return acl_worker (path, cmd, nentries, aclbufp, 0);
-}
-
-extern "C"
-int
-aclcheck (aclent_t *aclbufp, int nentries, int *which)
-{
- BOOL has_user_obj = FALSE;
- BOOL has_group_obj = FALSE;
- BOOL has_other_obj = FALSE;
- BOOL has_class_obj = FALSE;
- BOOL has_ug_objs = FALSE;
- BOOL has_def_user_obj = FALSE;
- BOOL has_def_group_obj = FALSE;
- BOOL has_def_other_obj = FALSE;
- BOOL has_def_class_obj = FALSE;
- BOOL has_def_ug_objs = FALSE;
- int pos2;
-
- for (int pos = 0; pos < nentries; ++pos)
- switch (aclbufp[pos].a_type)
- {
- case USER_OBJ:
- if (has_user_obj)
- {
- if (which)
- *which = pos;
- return USER_ERROR;
- }
- has_user_obj = TRUE;
- break;
- case GROUP_OBJ:
- if (has_group_obj)
- {
- if (which)
- *which = pos;
- return GRP_ERROR;
- }
- has_group_obj = TRUE;
- break;
- case OTHER_OBJ:
- if (has_other_obj)
- {
- if (which)
- *which = pos;
- return OTHER_ERROR;
- }
- has_other_obj = TRUE;
- break;
- case CLASS_OBJ:
- if (has_class_obj)
- {
- if (which)
- *which = pos;
- return CLASS_ERROR;
- }
- has_class_obj = TRUE;
- break;
- case USER:
- case GROUP:
- if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
- aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
- {
- if (which)
- *which = pos2;
- return DUPLICATE_ERROR;
- }
- has_ug_objs = TRUE;
- break;
- case DEF_USER_OBJ:
- if (has_def_user_obj)
- {
- if (which)
- *which = pos;
- return USER_ERROR;
- }
- has_def_user_obj = TRUE;
- break;
- case DEF_GROUP_OBJ:
- if (has_def_group_obj)
- {
- if (which)
- *which = pos;
- return GRP_ERROR;
- }
- has_def_group_obj = TRUE;
- break;
- case DEF_OTHER_OBJ:
- if (has_def_other_obj)
- {
- if (which)
- *which = pos;
- return OTHER_ERROR;
- }
- has_def_other_obj = TRUE;
- break;
- case DEF_CLASS_OBJ:
- if (has_def_class_obj)
- {
- if (which)
- *which = pos;
- return CLASS_ERROR;
- }
- has_def_class_obj = TRUE;
- break;
- case DEF_USER:
- case DEF_GROUP:
- if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
- aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
- {
- if (which)
- *which = pos2;
- return DUPLICATE_ERROR;
- }
- has_def_ug_objs = TRUE;
- break;
- default:
- return ENTRY_ERROR;
- }
- if (!has_user_obj
- || !has_group_obj
- || !has_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)
- *which = -1;
- return MISS_ERROR;
- }
- return 0;
-}
-
-extern "C"
-int acecmp (const void *a1, const void *a2)
-{
-#define ace(i) ((const aclent_t *) a##i)
- int ret = ace(1)->a_type - ace(2)->a_type;
- if (!ret)
- ret = ace(1)->a_id - ace(2)->a_id;
- return ret;
-#undef ace
-}
-
-extern "C"
-int
-aclsort (int nentries, int, aclent_t *aclbufp)
-{
- if (aclcheck (aclbufp, nentries, NULL))
- return -1;
- if (!aclbufp || nentries < 1)
- {
- set_errno (EINVAL);
- return -1;
- }
- qsort((void *) aclbufp, nentries, sizeof (aclent_t), acecmp);
- return 0;
-}
-
-extern "C"
-int
-acltomode (aclent_t *aclbufp, int nentries, mode_t *modep)
-{
- int pos;
-
- if (!aclbufp || nentries < 1 || !modep)
- {
- set_errno (EINVAL);
- return -1;
- }
- *modep = 0;
- if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- *modep |= aclbufp[pos].a_perm & S_IRWXU;
- if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- if (searchace (aclbufp, nentries, CLASS_OBJ) < 0)
- pos = searchace (aclbufp, nentries, CLASS_OBJ);
- *modep |= (aclbufp[pos].a_perm & S_IRWXU) >> 3;
- if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- *modep |= (aclbufp[pos].a_perm & S_IRWXU) >> 6;
- return 0;
-}
-
-extern "C"
-int
-aclfrommode(aclent_t *aclbufp, int nentries, mode_t *modep)
-{
- int pos;
-
- if (!aclbufp || nentries < 1 || !modep)
- {
- set_errno (EINVAL);
- return -1;
- }
- if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- aclbufp[pos].a_perm = (*modep & S_IRWXU)
- | (*modep & S_IRWXU) >> 3
- | (*modep & S_IRWXU) >> 6;
- if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- if (searchace (aclbufp, nentries, CLASS_OBJ) < 0)
- pos = searchace (aclbufp, nentries, CLASS_OBJ);
- aclbufp[pos].a_perm = (*modep & S_IRWXG)
- | (*modep & S_IRWXG) << 3
- | (*modep & S_IRWXG) >> 3;
- if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0)
- {
- set_errno (EINVAL);
- return -1;
- }
- aclbufp[pos].a_perm = (*modep & S_IRWXO)
- | (*modep & S_IRWXO) << 6
- | (*modep & S_IRWXO) << 3;
- return 0;
-}
-
-extern "C"
-int
-acltopbits (aclent_t *aclbufp, int nentries, mode_t *pbitsp)
-{
- return acltomode (aclbufp, nentries, pbitsp);
-}
-
-extern "C"
-int
-aclfrompbits (aclent_t *aclbufp, int nentries, mode_t *pbitsp)
-{
- return aclfrommode (aclbufp, nentries, pbitsp);
-}
-
-static char *
-permtostr (mode_t perm)
-{
- static char pbuf[4];
-
- pbuf[0] = (perm & S_IREAD) ? 'r' : '-';
- pbuf[1] = (perm & S_IWRITE) ? 'w' : '-';
- pbuf[2] = (perm & S_IEXEC) ? 'x' : '-';
- pbuf[3] = '\0';
- return pbuf;
-}
-
-extern "C"
-char *
-acltotext (aclent_t *aclbufp, int aclcnt)
-{
- if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES
- || aclcheck (aclbufp, aclcnt, NULL))
- {
- set_errno (EINVAL);
- return NULL;
- }
- char buf[32000];
- buf[0] = '\0';
- BOOL first = TRUE;
-
- for (int pos = 0; pos < aclcnt; ++pos)
- {
- if (!first)
- strcat (buf, ",");
- first = FALSE;
- if (aclbufp[pos].a_type & ACL_DEFAULT)
- strcat (buf, "default");
- switch (aclbufp[pos].a_type)
- {
- case USER_OBJ:
- __small_sprintf (buf + strlen (buf), "user::%s",
- permtostr (aclbufp[pos].a_perm));
- break;
- case USER:
- __small_sprintf (buf + strlen (buf), "user:%d:%s",
- aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
- break;
- case GROUP_OBJ:
- __small_sprintf (buf + strlen (buf), "group::%s",
- permtostr (aclbufp[pos].a_perm));
- break;
- case GROUP:
- __small_sprintf (buf + strlen (buf), "group:%d:%s",
- aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
- break;
- case CLASS_OBJ:
- __small_sprintf (buf + strlen (buf), "mask::%s",
- permtostr (aclbufp[pos].a_perm));
- break;
- case OTHER_OBJ:
- __small_sprintf (buf + strlen (buf), "other::%s",
- permtostr (aclbufp[pos].a_perm));
- break;
- default:
- set_errno (EINVAL);
- return NULL;
- }
- }
- return strdup (buf);
-}
-
-static mode_t
-permfromstr (char *perm)
-{
- mode_t mode = 0;
-
- if (strlen (perm) != 3)
- return 01000;
- if (perm[0] == 'r')
- mode |= S_IRUSR | S_IRGRP | S_IROTH;
- else if (perm[0] != '-')
- return 01000;
- if (perm[1] == 'w')
- mode |= S_IWUSR | S_IWGRP | S_IWOTH;
- else if (perm[1] != '-')
- return 01000;
- if (perm[2] == 'x')
- mode |= S_IXUSR | S_IXGRP | S_IXOTH;
- else if (perm[2] != '-')
- return 01000;
- return mode;
-}
-
-extern "C"
-aclent_t *
-aclfromtext (char *acltextp, int *)
-{
- if (!acltextp)
- {
- set_errno (EINVAL);
- return NULL;
- }
- char buf[strlen (acltextp) + 1];
- aclent_t lacl[MAX_ACL_ENTRIES];
- memset (lacl, 0, sizeof lacl);
- int pos = 0;
- strcpy (buf, acltextp);
- char *lasts;
- for (char *c = strtok_r (buf, ",", &lasts);
- c;
- c = strtok_r (NULL, ",", &lasts))
- {
- if (!strncmp (c, "default", 7))
- {
- lacl[pos].a_type |= ACL_DEFAULT;
- c += 7;
- }
- if (!strncmp (c, "user:", 5))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= USER_OBJ;
- else
- {
- lacl[pos].a_type |= USER;
- c += 5;
- if (isalpha (*c))
- {
- struct passwd *pw = getpwnam (c);
- if (!pw)
- {
- set_errno (EINVAL);
- return NULL;
- }
- lacl[pos].a_id = pw->pw_uid;
- c = strchr (c, ':');
- }
- else if (isdigit (*c))
- lacl[pos].a_id = strtol (c, &c, 10);
- if (!c || *c != ':')
- {
- set_errno (EINVAL);
- return NULL;
- }
- }
- }
- else if (!strncmp (c, "group:", 6))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= GROUP_OBJ;
- else
- {
- lacl[pos].a_type |= GROUP;
- c += 5;
- if (isalpha (*c))
- {
- struct group *gr = getgrnam (c);
- if (!gr)
- {
- set_errno (EINVAL);
- return NULL;
- }
- lacl[pos].a_id = gr->gr_gid;
- c = strchr (c, ':');
- }
- else if (isdigit (*c))
- lacl[pos].a_id = strtol (c, &c, 10);
- if (!c || *c != ':')
- {
- set_errno (EINVAL);
- return NULL;
- }
- }
- }
- else if (!strncmp (c, "mask:", 5))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= CLASS_OBJ;
- else
- {
- set_errno (EINVAL);
- return NULL;
- }
- }
- else if (!strncmp (c, "other:", 6))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= OTHER_OBJ;
- else
- {
- set_errno (EINVAL);
- return NULL;
- }
- }
- if ((lacl[pos].a_perm = permfromstr (c)) == 01000)
- {
- set_errno (EINVAL);
- return NULL;
- }
- ++pos;
- }
- aclent_t *aclp = (aclent_t *) malloc (pos * sizeof (aclent_t));
- if (aclp)
- memcpy (aclp, lacl, pos * sizeof (aclent_t));
- return aclp;
-}
-
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index bd1b3d8..b83e310 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -1,6 +1,6 @@
/* security.h: security declarations
- Copyright 2000 Red Hat, Inc.
+ Copyright 2000, 2001 Red Hat, Inc.
This file is part of Cygwin.
@@ -8,30 +8,51 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+#define DONT_INHERIT (0)
+#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
+#define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
+
+extern BOOL allow_ntsec;
+extern BOOL allow_smbntsec;
+
/* File manipulation */
int __stdcall set_process_privileges ();
int __stdcall get_file_attribute (int, const char *, int *,
uid_t * = NULL, gid_t * = NULL);
int __stdcall set_file_attribute (int, const char *, int);
int __stdcall set_file_attribute (int, const char *, uid_t, gid_t, int, const char *);
-extern BOOL allow_ntsec;
-extern BOOL allow_smbntsec;
-
+LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size);
+LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size);
+BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+
+
+/* sec_helper.cc: Security helper functions. */
+char *__stdcall convert_sid_to_string_sid (PSID psid, char *sid_str);
+PSID __stdcall convert_string_sid_to_sid (PSID psid, const char *sid_str);
+PSID __stdcall get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r);
+BOOL __stdcall get_pw_sid (PSID sid, struct passwd *pw);
+BOOL __stdcall get_gr_sid (PSID sid, struct group *gr);
+PSID __stdcall get_admin_sid ();
+PSID __stdcall get_system_sid ();
+PSID __stdcall get_creator_owner_sid ();
+PSID __stdcall get_world_sid ();
+int get_id_from_sid (PSID psid, BOOL search_grp, int *type);
+int __stdcall get_id_from_sid (PSID psid, BOOL search_grp);
+BOOL __stdcall legal_sid_type (SID_NAME_USE type);
+BOOL __stdcall is_grp_member (uid_t uid, gid_t gid);
/* `lookup_name' should be called instead of LookupAccountName.
* logsrv may be NULL, in this case only the local system is used for lookup.
* The buffer for ret_sid (40 Bytes) has to be allocated by the caller! */
BOOL __stdcall lookup_name (const char *, const char *, PSID);
-char *__stdcall convert_sid_to_string_sid (PSID, char *);
-PSID __stdcall convert_string_sid_to_sid (PSID, const char *);
-BOOL __stdcall get_pw_sid (PSID, struct passwd *);
-/* Retrieve a security descriptor that allows all access */
-SECURITY_DESCRIPTOR *__stdcall get_null_sd (void);
-
-int __stdcall get_id_from_sid (PSID, BOOL);
extern inline int get_uid_from_sid (PSID psid) { return get_id_from_sid (psid, FALSE);}
extern inline int get_gid_from_sid (PSID psid) { return get_id_from_sid (psid, TRUE); }
+/* shared.cc: */
+/* Retrieve a security descriptor that allows all access */
+SECURITY_DESCRIPTOR *__stdcall get_null_sd (void);
+
/* Various types of security attributes for use in Create* functions. */
extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih;
extern SECURITY_ATTRIBUTES *__stdcall sec_user (PVOID sa_buf, PSID sid2 = NULL, BOOL inherit = TRUE);