Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r--winsup/cygwin/security.cc1417
1 files changed, 6 insertions, 1411 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index d780103f8..38c741fa2 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;
-}
-