summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/sec_acl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sec_acl.cc')
-rw-r--r--winsup/cygwin/sec_acl.cc768
1 files changed, 506 insertions, 262 deletions
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index de40717dc..052856ffd 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -13,7 +13,6 @@ details. */
#include "winsup.h"
#include <stdlib.h>
-#include <sys/acl.h>
#include <ctype.h>
#include "cygerrno.h"
#include "security.h"
@@ -23,6 +22,7 @@ details. */
#include "cygheap.h"
#include "ntdll.h"
#include "tls_pbuf.h"
+#include "sec_posixacl.h"
/* How does a correctly constructed new-style Windows ACL claiming to be a
POSIX ACL look like?
@@ -118,7 +118,8 @@ searchace (aclent_t *aclp, int nentries, int type, uid_t id)
int i;
for (i = 0; i < nentries; ++i)
- if ((aclp[i].a_type == type && (id == ILLEGAL_UID || aclp[i].a_id == id))
+ if ((aclp[i].a_type == type
+ && (id == ACL_UNDEFINED_ID || aclp[i].a_id == id))
|| !aclp[i].a_type)
return i;
return -1;
@@ -186,25 +187,25 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
{
aclbufp = (aclent_t *) tp.c_get ();
aclbufp[0].a_type = USER_OBJ;
- aclbufp[0].a_id = ILLEGAL_UID;
+ aclbufp[0].a_id = ACL_UNDEFINED_ID;
aclbufp[0].a_perm = (attr >> 6) & S_IRWXO;
aclbufp[1].a_type = GROUP_OBJ;
- aclbufp[1].a_id = ILLEGAL_GID;
+ aclbufp[1].a_id = ACL_UNDEFINED_ID;
aclbufp[1].a_perm = (attr >> 3) & S_IRWXO;
aclbufp[2].a_type = OTHER_OBJ;
- aclbufp[2].a_id = ILLEGAL_GID;
+ aclbufp[2].a_id = ACL_UNDEFINED_ID;
aclbufp[2].a_perm = attr & S_IRWXO;
nentries = MIN_ACL_ENTRIES;
if (S_ISDIR (attr))
{
aclbufp[3].a_type = DEF_USER_OBJ;
- aclbufp[3].a_id = ILLEGAL_UID;
+ aclbufp[3].a_id = ACL_UNDEFINED_ID;
aclbufp[3].a_perm = (attr >> 6) & S_IRWXO;
aclbufp[4].a_type = GROUP_OBJ;
- aclbufp[4].a_id = ILLEGAL_GID;
+ aclbufp[4].a_id = ACL_UNDEFINED_ID;
aclbufp[4].a_perm = (attr >> 3) & S_IRWXO;
aclbufp[5].a_type = OTHER_OBJ;
- aclbufp[5].a_id = ILLEGAL_GID;
+ aclbufp[5].a_id = ACL_UNDEFINED_ID;
aclbufp[5].a_perm = attr & S_IRWXO;
nentries += MIN_ACL_ENTRIES;
}
@@ -618,19 +619,19 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
if (attr_ret)
*attr_ret &= S_IFMT;
if (uid_ret)
- *uid_ret = ILLEGAL_UID;
+ *uid_ret = ACL_UNDEFINED_ID;
if (gid_ret)
- *gid_ret = ILLEGAL_GID;
+ *gid_ret = ACL_UNDEFINED_ID;
if (aclbufp)
{
aclbufp[0].a_type = USER_OBJ;
- aclbufp[0].a_id = ILLEGAL_UID;
+ aclbufp[0].a_id = ACL_UNDEFINED_ID;
aclbufp[0].a_perm = 0;
aclbufp[1].a_type = GROUP_OBJ;
- aclbufp[1].a_id = ILLEGAL_GID;
+ aclbufp[1].a_id = ACL_UNDEFINED_ID;
aclbufp[1].a_perm = 0;
aclbufp[2].a_type = OTHER_OBJ;
- aclbufp[2].a_id = ILLEGAL_GID;
+ aclbufp[2].a_id = ACL_UNDEFINED_ID;
aclbufp[2].a_perm = 0;
return MIN_ACL_ENTRIES;
}
@@ -674,7 +675,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
lacl[1].a_type = GROUP_OBJ;
lacl[1].a_id = gid;
lacl[2].a_type = OTHER_OBJ;
- lacl[2].a_id = ILLEGAL_GID;
+ lacl[2].a_id = ACL_UNDEFINED_ID;
/* Create array to collect SIDs of all entries in lacl. */
aclsid = (cygpsid *) tp.w_get ();
aclsid[0] = owner_sid;
@@ -730,7 +731,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
>= 0)
{
lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
lacl[pos].a_perm = CYG_ACE_MASK_TO_POSIX (ace->Mask);
aclsid[pos] = well_known_null_sid;
}
@@ -743,7 +744,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
DEF_CLASS_OBJ)) >= 0)
{
lacl[pos].a_type = DEF_CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
lacl[pos].a_perm = CYG_ACE_MASK_TO_POSIX (ace->Mask);
aclsid[pos] = well_known_null_sid;
}
@@ -767,7 +768,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
else if (ace_sid == well_known_world_sid)
{
type = OTHER_OBJ;
- id = ILLEGAL_GID;
+ id = ACL_UNDEFINED_ID;
if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE
&& !(ace->Header.AceFlags & INHERIT_ONLY))
saw_other_obj = true;
@@ -776,14 +777,14 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
{
type = DEF_USER_OBJ;
types_def |= type;
- id = ILLEGAL_GID;
+ id = ACL_UNDEFINED_ID;
saw_def_user_obj = true;
}
else if (ace_sid == well_known_creator_group_sid)
{
type = DEF_GROUP_OBJ;
types_def |= type;
- id = ILLEGAL_GID;
+ id = ACL_UNDEFINED_ID;
saw_def_group_obj = true;
}
else
@@ -888,10 +889,10 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
{
if (owner_eq_group && !saw_def_group_obj && attr & S_ISGID)
{
- /* This needs post-processing in the following GROUP_OBJ
- handling... Set id to ILLEGAL_GID to play it safe. */
+ /* Needs post-processing in the following GROUP_OBJ block.
+ Set id to ACL_UNDEFINED_ID to play it safe. */
type = GROUP_OBJ;
- id = ILLEGAL_GID;
+ id = ACL_UNDEFINED_ID;
}
else
type = USER;
@@ -944,7 +945,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
&& (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
{
lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
class_perm |= lacl[1].a_perm;
lacl[pos].a_perm = class_perm;
aclsid[pos] = well_known_null_sid;
@@ -960,7 +961,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
&& (pos = searchace (lacl, MAX_ACL_ENTRIES, CLASS_OBJ)) >= 0)
{
lacl[pos].a_type = CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
lacl[pos].a_perm = lacl[1].a_perm; /* == group perms */
aclsid[pos] = well_known_null_sid;
}
@@ -1004,7 +1005,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES)
{
lacl[pos].a_type = DEF_OTHER_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
lacl[pos].a_perm = lacl[2].a_perm;
aclsid[pos] = well_known_world_sid;
pos++;
@@ -1019,7 +1020,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
&& (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
{
lacl[pos].a_type = DEF_CLASS_OBJ;
- lacl[pos].a_id = ILLEGAL_GID;
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
lacl[pos].a_perm = def_class_perm;
if (def_pgrp_pos >= 0)
lacl[pos].a_perm |= lacl[def_pgrp_pos].a_perm;
@@ -1175,130 +1176,151 @@ facl32 (int fd, int cmd, int nentries, aclent_t *aclbufp)
return res;
}
-extern "C" int
-aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
+int
+__aclcheck (aclent_t *aclbufp, int nentries, int *which, bool posix)
{
bool has_user_obj = false;
bool has_group_obj = false;
bool has_other_obj = false;
bool has_class_obj = false;
- bool has_ug_objs __attribute__ ((unused)) = false;
- bool has_def_objs __attribute__ ((unused)) = false;
- bool has_def_user_obj __attribute__ ((unused)) = false;
+ bool has_ug_objs = false;
+ bool has_def_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 __attribute__ ((unused)) = 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_objs = has_def_user_obj = true;
- break;
- case DEF_GROUP_OBJ:
- if (has_def_group_obj)
- {
- if (which)
- *which = pos;
- return GRP_ERROR;
- }
- has_def_objs = has_def_group_obj = true;
- break;
- case DEF_OTHER_OBJ:
- if (has_def_other_obj)
- {
- if (which)
- *which = pos;
- return OTHER_ERROR;
- }
- has_def_objs = has_def_other_obj = true;
- break;
- case DEF_CLASS_OBJ:
- if (has_def_class_obj)
- {
- if (which)
- *which = pos;
- return CLASS_ERROR;
- }
- has_def_objs = 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_objs = has_def_ug_objs = true;
- break;
- default:
- return ENTRY_ERROR;
- }
+ {
+ /* POSIX ACLs may contain deleted entries. Just ignore them. */
+ if (posix && aclbufp[pos].a_type == ACL_DELETED_TAG)
+ continue;
+ /* POSIX defines two sorts of ACLs, access and default, none of which
+ is supposed to have the ACL_DEFAULT flag set. */
+ if (posix && (aclbufp[pos].a_type & ACL_DEFAULT))
+ {
+ if (which)
+ *which = pos;
+ return ENTRY_ERROR;
+ }
+ 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_objs = has_def_user_obj = true;
+ break;
+ case DEF_GROUP_OBJ:
+ if (has_def_group_obj)
+ {
+ if (which)
+ *which = pos;
+ return GRP_ERROR;
+ }
+ has_def_objs = has_def_group_obj = true;
+ break;
+ case DEF_OTHER_OBJ:
+ if (has_def_other_obj)
+ {
+ if (which)
+ *which = pos;
+ return OTHER_ERROR;
+ }
+ has_def_objs = has_def_other_obj = true;
+ break;
+ case DEF_CLASS_OBJ:
+ if (has_def_class_obj)
+ {
+ if (which)
+ *which = pos;
+ return CLASS_ERROR;
+ }
+ has_def_objs = 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_objs = has_def_ug_objs = true;
+ break;
+ default:
+ if (which)
+ *which = pos;
+ return ENTRY_ERROR;
+ }
+ }
if (!has_user_obj
|| !has_group_obj
|| !has_other_obj
- || (has_def_objs
- && (!has_def_user_obj || !has_def_group_obj || !has_def_other_obj))
- || (has_ug_objs && !has_class_obj)
- || (has_def_ug_objs && !has_def_class_obj)
- )
+ || (has_ug_objs && !has_class_obj))
+ {
+ if (which)
+ *which = -1;
+ return MISS_ERROR;
+ }
+ /* Check for missing default entries only on Solaris ACLs. */
+ if (!posix &&
+ ((has_def_objs
+ && !(has_def_user_obj && has_def_group_obj && has_def_other_obj))
+ || (has_def_ug_objs && !has_def_class_obj)))
{
if (which)
*which = -1;
@@ -1307,22 +1329,44 @@ aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
return 0;
}
-void
+extern "C" int
+aclcheck32 (aclent_t *aclbufp, int nentries, int *which)
+{
+ return __aclcheck (aclbufp, nentries, which, false);
+}
+
+/* For the sake of acl_calc_mask, return -1 if the ACL doesn't need a mask
+ or if a mask entry already exists (__aclcalcmask sets the mask by itself).
+ Otherwise return the mask value so acl_calc_mask can create a mask entry.
+ This doesn't matter when called from aclsort. */
+mode_t
__aclcalcmask (aclent_t *aclbufp, int nentries)
{
mode_t mask = 0;
+ bool need_mask = false;
int mask_idx = -1;
for (int idx = 0; idx < nentries; ++idx)
- {
- if (aclbufp[idx].a_type == CLASS_OBJ)
- mask_idx = idx;
- else if (aclbufp[idx].a_type
- & (USER | GROUP_OBJ | GROUP))
+ switch (aclbufp[idx].a_type)
+ {
+ case USER:
+ case GROUP:
+ need_mask = true;
+ /*FALLTHRU*/
+ case GROUP_OBJ:
mask |= aclbufp[idx].a_perm;
- }
+ break;
+ case CLASS_OBJ:
+ mask_idx = idx;
+ break;
+ default:
+ break;
+ }
if (mask_idx != -1)
aclbufp[mask_idx].a_perm = mask;
+ if (need_mask && mask_idx == -1)
+ return mask;
+ return (acl_perm_t) -1;
}
static int
@@ -1336,15 +1380,25 @@ acecmp (const void *a1, const void *a2)
#undef ace
}
-extern "C" int
-aclsort32 (int nentries, int calclass, aclent_t *aclbufp)
+/* Sorts any acl. Called from sec_posixacl.cc. */
+int
+__aclsort (int nentries, aclent_t *aclbufp)
{
- if (aclcheck32 (aclbufp, nentries, NULL))
+ if (!aclbufp || nentries < 0)
{
set_errno (EINVAL);
return -1;
}
- if (!aclbufp || nentries < 1)
+ if (nentries > 0)
+ qsort ((void *) aclbufp, nentries, sizeof (aclent_t), acecmp);
+ return 0;
+}
+
+extern "C" int
+aclsort32 (int nentries, int calclass, aclent_t *aclbufp)
+{
+ if (!aclbufp || nentries < MIN_ACL_ENTRIES
+ || aclcheck32 (aclbufp, nentries, NULL))
{
set_errno (EINVAL);
return -1;
@@ -1444,79 +1498,224 @@ aclfrompbits32 (aclent_t *aclbufp, int nentries, mode_t *pbitsp)
}
static char *
-permtostr (mode_t perm)
+permtostr (char *bufp, mode_t perm)
{
- static char pbuf[4];
-
- pbuf[0] = (perm & S_IROTH) ? 'r' : '-';
- pbuf[1] = (perm & S_IWOTH) ? 'w' : '-';
- pbuf[2] = (perm & S_IXOTH) ? 'x' : '-';
- pbuf[3] = '\0';
- return pbuf;
+ *bufp++ = (perm & S_IROTH) ? 'r' : '-';
+ *bufp++ = (perm & S_IWOTH) ? 'w' : '-';
+ *bufp++ = (perm & S_IXOTH) ? 'x' : '-';
+ return bufp;
}
-extern "C" char *
-acltotext32 (aclent_t *aclbufp, int aclcnt)
+#define _OPT(o) (options & (o))
+
+#define _CHK(l) \
+ if (bufp + (l) >= buf + 2 * NT_MAX_PATH - 1) \
+ { \
+ set_errno (ENOMEM); \
+ return NULL; \
+ }
+#define _CPY(s) ({ \
+ const char *_s = (s); \
+ _CHK (strlen (_s)); \
+ bufp = stpcpy (bufp, _s); \
+ })
+#define _PTS(p) { \
+ _CHK (3); \
+ bufp = permtostr (bufp, p); \
+ }
+
+#define _CMP(s) (!strncmp (bufp, acl_part[s].str, acl_part[s].len))
+
+struct _acl_part
+{
+ const char *str;
+ size_t len;
+};
+
+static _acl_part acl_part_l[] =
+{
+ { "default:", 8 },
+ { "user:", 5 },
+ { "group:", 6 },
+ { "mask:", 5 },
+ { "other:", 6 }
+};
+
+static _acl_part acl_part_s[] =
+{
+ { "d:", 2 },
+ { "u:", 2 },
+ { "g:", 2 },
+ { "m:", 2 },
+ { "o:", 2 }
+};
+
+enum _acl_type {
+ default_s,
+ user_s,
+ group_s,
+ mask_s,
+ other_s,
+ none_s
+};
+
+char *
+__acltotext (aclent_t *aclbufp, int aclcnt, const char *prefix, char separator,
+ int options)
{
if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES
- || aclcheck32 (aclbufp, aclcnt, NULL))
+ || aclsort32 (aclcnt, 0, aclbufp))
{
set_errno (EINVAL);
return NULL;
}
+ cyg_ldap cldap;
tmp_pathbuf tp;
- char *buf = tp.c_get ();
- buf[0] = '\0';
+ char *buf = tp.t_get ();
+ char *bufp = buf;
+ char *entry_start;
bool first = true;
+ struct passwd *pw;
+ struct group *gr;
+ mode_t mask = S_IRWXO;
+ mode_t def_mask = S_IRWXO;
+ mode_t effective;
+ int pos;
+ _acl_part *acl_part = _OPT (TEXT_ABBREVIATE) ? acl_part_s : acl_part_l;
- for (int pos = 0; pos < aclcnt; ++pos)
+ *bufp = '\0';
+ /* If effective rights are requested, fetch mask values. */
+ if (_OPT (TEXT_SOME_EFFECTIVE | TEXT_ALL_EFFECTIVE))
+ {
+ if ((pos = searchace (aclbufp, aclcnt, CLASS_OBJ)) >= 0)
+ mask = aclbufp[pos].a_perm;
+ if ((pos = searchace (aclbufp, aclcnt, DEF_CLASS_OBJ)) >= 0)
+ def_mask = aclbufp[pos].a_perm;
+ }
+ for (pos = 0; pos < aclcnt; ++pos)
{
if (!first)
- strcat (buf, ",");
+ {
+ _CHK (1);
+ *bufp++ = separator;
+ }
first = false;
- if (aclbufp[pos].a_type & ACL_DEFAULT)
- strcat (buf, "default");
+ /* Rememeber start position of entry to compute TEXT_SMART_INDENT tabs. */
+ entry_start = bufp;
+ /* prefix */
+ if (prefix)
+ _CPY (prefix);
+ /* Solaris default acl? */
+ if (!_OPT (TEXT_IS_POSIX) && aclbufp[pos].a_type & ACL_DEFAULT)
+ _CPY (acl_part[default_s].str);
+ /* acl type */
switch (aclbufp[pos].a_type & ~ACL_DEFAULT)
{
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));
+ _CPY (acl_part[user_s].str);
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));
+ _CPY (acl_part[group_s].str);
break;
case CLASS_OBJ:
- __small_sprintf (buf + strlen (buf), "mask::%s",
- permtostr (aclbufp[pos].a_perm));
+ _CPY (acl_part[mask_s].str);
break;
case OTHER_OBJ:
- __small_sprintf (buf + strlen (buf), "other::%s",
- permtostr (aclbufp[pos].a_perm));
+ _CPY (acl_part[other_s].str);
+ break;
+ }
+ /* id, if any */
+ switch (aclbufp[pos].a_type & ~ACL_DEFAULT)
+ {
+ case USER:
+ if (_OPT (TEXT_NUMERIC_IDS)
+ || !(pw = internal_getpwuid (aclbufp[pos].a_id, &cldap)))
+ {
+ _CHK (11);
+ bufp += __small_sprintf (bufp, "%u:", aclbufp[pos].a_id);
+ }
+ else
+ {
+ _CHK (strlen (pw->pw_name + 1));
+ bufp += __small_sprintf (bufp, "%s:", pw->pw_name);
+ }
+ break;
+ case GROUP:
+ if (_OPT (TEXT_NUMERIC_IDS)
+ || !(gr = internal_getgrgid (aclbufp[pos].a_id, &cldap)))
+ {
+ _CHK (11);
+ bufp += __small_sprintf (bufp, "%u:", aclbufp[pos].a_id);
+ }
+ else
+ {
+ _CHK (strlen (gr->gr_name));
+ bufp += __small_sprintf (bufp, "%s:", gr->gr_name);
+ }
break;
default:
- set_errno (EINVAL);
- return NULL;
+ _CPY (":");
+ break;
}
+ /* real permissions */
+ _PTS (aclbufp[pos].a_perm);
+ if (!_OPT (TEXT_SOME_EFFECTIVE | TEXT_ALL_EFFECTIVE))
+ continue;
+ /* effective permissions */
+ switch (aclbufp[pos].a_type)
+ {
+ case USER:
+ case GROUP_OBJ:
+ case GROUP:
+ effective = aclbufp[pos].a_perm & mask;
+ break;
+ case DEF_USER:
+ case DEF_GROUP_OBJ:
+ case DEF_GROUP:
+ effective = aclbufp[pos].a_perm & def_mask;
+ break;
+ default:
+ continue;
+ }
+ if (_OPT (TEXT_ALL_EFFECTIVE) || effective != aclbufp[pos].a_perm)
+ {
+ if (_OPT (TEXT_SMART_INDENT))
+ {
+ int tabs = 3 - (bufp - entry_start) / 8;
+ if (tabs-- > 0)
+ {
+ _CHK (tabs);
+ while (tabs-- > 0)
+ *bufp++ = '\t';
+ }
+ }
+ _CPY ("\t#effective:");
+ _PTS (effective);
+ }
+ }
+ if (_OPT (TEXT_END_SEPARATOR))
+ {
+ _CHK (1);
+ *bufp++ = separator;
+ *bufp++ = '\0';
}
return strdup (buf);
}
+extern "C" char *
+acltotext32 (aclent_t *aclbufp, int aclcnt)
+{
+ return __acltotext (aclbufp, aclcnt, NULL, ',', 0);
+}
+
static mode_t
-permfromstr (char *perm)
+permfromstr (char *perm, bool posix_long)
{
mode_t mode = 0;
+ int idx;
- if (strlen (perm) != 3)
- return 01000;
if (perm[0] == 'r')
mode |= S_IROTH;
else if (perm[0] != '-')
@@ -1529,125 +1728,170 @@ permfromstr (char *perm)
mode |= S_IXOTH;
else if (perm[2] != '-')
return 01000;
- return mode;
+ idx = 3;
+ /* In posix long mode, only tabs up to a hash sign allowed. */
+ if (posix_long)
+ while (perm[idx] == '\t')
+ ++idx;
+ if (perm[idx] == '\0' || (posix_long && perm[idx] == '#'))
+ return mode;
+ return 01000;
}
-extern "C" aclent_t *
-aclfromtext32 (const char *acltextp, int *aclcnt)
+void *
+__aclfromtext (const char *acltextp, int *aclcnt, bool posix)
{
- if (!acltextp || strlen (acltextp) > NT_MAX_PATH)
+ if (!acltextp || strlen (acltextp) >= 2 * NT_MAX_PATH)
{
set_errno (EINVAL);
return NULL;
}
+ cyg_ldap cldap;
tmp_pathbuf tp;
- aclent_t lacl[MAX_ACL_ENTRIES];
- memset (lacl, 0, sizeof lacl);
+ const char *delim;
+ _acl_part *acl_part;
+ char *bufp, *lasts, *qualifier;
int pos = 0;
+ int acl_type;
+
+ aclent_t *lacl = (aclent_t *) tp.c_get ();
+ memset (lacl, 0, MAX_ACL_ENTRIES * sizeof (aclent_t *));
char *buf = tp.t_get ();
stpcpy (buf, acltextp);
- char *lasts;
- cyg_ldap cldap;
- for (char *c = strtok_r (buf, ",", &lasts);
- c;
- c = strtok_r (NULL, ",", &lasts))
+
+ if (posix)
+ {
+ /* Posix long or short form. Any \n in the string means long form. */
+ if (strchr (buf, '\n'))
+ {
+ delim = "\n";
+ acl_part = acl_part_l;
+ }
+ else
+ {
+ delim = ",";
+ acl_part = acl_part_s;
+ }
+ }
+ else
{
- if (!strncmp (c, "default", 7))
+ /* Solaris aclfromtext format. */
+ delim = ",";
+ acl_part = acl_part_l;
+ }
+
+ for (bufp = strtok_r (buf, delim, &lasts);
+ bufp;
+ bufp = strtok_r (NULL, delim, &lasts))
+ {
+ /* Handle default acl entries only for Solaris ACLs. */
+ if (!posix && _CMP (default_s))
{
lacl[pos].a_type |= ACL_DEFAULT;
- c += 7;
+ bufp += acl_part[default_s].len;
}
- if (!strncmp (c, "user:", 5))
+ lacl[pos].a_id = ACL_UNDEFINED_ID;
+ for (acl_type = user_s; acl_type < none_s; ++acl_type)
+ if (_CMP (acl_type))
+ break;
+ if (acl_type == none_s)
{
- if (c[5] == ':')
- lacl[pos].a_type |= USER_OBJ;
- else
- {
- lacl[pos].a_type |= USER;
- c += 5;
- if (isalpha (*c))
- {
- struct passwd *pw = internal_getpwnam (c, &cldap);
- if (!pw)
- {
- set_errno (EINVAL);
- return NULL;
- }
- lacl[pos].a_id = pw->pw_uid;
- c = strchrnul (c, ':');
- }
- else if (isdigit (*c))
- lacl[pos].a_id = strtol (c, &c, 10);
- if (*c != ':')
- {
- set_errno (EINVAL);
- return NULL;
- }
- }
+ set_errno (EINVAL);
+ return NULL;
}
- else if (!strncmp (c, "group:", 6))
+ bufp += acl_part[acl_type].len;
+ switch (acl_type)
{
- if (c[5] == ':')
- lacl[pos].a_type |= GROUP_OBJ;
- else
+ case user_s:
+ case group_s:
+ qualifier = bufp;
+ bufp = strchrnul (bufp, ':');
+ *bufp++ = '\0';
+ /* No qualifier? USER_OBJ or GROUP_OBJ */
+ if (!*qualifier)
{
- lacl[pos].a_type |= GROUP;
- c += 5;
- if (isalpha (*c))
- {
- struct group *gr = internal_getgrnam (c, &cldap);
- if (!gr)
- {
- set_errno (EINVAL);
- return NULL;
- }
- lacl[pos].a_id = gr->gr_gid;
- c = strchrnul (c, ':');
- }
- else if (isdigit (*c))
- lacl[pos].a_id = strtol (c, &c, 10);
- if (*c != ':')
+ lacl[pos].a_type |= (acl_type == user_s) ? USER_OBJ : GROUP_OBJ;
+ break;
+ }
+ /* Some qualifier, USER or GROUP */
+ lacl[pos].a_type |= (acl_type == user_s) ? USER : GROUP;
+ if (isdigit (*qualifier))
+ {
+ char *ep;
+
+ id_t id = strtol (qualifier, &ep, 10);
+ if (*ep == '\0')
{
- set_errno (EINVAL);
- return NULL;
+ lacl[pos].a_id = id;
+ break;
}
}
- }
- else if (!strncmp (c, "mask:", 5))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= CLASS_OBJ;
+ if (acl_type == user_s)
+ {
+ struct passwd *pw = internal_getpwnam (qualifier, &cldap);
+ if (pw)
+ lacl[pos].a_id = pw->pw_uid;
+ }
else
{
+ struct group *gr = internal_getgrnam (qualifier, &cldap);
+ if (gr)
+ lacl[pos].a_id = gr->gr_gid;
+ }
+ if (lacl[pos].a_id == ACL_UNDEFINED_ID)
+ {
set_errno (EINVAL);
return NULL;
}
- }
- else if (!strncmp (c, "other:", 6))
- {
- if (c[5] == ':')
- lacl[pos].a_type |= OTHER_OBJ;
- else
+ break;
+ case mask_s:
+ case other_s:
+ if (*bufp++ != ':')
{
set_errno (EINVAL);
return NULL;
}
+ lacl[pos].a_type |= (acl_type == mask_s) ? CLASS_OBJ : OTHER_OBJ;
+ break;
}
- if ((lacl[pos].a_perm = permfromstr (c)) == 01000)
+ /* In posix long mode, the next char after the permissions may be a tab
+ followed by effective permissions we can ignore here. */
+ if ((lacl[pos].a_perm = permfromstr (bufp, *delim == '\n')) == 01000)
{
set_errno (EINVAL);
return NULL;
}
++pos;
}
- aclent_t *aclp = (aclent_t *) malloc (pos * sizeof (aclent_t));
- if (aclp)
+ if (posix)
{
- memcpy (aclp, lacl, pos * sizeof (aclent_t));
- if (aclcnt)
- *aclcnt = pos;
+ acl_t acl = (acl_t) acl_init (pos);
+ if (acl)
+ {
+ memcpy (acl->entry, lacl, pos * sizeof (aclent_t));
+ acl->count = pos;
+ if (aclcnt)
+ *aclcnt = pos;
+ }
+ return (void *) acl;
}
- return aclp;
+ else
+ {
+ aclent_t *aclp = (aclent_t *) malloc (pos * sizeof (aclent_t));
+ if (aclp)
+ {
+ memcpy (aclp, lacl, pos * sizeof (aclent_t));
+ if (aclcnt)
+ *aclcnt = pos;
+ }
+ return (void *) aclp;
+ }
+}
+
+extern "C" aclent_t *
+aclfromtext32 (char *acltextp, int *aclcnt)
+{
+ return (aclent_t *) __aclfromtext (acltextp, aclcnt, false);
}
#ifdef __x86_64__