summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/autoload.cc2
-rw-r--r--winsup/cygwin/cygheap.h38
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc8
-rw-r--r--winsup/cygwin/pwdgrp.h39
-rw-r--r--winsup/cygwin/sec_helper.cc8
-rw-r--r--winsup/cygwin/uinfo.cc258
7 files changed, 192 insertions, 181 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ee6da9755..c79a62684 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,23 @@
+2014-02-11 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (NetLocalGroupGetInfo): Replace NetGroupGetInfo.
+ * cygheap.h (class cygheap_ugid_cache): Move ugid_cache_t type here
+ and rename.
+ (struct init_cygheap): Add cygheap_ugid_cache member "ugid_cache".
+ * pwdgrp.h (class ugid_cache_t): Remove here.
+ * fhandler_disk_file.cc (fhandler_base::fstat_by_nfs_ea): Accommodate
+ move of ugid_cache to cygheap.
+ * sec_helper.cc (get_sids_info): Ditto.
+ * uinfo.cc (ugid_cache): Remove.
+ (pwdgrp::fetch_account_from_windows): Define id_val globally.
+ Move SidTypeAlias handling into SidTypeUser/SidTypeGroup branch since
+ aliases are handled like groups in SAM. Accommodate move of ugid_cache
+ to cygheap. Consolidate code reading SAM comments into a single branch
+ for both, SidTypeUser and SidTypeAlias. For SidTypeAlias, fix thinko
+ and call NetLocalGroupGetInfo rather than NetGroupGetInfo. Simplify
+ code setting Cygwin primary group for SAM accounts. Add code to handle
+ UNIX uid/gid from SAM comment.
+
2014-02-11 Christopher Faylor <me.cygwin2014@cgf.cx>
* winsup.h (Interlocked*): Use intrinsic versions of Interlocked
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 15d185a84..1086bd872 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -610,7 +610,7 @@ LoadDLLfunc (WNetOpenEnumA, 20, mpr)
LoadDLLfunc (DsEnumerateDomainTrustsW, 16, netapi32)
LoadDLLfunc (DsGetDcNameW, 24, netapi32)
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
-LoadDLLfunc (NetGroupGetInfo, 16, netapi32)
+LoadDLLfunc (NetLocalGroupGetInfo, 16, netapi32)
LoadDLLfunc (NetUseGetInfo, 16, netapi32)
LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index a6cfd9d44..9596161f3 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -434,6 +434,43 @@ public:
inline bool nss_db_caching () const { return caching; }
};
+class cygheap_ugid_cache
+{
+ struct idmap {
+ uint32_t nfs_id;
+ uint32_t cyg_id;
+ };
+ class idmaps {
+ uint32_t _cnt;
+ uint32_t _max;
+ idmap *_map;
+ public:
+ uint32_t get (uint32_t id) const
+ {
+ for (uint32_t i = 0; i < _cnt; ++i)
+ if (_map[i].nfs_id == id)
+ return _map[i].cyg_id;
+ return (uint32_t) -1;
+ }
+ void add (uint32_t nfs_id, uint32_t cyg_id)
+ {
+ if (_cnt >= _max)
+ _map = (idmap *) crealloc (_map, (_max += 10) * sizeof (*_map));
+ _map[_cnt].nfs_id = nfs_id;
+ _map[_cnt].cyg_id = cyg_id;
+ ++_cnt;
+ }
+ };
+ idmaps uids;
+ idmaps gids;
+
+public:
+ uid_t get_uid (uid_t uid) const { return uids.get (uid); }
+ gid_t get_gid (gid_t gid) const { return gids.get (gid); }
+ void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); }
+ void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); }
+};
+
struct hook_chain
{
void **loc;
@@ -459,6 +496,7 @@ struct init_cygheap: public mini_cygheap
cygheap_root root;
cygheap_domain_info dom;
cygheap_pwdgrp pg;
+ cygheap_ugid_cache ugid_cache;
cygheap_user user;
user_heap_info user_heap;
mode_t umask;
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index aea390508..a44bfb8b6 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -347,8 +347,8 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
the cache, try to fetch it from the configured RFC 2307 domain (see
last comment in cygheap_domain_info::init() for more information) and
add it to the mapping cache. */
- buf->st_uid = ugid_cache.get_uid (nfs_attr->uid);
- buf->st_gid = ugid_cache.get_gid (nfs_attr->gid);
+ buf->st_uid = cygheap->ugid_cache.get_uid (nfs_attr->uid);
+ buf->st_gid = cygheap->ugid_cache.get_gid (nfs_attr->gid);
if (buf->st_uid == ILLEGAL_UID)
{
uid_t map_uid = ILLEGAL_UID;
@@ -358,7 +358,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
map_uid = cldap.remap_uid (nfs_attr->uid);
if (map_uid == ILLEGAL_UID)
map_uid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->uid);
- ugid_cache.add_uid (nfs_attr->uid, map_uid);
+ cygheap->ugid_cache.add_uid (nfs_attr->uid, map_uid);
buf->st_uid = map_uid;
}
if (buf->st_gid == ILLEGAL_GID)
@@ -370,7 +370,7 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
map_gid = cldap.remap_gid (nfs_attr->gid);
if (map_gid == ILLEGAL_GID)
map_gid = MAP_UNIX_TO_CYGWIN_ID (nfs_attr->gid);
- ugid_cache.add_gid (nfs_attr->gid, map_gid);
+ cygheap->ugid_cache.add_gid (nfs_attr->gid, map_gid);
buf->st_gid = map_gid;
}
buf->st_rdev = makedev (nfs_attr->rdev.specdata1,
diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h
index a93d2b979..4ed245104 100644
--- a/winsup/cygwin/pwdgrp.h
+++ b/winsup/cygwin/pwdgrp.h
@@ -141,42 +141,3 @@ public:
struct group *find_group (const char *name);
struct group *find_group (gid_t gid);
};
-
-class ugid_cache_t
-{
- struct idmap {
- uint32_t nfs_id;
- uint32_t cyg_id;
- };
- class idmaps {
- uint32_t _cnt;
- uint32_t _max;
- idmap *_map;
- public:
- idmaps () : _cnt (0), _max (0), _map (NULL) {}
- uint32_t get (uint32_t id) const
- {
- for (uint32_t i = 0; i < _cnt; ++i)
- if (_map[i].nfs_id == id)
- return _map[i].cyg_id;
- return (uint32_t) -1;
- }
- void add (uint32_t nfs_id, uint32_t cyg_id)
- {
- if (_cnt >= _max)
- _map = (idmap *) realloc (_map, (_max += 10) * sizeof (*_map));
- _map[_cnt].nfs_id = nfs_id;
- _map[_cnt].cyg_id = cyg_id;
- ++_cnt;
- }
- };
- idmaps uids;
- idmaps gids;
-
-public:
- uid_t get_uid (uid_t uid) const { return uids.get (uid); }
- gid_t get_gid (gid_t gid) const { return gids.get (gid); }
- void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); }
- void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); }
-};
-extern ugid_cache_t ugid_cache;
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index 8aeac2e5b..8a31693f1 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -314,7 +314,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid
last comment in cygheap_domain_info::init() for more information) and
add it to the mapping cache. */
gid_t gid = sid_sub_auth_rid (group_sid);
- gid_t map_gid = ugid_cache.get_gid (gid);
+ gid_t map_gid = cygheap->ugid_cache.get_gid (gid);
if (map_gid == ILLEGAL_GID)
{
domain = cygheap->dom.get_rfc2307_domain ();
@@ -322,7 +322,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid
map_gid = cldap.remap_gid (gid);
if (map_gid == ILLEGAL_GID)
map_gid = MAP_UNIX_TO_CYGWIN_ID (gid);
- ugid_cache.add_gid (gid, map_gid);
+ cygheap->ugid_cache.add_gid (gid, map_gid);
}
*gidret = map_gid;
}
@@ -343,7 +343,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid
{
/* Samba UNIX user. See comment above. */
uid_t uid = sid_sub_auth_rid (owner_sid);
- uid_t map_uid = ugid_cache.get_uid (uid);
+ uid_t map_uid = cygheap->ugid_cache.get_uid (uid);
if (map_uid == ILLEGAL_UID)
{
domain = cygheap->dom.get_rfc2307_domain ();
@@ -351,7 +351,7 @@ get_sids_info (cygpsid owner_sid, cygpsid group_sid, uid_t * uidret, gid_t * gid
map_uid = cldap.remap_uid (uid);
if (map_uid == ILLEGAL_UID)
map_uid = MAP_UNIX_TO_CYGWIN_ID (uid);
- ugid_cache.add_uid (uid, map_uid);
+ cygheap->ugid_cache.add_uid (uid, map_uid);
}
*uidret = map_uid;
}
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index d522b9f7b..2bf10ac7f 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -548,8 +548,6 @@ pwdgrp::add_line (char *eptr)
return eptr;
}
-ugid_cache_t ugid_cache;
-
void
cygheap_pwdgrp::init ()
{
@@ -1100,6 +1098,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
WCHAR sidstr[128];
/* Temporary stuff. */
ULONG posix_offset = 0;
+ uint32_t id_val;
cyg_ldap cldap;
bool ldap_open = false;
@@ -1240,8 +1239,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
Skip primary domain. */
if (!td->PosixOffset && !(td->Flags & DS_DOMAIN_PRIMARY))
{
- uint32_t id_val;
-
if (!ldap_open && !(ldap_open = cldap.open (NULL)))
id_val = cygheap->dom.lowest_tdo_posix_offset
- 0x01000000;
@@ -1287,18 +1284,29 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
if a process is running as LocalSystem service. */
if (acc_type == SidTypeUser && sid_sub_auth_count (sid) <= 3)
acc_type = SidTypeWellKnownGroup;
- /* Alias? There are two types, the builtin aliases like "Administrators"
- and the local groups in SAM. Handle local groups as groups. */
- else if (acc_type == SidTypeAlias
- && sid_sub_auth (sid, 0) == SECURITY_NT_NON_UNIQUE)
- acc_type = SidTypeGroup;
-
switch (acc_type)
{
case SidTypeUser:
case SidTypeGroup:
+ case SidTypeAlias:
+ /* Predefined alias? */
+ if (acc_type == SidTypeAlias
+ && sid_sub_auth (sid, 0) != SECURITY_NT_NON_UNIQUE)
+ {
+#ifdef INTERIX_COMPATIBLE
+ posix_offset = 0x30000;
+ uid = 0x1000 * sid_sub_auth (sid, 0)
+ + (sid_sub_auth_rid (sid) & 0xffff);
+#else
+ posix_offset = 0;
+#endif
+ name_style = (cygheap->pg.nss_prefix_always ()) ? fully_qualified
+ : plus_prepended;
+ domain = cygheap->dom.account_flat_name ();
+ is_domain_account = false;
+ }
/* Account domain account? */
- if (!wcscmp (dom, cygheap->dom.account_flat_name ()))
+ else if (!wcscmp (dom, cygheap->dom.account_flat_name ()))
{
posix_offset = 0x30000;
if (cygheap->dom.member_machine ()
@@ -1345,8 +1353,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
fetch it. */
if (!posix_offset)
{
- uint32_t id_val;
-
if (!ldap_open && !(ldap_open = cldap.open (NULL)))
{
/* We're probably running under a local account,
@@ -1385,7 +1391,8 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
return NULL;
}
/* Generate values. */
- uid = posix_offset + sid_sub_auth_rid (sid);
+ if (uid == ILLEGAL_UID)
+ uid = posix_offset + sid_sub_auth_rid (sid);
gid = posix_offset + DOMAIN_GROUP_RID_USERS; /* Default. */
if (is_domain_account)
@@ -1396,9 +1403,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
if (cldap.fetch_ad_account (sid, group))
{
PWCHAR val;
- uint32_t id_val;
-
- if (!group)
+ if (acc_type == SidTypeUser)
{
if ((id_val = cldap.get_primary_gid ()) != ILLEGAL_GID)
gid = posix_offset + id_val;
@@ -1419,10 +1424,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
id mapping on the fly. */
id_val = cldap.get_unix_uid ();
if (id_val != ILLEGAL_UID
- && ugid_cache.get_uid (id_val) == ILLEGAL_UID)
- ugid_cache.add_uid (id_val, uid);
+ && cygheap->ugid_cache.get_uid (id_val)
+ == ILLEGAL_UID)
+ cygheap->ugid_cache.add_uid (id_val, uid);
}
- else
+ else /* SidTypeGroup */
{
if ((val = cldap.get_group_name ())
&& wcscmp (name, val))
@@ -1430,136 +1436,124 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
* sizeof (WCHAR)), val);
id_val = cldap.get_unix_gid ();
if (id_val != ILLEGAL_GID
- && ugid_cache.get_gid (id_val) == ILLEGAL_GID)
- ugid_cache.add_gid (id_val, uid);
+ && cygheap->ugid_cache.get_gid (id_val)
+ == ILLEGAL_GID)
+ cygheap->ugid_cache.add_gid (id_val, uid);
}
}
}
/* Otherwise check account domain (local SAM).*/
- else if (acc_type == SidTypeUser)
+ else
{
NET_API_STATUS nas;
PUSER_INFO_4 ui;
-
- nas = NetUserGetInfo (domain, name, 4, (PBYTE *) &ui);
- if (nas != NERR_Success)
- debug_printf ("NetUserGetInfo(%W,%W) %u", domain, name, nas);
- else
+ PLOCALGROUP_INFO_1 gi;
+ PCWSTR comment;
+ PWCHAR pgrp = NULL;
+ PWCHAR uxid = NULL;
+ struct {
+ PCWSTR str;
+ size_t len;
+ PWCHAR *tgt;
+ bool group;
+ } search[] = {
+ { L"name=\"", 6, &user, true },
+ { L"unix=\"", 6, &uxid, true },
+ { L"home=\"", 6, &home, false },
+ { L"shell=\"", 7, &shell, false },
+ { L"group=\"", 7, &pgrp, false },
+ { NULL, 0, NULL }
+ };
+ PWCHAR s, e;
+
+ if (acc_type == SidTypeUser)
{
- PWCHAR pgrp = NULL;
- struct {
- PCWSTR str;
- size_t len;
- PWCHAR *tgt;
- } search[] = {
- { L"name=\"", 6, &user },
- { L"home=\"", 6, &home },
- { L"shell=\"", 7, &shell },
- { L"group=\"", 7, &pgrp }
- };
- PWCHAR s, e;
-
- /* Fetch primary group. */
- gid = posix_offset + ui->usri4_primary_group_id;
- /* Local SAM accounts have only a handful attributes
- available to home users. Therefore, fetch different
- Cygwin user name, Cygwin home dir, and Cygwin login
- shell from the "Description" field in XML short
- style. */
- if ((s = wcsstr (ui->usri4_comment, L"<cygwin "))
- && (e = wcsstr (s + 8, L"/>")))
+ nas = NetUserGetInfo (NULL, name, 4, (PBYTE *) &ui);
+ if (nas != NERR_Success)
{
- s += 8;
- *e = L'\0';
- while (*s)
- {
- while (*s == L' ')
- ++s;
- for (size_t i = 0;
- i < sizeof search / sizeof search[0];
- ++i)
- if (!wcsncmp (s, search[i].str, search[i].len))
- {
- s += search[i].len;
- if ((e = wcschr (s, L'"'))
- && (i > 0 || wcsncmp (name, s, e - s)))
- {
- *search[i].tgt =
- (PWCHAR) alloca ((e - s + 1)
- * sizeof (WCHAR));
- *wcpncpy (*search[i].tgt, s, e - s) = L'\0';
- s = e + 1;
- }
- else
- {
- *s = L'\0';
- break;
- }
- }
- }
+ debug_printf ("NetUserGetInfo(%W) %u", name, nas);
+ break;
}
- NetApiBufferFree (ui);
- if (pgrp)
+ /* Set comment variable for below attribute loop. */
+ comment = ui->usri4_comment;
+ }
+ else /* SidTypeGroup || SidTypeAlias */
+ {
+ nas = NetLocalGroupGetInfo (NULL, name, 1, (PBYTE *) &gi);
+ if (nas != NERR_Success)
{
- /* For setting the primary group, we have to test all
- three possible Cygwin name variations:
-
- MACHINE+group, +group, group
- */
- char gname[2 * (DNLEN + UNLEN + 1)];
- char *sep;
- struct group *gr;
-
- sep += sys_wcstombs (sep = gname, 2 * DNLEN + 1, domain);
- *sep = cygheap->pg.nss_separator ()[0];
- sys_wcstombs (sep + 1, 2 * UNLEN + 1, pgrp);
- if ((gr = internal_getgrnam (gname))
- || (gr = internal_getgrnam (sep))
- || (gr = internal_getgrnam (sep + 1)))
- gid = gr->gr_gid;
+ debug_printf ("NetLocalGroupGetInfo(%W) %u", name, nas);
+ break;
}
+ /* Set comment variable for below attribute loop. */
+ comment = gi->lgrpi1_comment;
}
- }
- else /* SidTypeGroup */
- {
- NET_API_STATUS nas;
- PGROUP_INFO_3 gi;
-
- nas = NetGroupGetInfo (domain, name, 3, (PBYTE *) &gi);
- if (nas != NERR_Success)
- debug_printf ("NetGroupGetInfo(%W,%W) %u", domain, name, nas);
+ /* Local SAM accounts have only a handful attributes
+ available to home users. Therefore, fetch additional
+ passwd/group attributes from the "Description" field
+ in XML short style. */
+ if ((s = wcsstr (comment, L"<cygwin "))
+ && (e = wcsstr (s + 8, L"/>")))
+ {
+ s += 8;
+ *e = L'\0';
+ while (*s)
+ {
+ bool found = false;
+
+ while (*s == L' ')
+ ++s;
+ for (size_t i = 0; search[i].str; ++i)
+ if ((acc_type == SidTypeUser || search[i].group)
+ && !wcsncmp (s, search[i].str, search[i].len))
+ {
+ s += search[i].len;
+ if ((e = wcschr (s, L'"'))
+ && (i > 0 || wcsncmp (name, s, e - s)))
+ {
+ *search[i].tgt =
+ (PWCHAR) alloca ((e - s + 1)
+ * sizeof (WCHAR));
+ *wcpncpy (*search[i].tgt, s, e - s) = L'\0';
+ s = e + 1;
+ found = true;
+ }
+ else
+ break;
+ }
+ if (!found)
+ break;
+ }
+ }
+ if (acc_type == SidTypeUser)
+ NetApiBufferFree (ui);
else
+ NetApiBufferFree (gi);
+ if (pgrp)
{
- PWCHAR s, e;
-
- /* Fetch different Cygwin group name from description. */
- if ((s = wcsstr (gi->grpi3_comment, L"<cygwin "))
- && (e = wcsstr (s + 8, L"/>")))
+ /* For setting the primary group, we have to test
+ with and without prepended separator. */
+ char gname[2 * UNLEN + 2];
+ struct group *gr;
+
+ *gname = cygheap->pg.nss_separator ()[0];
+ sys_wcstombs (gname + 1, 2 * UNLEN + 1, pgrp);
+ if ((gr = internal_getgrnam (gname))
+ || (gr = internal_getgrnam (gname + 1)))
+ gid = gr->gr_gid;
+ }
+ if (uxid && ((id_val = wcstoul (uxid, &e, 10)), !*e))
+ {
+ if (acc_type == SidTypeUser)
{
- s += 8;
- *e = L'\0';
- while (*s)
- {
- while (*s == L' ')
- ++s;
- if (!wcsncmp (s, L"name=\"", 6))
- {
- s += 6;
- if ((e = wcschr (s, L'"')))
- {
- *wcpncpy (name = namebuf, s, e - s) = L'\0';
- s = e + 1;
- }
- else
- break;
- }
- }
+ if (cygheap->ugid_cache.get_uid (id_val) == ILLEGAL_UID)
+ cygheap->ugid_cache.add_uid (id_val, uid);
}
- NetApiBufferFree (gi);
+ else if (cygheap->ugid_cache.get_gid (id_val) == ILLEGAL_GID)
+ cygheap->ugid_cache.add_gid (id_val, uid);
}
}
break;
- case SidTypeAlias:
case SidTypeWellKnownGroup:
name_style = (cygheap->pg.nss_prefix_always ()) ? fully_qualified
: plus_prepended;
@@ -1569,8 +1563,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
{
uid = 0x1000 * sid_sub_auth (sid, 0)
+ (sid_sub_auth_rid (sid) & 0xffff);
- if (sid_sub_auth (sid, 0) > SECURITY_BUILTIN_DOMAIN_RID)
- name_style = fully_qualified;
+ name_style = fully_qualified;
}
else
uid = 0x10000 + 0x100 * sid_id_auth (sid)
@@ -1585,7 +1578,6 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
{
uid = 0x1000 * sid_sub_auth (sid, 0)
+ (sid_sub_auth_rid (sid) & 0xffff);
- //name_style = fully_qualified;
}
#endif
/* Special case for "Everyone". We don't want to return Everyone