summaryrefslogtreecommitdiffstats
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog69
-rw-r--r--winsup/cygwin/autoload.cc6
-rw-r--r--winsup/cygwin/cygheap.h16
-rw-r--r--winsup/cygwin/cygtls.h2
-rw-r--r--winsup/cygwin/grp.cc111
-rw-r--r--winsup/cygwin/ldap.cc120
-rw-r--r--winsup/cygwin/ldap.h7
-rw-r--r--winsup/cygwin/passwd.cc368
-rw-r--r--winsup/cygwin/pwdgrp.h102
-rw-r--r--winsup/cygwin/tlsoffsets.h216
-rw-r--r--winsup/cygwin/tlsoffsets64.h216
-rw-r--r--winsup/cygwin/uinfo.cc109
12 files changed, 1060 insertions, 282 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ccd93b2ee..520803b01 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,72 @@
+2014-02-17 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (ldap_abandon): Import.
+ (ldap_result): Import.
+ (ldap_searchW): Import.
+ (NetGroupEnum): Import.
+ (NetLocalGroupEnum): Import.
+ (NetUserEnum): Import.
+ * cygheap.h (class cygheap_pwdgrp): Add members enums and enum_tdoms.
+ (cygheap_pwdgrp::nss_db_enums): New inline method.
+ (cygheap_pwdgrp::nss_db_enum_tdoms): Ditto.
+ * cygtls.h (struct _local_storage): Drop unused members pw_pos and
+ grp_pos.
+ * grp.cc (grent): New static variable of class gr_ent.
+ (gr_ent::enumerate_caches): New method.
+ (gr_ent::enumerate_local): New method.
+ (gr_ent::getgrent): New method.
+ (setgrent): Call gr_ent method.
+ (getgrent32): Ditto.
+ (endgrent): Ditto.
+ * ldap.cc (sid_attr): Rename from nfs_attr.
+ (cyg_ldap::close): Abandon still running asynchronous search.
+ (cyg_ldap::fetch_ad_account): Reduce filter buffer size.
+ (cyg_ldap::enumerate_ad_accounts): New method.
+ (cyg_ldap::next_account): New method.
+ (cyg_ldap::fetch_posix_offset_for_domain): Reduce filter buffer size.
+ (cyg_ldap::fetch_unix_sid_from_ad): Ditto. Fix return value in case
+ no value has been read.
+ (cyg_ldap::fetch_unix_name_from_rfc2307): Reduce filter buffer size.
+ * ldap.h (class cyg_ldap): Add msg_id member.
+ (cyg_ldap::enumerate_ad_accounts): Declare.
+ (cyg_ldap::next_account): Declare:
+ * passwd.cc (pwent): New static variable of class pw_ent.
+ (pg_ent::clear_cache): New method.
+ (pg_ent::setent): New method.
+ (pg_ent::getent): New method.
+ (pg_ent::endent): New method.
+ (pg_ent::enumerate_file): New method.
+ (pg_ent::enumerate_builtin): New method.
+ (pg_ent::enumerate_sam): New method.
+ (pg_ent::enumerate_ad): New method.
+ (pw_ent::enumerate_caches): New method.
+ (pw_ent::enumerate_local): New method.
+ (pw_ent::getpwent): New method.
+ (setpwent): Call pw_ent method.
+ (getpwent): Ditto.
+ (endpwent): Ditto.
+ * pwdgrp.h (class pwdgrp): Define pg_ent, pw_ent and gr_ent as friend
+ classes.
+ (pwdgrp::add_account_post_fetch): Declare with extra bool parameter.
+ (pwdgrp::file_attr): New inline method.
+ (enum nss_enum_t): Define.
+ (class pg_ent): Define.
+ (class pw_ent): Define.
+ (class gr_ent): Define.
+ * tlsoffsets.h: Regenerate.
+ * tlsoffsets64.h: Ditto.
+ * uinfo.cc (cygheap_pwdgrp::init): Initialize enums and enum_tdoms.
+ (cygheap_pwdgrp::nss_init_line): Fix typo in preceeding comment.
+ Handle new "db_enum" keyword.
+ (pwdgrp::add_account_post_fetch): Take additional `bool lock' parameter
+ and acquire pglock before adding element to array if lock is true.
+ (pwdgrp::add_account_from_file): Call add_account_post_fetch with lock
+ set to true.
+ (pwdgrp::add_account_from_windows): Ditto in case of caching.
+ (pwdgrp::fetch_account_from_windows): Handle builtin aliases only
+ known to the domain controller. Only call NetLocalGroupGetInfo for
+ aliases.
+
2014-02-16 Corinna Vinschen <corinna@vinschen.de>
* miscfuncs.h (NT_readline::close): New function to close handle.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 1086bd872..65999de46 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -584,6 +584,7 @@ LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
#pragma push_macro ("mangle")
#undef mangle
#define mangle(name, n) #name
+LoadDLLfunc (ldap_abandon, 0, wldap32)
LoadDLLfunc (ldap_bind_s, 0, wldap32)
LoadDLLfunc (ldap_count_valuesW, 0, wldap32)
LoadDLLfunc (ldap_first_entry, 0, wldap32)
@@ -592,6 +593,8 @@ LoadDLLfunc (ldap_get_values_lenW, 0, wldap32)
LoadDLLfunc (ldap_initW, 0, wldap32)
LoadDLLfunc (ldap_memfreeW, 0, wldap32)
LoadDLLfunc (ldap_next_entry, 0, wldap32)
+LoadDLLfunc (ldap_result, 0, wldap32)
+LoadDLLfunc (ldap_searchW, 0, wldap32)
LoadDLLfunc (ldap_search_stW, 0, wldap32)
LoadDLLfunc (ldap_set_option, 0, wldap32)
LoadDLLfunc (ldap_sslinitW, 0, wldap32)
@@ -610,8 +613,11 @@ LoadDLLfunc (WNetOpenEnumA, 20, mpr)
LoadDLLfunc (DsEnumerateDomainTrustsW, 16, netapi32)
LoadDLLfunc (DsGetDcNameW, 24, netapi32)
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
+LoadDLLfunc (NetGroupEnum, 28, netapi32)
+LoadDLLfunc (NetLocalGroupEnum, 28, netapi32)
LoadDLLfunc (NetLocalGroupGetInfo, 16, netapi32)
LoadDLLfunc (NetUseGetInfo, 16, netapi32)
+LoadDLLfunc (NetUserEnum, 32, netapi32)
LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetUserGetLocalGroups, 32, netapi32)
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 9596161f3..7d4198a49 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -400,12 +400,14 @@ class cygheap_pwdgrp
NSS_PRIMARY,
NSS_ALWAYS
};
- bool nss_inited;
- int pwd_src;
- int grp_src;
- pfx_t prefix;
- WCHAR separator[2];
- bool caching;
+ bool nss_inited;
+ int pwd_src;
+ int grp_src;
+ pfx_t prefix;
+ WCHAR separator[2];
+ bool caching;
+ int enums;
+ PWCHAR enum_tdoms;
void nss_init_line (const char *line);
void _nss_init ();
@@ -432,6 +434,8 @@ public:
inline bool nss_prefix_always () const { return prefix == NSS_ALWAYS; }
inline PCWSTR nss_separator () const { return separator; }
inline bool nss_db_caching () const { return caching; }
+ inline int nss_db_enums () const { return enums; }
+ inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
};
class cygheap_ugid_cache
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 2c4f921a8..fd464f4ce 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -82,11 +82,9 @@ struct _local_storage
/* passwd.cc */
void *pwbuf;
char pass[_PASSWORD_LEN];
- ULONG pw_pos;
/* grp.cc */
void *grbuf;
- ULONG grp_pos;
/* dlfcn.cc */
int dl_error;
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index 09a8daa37..6f9b4b9bb 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -13,6 +13,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
+#include <lm.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,6 +24,9 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "ntdll.h"
+#include "miscfuncs.h"
+#include "ldap.h"
+#include "tls_pbuf.h"
static char * NO_COPY_RO null_ptr;
@@ -309,31 +313,104 @@ getgrnam (const char *name)
}
#endif
-extern "C" void
-endgrent ()
-{
- _my_tls.locals.grp_pos = 0;
-}
+/* getgrent functions are not reentrant. */
+static gr_ent grent;
-extern "C" struct group *
-getgrent32 ()
+void *
+gr_ent::enumerate_caches ()
{
- pwdgrp &grf = cygheap->pg.grp_cache.file;
- if (cygheap->pg.nss_grp_files ())
+ if (!max && from_files)
{
- cygheap->pg.grp_cache.file.check_file (true);
- if (_my_tls.locals.grp_pos < grf.cached_groups ())
- return &grf.group ()[_my_tls.locals.grp_pos++].g;
+ pwdgrp &grf = cygheap->pg.grp_cache.file;
+ grf.check_file (true);
+ if (cnt < grf.cached_groups ())
+ return &grf.group ()[cnt++].g;
+ cnt = 0;
+ max = 1;
}
- if ((cygheap->pg.nss_grp_db ()) && cygheap->pg.nss_db_caching ())
+ if (from_db && cygheap->pg.nss_db_caching ())
{
pwdgrp &grw = cygheap->pg.grp_cache.win;
- if (_my_tls.locals.grp_pos - grf.cached_groups () < grw.cached_groups ())
- return &grw.group ()[_my_tls.locals.grp_pos++ - grf.cached_groups ()].g;
+ if (cnt < grw.cached_groups ())
+ return &grw.group ()[cnt++].g;
}
+ cnt = max = 0;
return NULL;
}
+void *
+gr_ent::enumerate_local ()
+{
+ while (true)
+ {
+ if (!cnt)
+ {
+ DWORD total;
+ NET_API_STATUS ret;
+
+ if (buf)
+ {
+ NetApiBufferFree (buf);
+ buf = NULL;
+ }
+ if (resume == ULONG_MAX)
+ ret = ERROR_NO_MORE_ITEMS;
+ else
+ ret = NetLocalGroupEnum (NULL, 0, (PBYTE *) &buf,
+ MAX_PREFERRED_LENGTH,
+ &max, &total, &resume);
+ if (ret == NERR_Success)
+ resume = ULONG_MAX;
+ else if (ret != ERROR_MORE_DATA)
+ {
+ cnt = max = resume = 0;
+ return NULL;
+ }
+ }
+ while (cnt < max)
+ {
+ cygsid sid;
+ DWORD slen = MAX_SID_LEN;
+ WCHAR dom[DNLEN + 1];
+ DWORD dlen = DNLEN + 1;
+ SID_NAME_USE acc_type;
+
+ LookupAccountNameW (NULL,
+ ((PLOCALGROUP_INFO_0) buf)[cnt++].lgrpi0_name,
+ sid, &slen, dom, &dlen, &acc_type);
+ fetch_user_arg_t arg;
+ arg.type = SID_arg;
+ arg.sid = &sid;
+ char *line = pg.fetch_account_from_windows (arg, true);
+ if (line)
+ return pg.add_account_post_fetch (line, false);
+ }
+ cnt = 0;
+ }
+}
+
+struct group *
+gr_ent::getgrent (void)
+{
+ if (state == rewound)
+ setent (true);
+ else
+ clear_cache ();
+ return (struct group *) getent ();
+}
+
+extern "C" void
+setgrent ()
+{
+ grent.setgrent ();
+}
+
+extern "C" struct group *
+getgrent32 (void)
+{
+ return grent.getgrent ();
+}
+
#ifdef __x86_64__
EXPORT_ALIAS (getgrent32, getgrent)
#else
@@ -347,9 +424,9 @@ getgrent ()
#endif
extern "C" void
-setgrent ()
+endgrent (void)
{
- _my_tls.locals.grp_pos = 0;
+ grent.endgrent ();
}
int
diff --git a/winsup/cygwin/ldap.cc b/winsup/cygwin/ldap.cc
index 64e8949da..740995a61 100644
--- a/winsup/cygwin/ldap.cc
+++ b/winsup/cygwin/ldap.cc
@@ -20,6 +20,7 @@ details. */
#include "pinfo.h"
#include "lm.h"
#include "dsgetdc.h"
+#include "tls_pbuf.h"
static LDAP_TIMEVAL tv = { 3, 0 };
@@ -54,7 +55,7 @@ PWCHAR tdom_attr[] =
NULL
};
-PWCHAR nfs_attr[] =
+PWCHAR sid_attr[] =
{
(PWCHAR) L"objectSid",
NULL
@@ -216,6 +217,8 @@ err:
void
cyg_ldap::close ()
{
+ if (msg_id != (ULONG) -1)
+ ldap_abandon (lh, msg_id);
if (lh)
ldap_unbind (lh);
if (msg)
@@ -228,12 +231,13 @@ cyg_ldap::close ()
msg = entry = NULL;
val = NULL;
rootdse = NULL;
+ msg_id = (ULONG) -1;
}
bool
cyg_ldap::fetch_ad_account (PSID sid, bool group)
{
- WCHAR filter[512], *f;
+ WCHAR filter[140], *f;
LONG len = (LONG) RtlLengthSid (sid);
PBYTE s = (PBYTE) sid;
static WCHAR hex_wchars[] = L"0123456789abcdef";
@@ -273,10 +277,109 @@ cyg_ldap::fetch_ad_account (PSID sid, bool group)
return true;
}
+bool
+cyg_ldap::enumerate_ad_accounts (PCWSTR domain, bool group)
+{
+ tmp_pathbuf tp;
+ PCWSTR filter;
+ PWCHAR dse;
+
+ if (msg)
+ {
+ ldap_memfreeW ((PWCHAR) msg);
+ msg = entry = NULL;
+ }
+ if (val)
+ {
+ ldap_value_freeW (val);
+ val = NULL;
+ }
+ if (!group)
+ filter = L"(&(objectClass=User)"
+ "(objectCategory=Person)"
+ /* 512 == ADS_UF_NORMAL_ACCOUNT */
+ "(userAccountControl:" LDAP_MATCHING_RULE_BIT_AND ":=512)"
+ "(objectSid=*))";
+ else if (!domain)
+ filter = L"(&(objectClass=Group)"
+ "(objectSid=*))";
+ else
+ filter = L"(&(objectClass=Group)"
+ /* 1 == ACCOUNT_GROUP */
+ "(!(groupType:" LDAP_MATCHING_RULE_BIT_AND ":=1))"
+ "(objectSid=*))";
+ if (!domain)
+ dse = rootdse;
+ else
+ {
+ /* create rootdse from domain name. */
+ dse = tp.w_get ();
+ PCWSTR ps, pe;
+ PWCHAR d;
+
+ d = dse;
+ for (ps = domain; (pe = wcschr (ps, L'.')); ps = pe + 1)
+ {
+ if (d > dse)
+ d = wcpcpy (d, L",");
+ d = wcpncpy (wcpcpy (d, L"DC="), ps, pe - ps);
+ }
+ if (d > dse)
+ d = wcpcpy (d, L",");
+ d = wcpcpy (wcpcpy (d, L"DC="), ps);
+ }
+ msg_id = ldap_searchW (lh, dse, LDAP_SCOPE_SUBTREE, (PWCHAR) filter,
+ sid_attr, 0);
+ if (msg_id == (ULONG) -1)
+ {
+ debug_printf ("ldap_searchW(%W,%W) error 0x%02x", dse, filter,
+ LdapGetLastError ());
+ return false;
+ }
+ return true;
+}
+
+bool
+cyg_ldap::next_account (cygsid &sid)
+{
+ ULONG ret;
+ PLDAP_BERVAL *bval;
+
+ if (msg)
+ {
+ ldap_memfreeW ((PWCHAR) msg);
+ msg = entry = NULL;
+ }
+ if (val)
+ {
+ ldap_value_freeW (val);
+ val = NULL;
+ }
+ ret = ldap_result (lh, msg_id, LDAP_MSG_ONE, &tv, &msg);
+ if (ret == 0)
+ {
+ debug_printf ("ldap_result() timeout!");
+ return false;
+ }
+ if (ret == (ULONG) -1)
+ {
+ debug_printf ("ldap_result() error 0x%02x", LdapGetLastError ());
+ return false;
+ }
+ if ((entry = ldap_first_entry (lh, msg))
+ && (bval = ldap_get_values_lenW (lh, entry, sid_attr[0])))
+ {
+ sid = (PSID) bval[0]->bv_val;
+ ldap_value_free_len (bval);
+ return true;
+ }
+ return false;
+}
+
uint32_t
cyg_ldap::fetch_posix_offset_for_domain (PCWSTR domain)
{
- WCHAR filter[512];
+ WCHAR filter[300];
ULONG ret;
if (msg)
@@ -331,7 +434,7 @@ cyg_ldap::get_num_attribute (int idx)
bool
cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group)
{
- WCHAR filter[512];
+ WCHAR filter[48];
ULONG ret;
PLDAP_BERVAL *bval;
@@ -345,25 +448,26 @@ cyg_ldap::fetch_unix_sid_from_ad (uint32_t id, cygsid &sid, bool group)
else
__small_swprintf (filter, L"(&(objectClass=User)(uidNumber=%u))", id);
if ((ret = ldap_search_stW (lh, rootdse, LDAP_SCOPE_SUBTREE, filter,
- nfs_attr, 0, &tv, &msg)) != LDAP_SUCCESS)
+ sid_attr, 0, &tv, &msg)) != LDAP_SUCCESS)
{
debug_printf ("ldap_search_stW(%W,%W) error 0x%02x",
rootdse, filter, ret);
return false;
}
if ((entry = ldap_first_entry (lh, msg))
- && (bval = ldap_get_values_lenW (lh, entry, nfs_attr[0])))
+ && (bval = ldap_get_values_lenW (lh, entry, sid_attr[0])))
{
sid = (PSID) bval[0]->bv_val;
ldap_value_free_len (bval);
+ return true;
}
- return true;
+ return false;
}
PWCHAR
cyg_ldap::fetch_unix_name_from_rfc2307 (uint32_t id, bool group)
{
- WCHAR filter[512];
+ WCHAR filter[52];
ULONG ret;
if (msg)
diff --git a/winsup/cygwin/ldap.h b/winsup/cygwin/ldap.h
index 078951768..bd23b8658 100644
--- a/winsup/cygwin/ldap.h
+++ b/winsup/cygwin/ldap.h
@@ -8,6 +8,8 @@ This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
+#pragma once
+
#pragma push_macro ("DECLSPEC_IMPORT")
#undef DECLSPEC_IMPORT
#define DECLSPEC_IMPORT
@@ -32,6 +34,7 @@ class cyg_ldap {
PWCHAR *val;
PWCHAR *attr;
bool isAD;
+ ULONG msg_id;
bool connect_ssl (PCWSTR domain);
bool connect_non_ssl (PCWSTR domain);
@@ -42,7 +45,7 @@ class cyg_ldap {
public:
cyg_ldap () : lh (NULL), rootdse (NULL), msg (NULL), entry (NULL),
- val (NULL), isAD (false)
+ val (NULL), isAD (false), msg_id ((ULONG) -1)
{}
~cyg_ldap () { close (); }
@@ -50,6 +53,8 @@ public:
bool open (PCWSTR in_domain);
void close ();
bool fetch_ad_account (PSID sid, bool group);
+ bool enumerate_ad_accounts (PCWSTR domain, bool group);
+ bool next_account (cygsid &sid);
uint32_t fetch_posix_offset_for_domain (PCWSTR domain);
uid_t remap_uid (uid_t uid);
gid_t remap_gid (gid_t gid);
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
index fb51d5aef..9d4eaba14 100644
--- a/winsup/cygwin/passwd.cc
+++ b/winsup/cygwin/passwd.cc
@@ -10,6 +10,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
+#include <lm.h>
#include <stdlib.h>
#include <stdio.h>
#include "cygerrno.h"
@@ -20,6 +21,9 @@ details. */
#include "pinfo.h"
#include "cygheap.h"
#include "shared_info.h"
+#include "miscfuncs.h"
+#include "ldap.h"
+#include "tls_pbuf.h"
/* Parse /etc/passwd line into passwd structure. */
bool
@@ -275,45 +279,375 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s
return 0;
}
-extern "C" struct passwd *
-getpwent (void)
+/* getpwent functions are not reentrant. */
+static pw_ent pwent;
+
+void
+pg_ent::clear_cache ()
{
- pwdgrp &prf = cygheap->pg.pwd_cache.file;
- if (cygheap->pg.nss_pwd_files ())
+ if (pg.curr_lines)
{
- cygheap->pg.pwd_cache.file.check_file (false);
- if (_my_tls.locals.pw_pos < prf.cached_users ())
- return &prf.passwd ()[_my_tls.locals.pw_pos++].p;
+ if (state > from_file)
+ cfree (group ? grp.g.gr_name : pwd.p.pw_name);
+ pg.curr_lines = 0;
+ }
+}
+
+void
+pg_ent::setent (bool _group, int _enums, PCWSTR _enum_tdoms)
+{
+ endent (_group);
+ if (!_enums && !_enum_tdoms)
+ {
+ enums = cygheap->pg.nss_db_enums ();
+ enum_tdoms = cygheap->pg.nss_db_enum_tdoms ();
}
- if ((cygheap->pg.nss_pwd_db ()) && cygheap->pg.nss_db_caching ())
+ else
+ {
+ enums = _enums;
+ enum_tdoms = _enum_tdoms;
+ }
+ if (_group)
+ {
+ from_files = cygheap->pg.nss_grp_files ();
+ from_db = cygheap->pg.nss_grp_db ();
+ }
+ else
+ {
+ from_files = cygheap->pg.nss_pwd_files ();
+ from_db = cygheap->pg.nss_pwd_db ();
+ }
+}
+
+void *
+pg_ent::getent (void)
+{
+ void *entry;
+
+ switch (state)
+ {
+ case rewound:
+ state = from_cache;
+ /*FALLTHRU*/
+ case from_cache:
+ if (nss_db_enum_caches ()
+ && (entry = enumerate_caches ()))
+ return entry;
+ state = from_file;
+ /*FALLTHRU*/
+ case from_file:
+ if (from_files
+ && nss_db_enum_files ()
+ && (entry = enumerate_file ()))
+ return entry;
+ state = from_builtin;
+ /*FALLTHRU*/
+ case from_builtin:
+ if (from_db
+ && nss_db_enum_builtin ()
+ && (entry = enumerate_builtin ()))
+ return entry;
+ state = from_local;
+ /*FALLTHRU*/
+ case from_local:
+ if (from_db
+ && nss_db_enum_local ()
+ && (!cygheap->dom.member_machine ()
+ || !nss_db_enum_primary ())
+ && (entry = enumerate_local ()))
+ return entry;
+ state = from_sam;
+ /*FALLTHRU*/
+ case from_sam:
+ if (from_db
+ && nss_db_enum_local ()
+ && (entry = enumerate_sam ()))
+ return entry;
+ state = from_ad;
+ /*FALLTHRU*/
+ case from_ad:
+ if (cygheap->dom.member_machine ()
+ && from_db
+ && (entry = enumerate_ad ()))
+ return entry;
+ state = finished;
+ /*FALLTHRU*/
+ case finished:
+ break;
+ }
+ return NULL;
+}
+
+void
+pg_ent::endent (bool _group)
+{
+ if (buf)
+ {
+ if (state == from_file)
+ free (buf);
+ else if (state == from_local || state == from_sam)
+ NetApiBufferFree (buf);
+ buf = NULL;
+ }
+ if (!pg.curr_lines)
+ {
+ if ((group = _group))
+ {
+ pg.init_grp ();
+ pg.pwdgrp_buf = (void *) &grp;
+ }
+ else
+ {
+ pg.init_pwd ();
+ pg.pwdgrp_buf = (void *) &pwd;
+ }
+ pg.max_lines = 1;
+ }
+ else
+ clear_cache ();
+ cldap.close ();
+ rl.close ();
+ cnt = max = resume = 0;
+ enums = 0;
+ enum_tdoms = NULL;
+ state = rewound;
+}
+
+void *
+pg_ent::enumerate_file ()
+{
+ void *entry;
+
+ if (!cnt)
+ {
+ pwdgrp &prf = group ? cygheap->pg.grp_cache.file
+ : cygheap->pg.pwd_cache.file;
+ if (prf.check_file (group))
+ {
+ if (!buf)
+ buf = (char *) malloc (NT_MAX_PATH);
+ if (buf
+ && !rl.init (prf.file_attr (), buf, NT_MAX_PATH))
+ {
+ free (buf);
+ buf = NULL;
+ }
+ }
+ }
+ ++cnt;
+ if ((entry = pg.add_account_post_fetch (rl.gets (), false)))
+ return entry;
+ rl.close ();
+ free (buf);
+ buf = NULL;
+ cnt = max = resume = 0;
+ return NULL;
+}
+
+void *
+pg_ent::enumerate_builtin ()
+{
+ static const char *pwd_builtins[] = {
+ /* SYSTEM */
+ "S-1-5-18",
+ /* LocalService */
+ "S-1-5-19",
+ /* NetworkService */
+ "S-1-5-20",
+ /* Administrators */
+ "S-1-5-32-544",
+ /* TrustedInstaller */
+ "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464",
+ /* The end */
+ NULL
+ };
+ static const char *grp_builtins[] = {
+ /* SYSTEM */
+ "S-1-5-18",
+ /* TrustedInstaller */
+ "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464",
+ /* The end */
+ NULL
+ };
+
+ const char **builtins = group ? grp_builtins : pwd_builtins;
+ if (!builtins[cnt])
+ {
+ cnt = max = resume = 0;
+ return NULL;
+ }
+ cygsid sid (builtins[cnt++]);
+ fetch_user_arg_t arg;
+ arg.type = SID_arg;
+ arg.sid = &sid;
+ char *line = pg.fetch_account_from_windows (arg, group);
+ return pg.add_account_post_fetch (line, false);
+}
+
+void *
+pg_ent::enumerate_sam ()
+{
+ while (true)
+ {
+ if (!cnt)
+ {
+ DWORD total;
+ NET_API_STATUS ret;
+
+ if (buf)
+ {
+ NetApiBufferFree (buf);
+ buf = NULL;
+ }
+ if (resume == ULONG_MAX)
+ ret = ERROR_NO_MORE_ITEMS;
+ else if (group)
+ ret = NetGroupEnum (NULL, 2, (PBYTE *) &buf, MAX_PREFERRED_LENGTH,
+ &max, &total, &resume);
+ else
+ ret = NetUserEnum (NULL, 20, FILTER_NORMAL_ACCOUNT, (PBYTE *) &buf,
+ MAX_PREFERRED_LENGTH, &max, &total,
+ (PDWORD) &resume);
+ if (ret == NERR_Success)
+ resume = ULONG_MAX;
+ else if (ret != ERROR_MORE_DATA)
+ {
+ cnt = max = resume = 0;
+ return NULL;
+ }
+ }
+ while (cnt < max)
+ {
+ cygsid sid (cygheap->dom.account_sid ());
+ sid_sub_auth (sid, sid_sub_auth_count (sid)) =
+ group ? ((PGROUP_INFO_2) buf)[cnt].grpi2_group_id
+ : ((PUSER_INFO_20) buf)[cnt].usri20_user_id;
+ ++cnt;
+ ++sid_sub_auth_count (sid);
+ fetch_user_arg_t arg;
+ arg.type = SID_arg;
+ arg.sid = &sid;
+ char *line = pg.fetch_account_from_windows (arg, group);
+ if (line)
+ return pg.add_account_post_fetch (line, false);
+ }
+ cnt = 0;
+ }
+}
+
+void *
+pg_ent::enumerate_ad ()
+{
+ while (true)
+ {
+ if (!cnt)
+ {
+ PDS_DOMAIN_TRUSTSW td;
+
+ if (!resume)
+ {
+ if (!cldap.open (NULL))
+ return NULL;
+ ++resume;
+ if (!nss_db_enum_primary ()
+ || !cldap.enumerate_ad_accounts (NULL, group))
+ continue;
+ }
+ else if ((td = cygheap->dom.trusted_domain (resume - 1)))
+ {
+ ++resume;
+ if ((td->Flags & DS_DOMAIN_PRIMARY)
+ || !td->DomainSid
+ || (!nss_db_enum_tdom (td->NetbiosDomainName)
+ && !nss_db_enum_tdom (td->DnsDomainName))
+ || !cldap.enumerate_ad_accounts (td->DnsDomainName, group))
+ continue;
+ }
+ else
+ {
+ cldap.close ();
+ return NULL;
+ }
+ }
+ ++cnt;
+ cygsid sid;
+ if (cldap.next_account (sid))
+ {
+ fetch_user_arg_t arg;
+ arg.type = SID_arg;
+ arg.sid = &sid;
+ char *line = pg.fetch_account_from_windows (arg, group);
+ if (line)
+ return pg.add_account_post_fetch (line, false);
+ }
+ cnt = 0;
+ }
+}
+
+void *
+pw_ent::enumerate_caches ()
+{
+ if (!max && from_files)
+ {
+ pwdgrp &prf = cygheap->pg.pwd_cache.file;
+ prf.check_file (false);
+ if (cnt < prf.cached_users ())
+ return &prf.passwd ()[cnt++].p;
+ cnt = 0;
+ max = 1;
+ }
+ if (from_db && cygheap->pg.nss_db_caching ())
{
pwdgrp &prw = cygheap->pg.pwd_cache.win;
- if (_my_tls.locals.pw_pos - prf.cached_users () < prw.cached_users ())
- return &prw.passwd ()[_my_tls.locals.pw_pos++ - prf.cached_users ()].p;
+ if (cnt < prw.cached_users ())
+ return &prw.passwd ()[cnt++].p;
}
+ cnt = max = 0;
return NULL;
}
-#ifndef __x86_64__
-extern "C" struct passwd *
-getpwduid (__uid16_t)
+void *
+pw_ent::enumerate_local ()
{
return NULL;
}
-#endif
+
+struct passwd *
+pw_ent::getpwent (void)
+{
+ if (state == rewound)
+ setent (false);
+ else
+ clear_cache ();
+ return (struct passwd *) getent ();
+}
extern "C" void
-setpwent (void)
+setpwent ()
{
- _my_tls.locals.pw_pos = 0;
+ pwent.setpwent ();
+}
+
+extern "C" struct passwd *
+getpwent (void)
+{
+ return pwent.getpwent ();
}
extern "C" void
endpwent (void)
{
- _my_tls.locals.pw_pos = 0;
+ pwent.endpwent ();
}
+#ifndef __x86_64__
+extern "C" struct passwd *
+getpwduid (__uid16_t)
+{
+ return NULL;
+}
+#endif
+
extern "C" int
setpassent (int)
{
diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h
index 4ed245104..e59b2173b 100644
--- a/winsup/cygwin/pwdgrp.h
+++ b/winsup/cygwin/pwdgrp.h
@@ -23,6 +23,8 @@ extern struct group *internal_getgrnam (const char *);
int internal_getgroups (int, gid_t *, cygpsid * = NULL);
#include "sync.h"
+#include "ldap.h"
+#include "miscfuncs.h"
enum fetch_user_arg_type_t {
SID_arg,
@@ -56,6 +58,10 @@ struct pg_grp
class pwdgrp
{
+ friend class pg_ent;
+ friend class pw_ent;
+ friend class gr_ent;
+
unsigned pwdgrp_buf_elem_size;
void *pwdgrp_buf;
bool (pwdgrp::*parse) ();
@@ -87,7 +93,7 @@ class pwdgrp
i = (int) x;
return res;
}
- void *add_account_post_fetch (char *line);
+ void *add_account_post_fetch (char *line, bool lock);
void *add_account_from_file (cygpsid &sid);
void *add_account_from_file (const char *name);
void *add_account_from_file (uint32_t id);
@@ -103,6 +109,7 @@ class pwdgrp
public:
ULONG cached_users () const { return curr_lines; }
ULONG cached_groups () const { return curr_lines; }
+ POBJECT_ATTRIBUTES file_attr () { return &attr; }
bool check_file (bool group);
void init_pwd ();
@@ -141,3 +148,96 @@ public:
struct group *find_group (const char *name);
struct group *find_group (gid_t gid);
};
+
+enum nss_enum_t
+{
+ ENUM_NONE = 0x00,
+ ENUM_CACHE = 0x01,
+ ENUM_FILES = 0x02,
+ ENUM_BUILTIN = 0x04,
+ ENUM_LOCAL = 0x08,
+ ENUM_PRIMARY = 0x10,
+ ENUM_TDOMS = 0x20,
+ ENUM_TDOMS_ALL = 0x40,
+ ENUM_ALL = 0x7f
+};
+
+class pg_ent
+{
+protected:
+ pwdgrp pg;
+ bool group;
+ pg_pwd pwd;
+ pg_grp grp;
+ NT_readline rl;
+ cyg_ldap cldap;
+ PCHAR buf;
+ ULONG cnt;
+ ULONG max;
+ ULONG_PTR resume;
+ int enums;
+ PCWSTR enum_tdoms;
+ bool from_files;
+ bool from_db;
+ enum {
+ rewound = 0,
+ from_cache,
+ from_file,
+ from_builtin,
+ from_local,
+ from_sam,
+ from_ad,
+ finished
+ } state;
+
+ void clear_cache ();
+ inline bool nss_db_enum_caches () const { return !!(enums & ENUM_CACHE); }
+ inline bool nss_db_enum_files () const { return !!(enums & ENUM_FILES); }
+ inline bool nss_db_enum_builtin () const { return !!(enums & ENUM_BUILTIN); }
+ inline bool nss_db_enum_local () const { return !!(enums & ENUM_LOCAL); }
+ inline bool nss_db_enum_primary () const { return !!(enums & ENUM_PRIMARY); }
+ inline bool nss_db_enum_tdom (PWCHAR domain)
+ {
+ if (enums & ENUM_TDOMS_ALL)
+ return true;
+ if (!(enums & ENUM_TDOMS) || !enum_tdoms || !domain)
+ return false;
+ for (PCWSTR td = enum_tdoms; td && *td; td = wcschr (td, L'\0'))
+ if (!wcscasecmp (td, domain))
+ return true;
+ return false;
+ }
+ virtual void *enumerate_caches () = 0;
+ virtual void *enumerate_file ();
+ virtual void *enumerate_builtin ();
+ virtual void *enumerate_local () = 0;
+ virtual void *enumerate_sam ();
+ virtual void *enumerate_ad ();
+
+public:
+ void setent (bool _group, int _enums = 0, PCWSTR _enum_tdoms = NULL);
+ void *getent ();
+ void endent (bool _group);
+};
+
+class pw_ent : public pg_ent
+{
+ void *enumerate_caches ();
+ void *enumerate_local ();
+public:
+ inline void setpwent (int _enums = 0, PCWSTR _enum_tdoms = NULL)
+ { setent (false, _enums, _enum_tdoms); }
+ struct passwd *getpwent ();
+ inline void endpwent () { endent (false); }
+};
+
+class gr_ent : public pg_ent
+{
+ void *enumerate_caches ();
+ void *enumerate_local ();
+public:
+ inline void setgrent (int _enums = 0, PCWSTR _enum_tdoms = NULL)
+ { setent (true, _enums, _enum_tdoms); }
+ struct group *getgrent ();
+ inline void endgrent () { endent (true); }
+};
diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h
index df8ccfa11..8edc86c18 100644
--- a/winsup/cygwin/tlsoffsets.h
+++ b/winsup/cygwin/tlsoffsets.h
@@ -3,115 +3,115 @@
//; $tls::start_offset = -12700;
//; $tls::locals = -12700;
//; $tls::plocals = 0;
-//; $tls::local_clib = -11284;
-//; $tls::plocal_clib = 1416;
-//; $tls::__dontuse = -11284;
-//; $tls::p__dontuse = 1416;
-//; $tls::func = -10196;
-//; $tls::pfunc = 2504;
-//; $tls::saved_errno = -10192;
-//; $tls::psaved_errno = 2508;
-//; $tls::sa_flags = -10188;
-//; $tls::psa_flags = 2512;
-//; $tls::oldmask = -10184;
-//; $tls::poldmask = 2516;
-//; $tls::deltamask = -10180;
-//; $tls::pdeltamask = 2520;
-//; $tls::errno_addr = -10176;
-//; $tls::perrno_addr = 2524;
-//; $tls::sigmask = -10172;
-//; $tls::psigmask = 2528;
-//; $tls::sigwait_mask = -10168;
-//; $tls::psigwait_mask = 2532;
-//; $tls::sigwait_info = -10164;
-//; $tls::psigwait_info = 2536;
-//; $tls::signal_arrived = -10160;
-//; $tls::psignal_arrived = 2540;
-//; $tls::will_wait_for_signal = -10156;
-//; $tls::pwill_wait_for_signal = 2544;
-//; $tls::thread_context = -10152;
-//; $tls::pthread_context = 2548;
-//; $tls::thread_id = -9940;
-//; $tls::pthread_id = 2760;
-//; $tls::infodata = -9936;
-//; $tls::pinfodata = 2764;
-//; $tls::tid = -9788;
-//; $tls::ptid = 2912;
-//; $tls::_ctinfo = -9784;
-//; $tls::p_ctinfo = 2916;
-//; $tls::andreas = -9780;
-//; $tls::pandreas = 2920;
-//; $tls::wq = -9776;
-//; $tls::pwq = 2924;
-//; $tls::sig = -9748;
-//; $tls::psig = 2952;
-//; $tls::incyg = -9744;
-//; $tls::pincyg = 2956;
-//; $tls::spinning = -9740;
-//; $tls::pspinning = 2960;
-//; $tls::stacklock = -9736;
-//; $tls::pstacklock = 2964;
-//; $tls::stackptr = -9732;
-//; $tls::pstackptr = 2968;
-//; $tls::stack = -9728;
-//; $tls::pstack = 2972;
-//; $tls::initialized = -8704;
-//; $tls::pinitialized = 3996;
+//; $tls::local_clib = -11292;
+//; $tls::plocal_clib = 1408;
+//; $tls::__dontuse = -11292;
+//; $tls::p__dontuse = 1408;
+//; $tls::func = -10204;
+//; $tls::pfunc = 2496;
+//; $tls::saved_errno = -10200;
+//; $tls::psaved_errno = 2500;
+//; $tls::sa_flags = -10196;
+//; $tls::psa_flags = 2504;
+//; $tls::oldmask = -10192;
+//; $tls::poldmask = 2508;
+//; $tls::deltamask = -10188;
+//; $tls::pdeltamask = 2512;
+//; $tls::errno_addr = -10184;
+//; $tls::perrno_addr = 2516;
+//; $tls::sigmask = -10180;
+//; $tls::psigmask = 2520;
+//; $tls::sigwait_mask = -10176;
+//; $tls::psigwait_mask = 2524;
+//; $tls::sigwait_info = -10172;
+//; $tls::psigwait_info = 2528;
+//; $tls::signal_arrived = -10168;
+//; $tls::psignal_arrived = 2532;
+//; $tls::will_wait_for_signal = -10164;
+//; $tls::pwill_wait_for_signal = 2536;
+//; $tls::thread_context = -10160;
+//; $tls::pthread_context = 2540;
+//; $tls::thread_id = -9948;
+//; $tls::pthread_id = 2752;
+//; $tls::infodata = -9944;
+//; $tls::pinfodata = 2756;
+//; $tls::tid = -9796;
+//; $tls::ptid = 2904;
+//; $tls::_ctinfo = -9792;
+//; $tls::p_ctinfo = 2908;
+//; $tls::andreas = -9788;
+//; $tls::pandreas = 2912;
+//; $tls::wq = -9784;
+//; $tls::pwq = 2916;
+//; $tls::sig = -9756;
+//; $tls::psig = 2944;
+//; $tls::incyg = -9752;
+//; $tls::pincyg = 2948;
+//; $tls::spinning = -9748;
+//; $tls::pspinning = 2952;
+//; $tls::stacklock = -9744;
+//; $tls::pstacklock = 2956;
+//; $tls::stackptr = -9740;
+//; $tls::pstackptr = 2960;
+//; $tls::stack = -9736;
+//; $tls::pstack = 2964;
+//; $tls::initialized = -8712;
+//; $tls::pinitialized = 3988;
//; __DATA__
#define tls_locals (-12700)
#define tls_plocals (0)
-#define tls_local_clib (-11284)
-#define tls_plocal_clib (1416)
-#define tls___dontuse (-11284)
-#define tls_p__dontuse (1416)
-#define tls_func (-10196)
-#define tls_pfunc (2504)
-#define tls_saved_errno (-10192)
-#define tls_psaved_errno (2508)
-#define tls_sa_flags (-10188)
-#define tls_psa_flags (2512)
-#define tls_oldmask (-10184)
-#define tls_poldmask (2516)
-#define tls_deltamask (-10180)
-#define tls_pdeltamask (2520)
-#define tls_errno_addr (-10176)
-#define tls_perrno_addr (2524)
-#define tls_sigmask (-10172)
-#define tls_psigmask (2528)
-#define tls_sigwait_mask (-10168)
-#define tls_psigwait_mask (2532)
-#define tls_sigwait_info (-10164)
-#define tls_psigwait_info (2536)
-#define tls_signal_arrived (-10160)
-#define tls_psignal_arrived (2540)
-#define tls_will_wait_for_signal (-10156)
-#define tls_pwill_wait_for_signal (2544)
-#define tls_thread_context (-10152)
-#define tls_pthread_context (2548)
-#define tls_thread_id (-9940)
-#define tls_pthread_id (2760)
-#define tls_infodata (-9936)
-#define tls_pinfodata (2764)
-#define tls_tid (-9788)
-#define tls_ptid (2912)
-#define tls__ctinfo (-9784)
-#define tls_p_ctinfo (2916)
-#define tls_andreas (-9780)
-#define tls_pandreas (2920)
-#define tls_wq (-9776)
-#define tls_pwq (2924)
-#define tls_sig (-9748)
-#define tls_psig (2952)
-#define tls_incyg (-9744)
-#define tls_pincyg (2956)
-#define tls_spinning (-9740)
-#define tls_pspinning (2960)
-#define tls_stacklock (-9736)
-#define tls_pstacklock (2964)
-#define tls_stackptr (-9732)
-#define tls_pstackptr (2968)
-#define tls_stack (-9728)
-#define tls_pstack (2972)
-#define tls_initialized (-8704)
-#define tls_pinitialized (3996)
+#define tls_local_clib (-11292)
+#define tls_plocal_clib (1408)
+#define tls___dontuse (-11292)
+#define tls_p__dontuse (1408)
+#define tls_func (-10204)
+#define tls_pfunc (2496)
+#define tls_saved_errno (-10200)
+#define tls_psaved_errno (2500)
+#define tls_sa_flags (-10196)
+#define tls_psa_flags (2504)
+#define tls_oldmask (-10192)
+#define tls_poldmask (2508)
+#define tls_deltamask (-10188)
+#define tls_pdeltamask (2512)
+#define tls_errno_addr (-10184)
+#define tls_perrno_addr (2516)
+#define tls_sigmask (-10180)
+#define tls_psigmask (2520)
+#define tls_sigwait_mask (-10176)
+#define tls_psigwait_mask (2524)
+#define tls_sigwait_info (-10172)
+#define tls_psigwait_info (2528)
+#define tls_signal_arrived (-10168)
+#define tls_psignal_arrived (2532)
+#define tls_will_wait_for_signal (-10164)
+#define tls_pwill_wait_for_signal (2536)
+#define tls_thread_context (-10160)
+#define tls_pthread_context (2540)
+#define tls_thread_id (-9948)
+#define tls_pthread_id (2752)
+#define tls_infodata (-9944)
+#define tls_pinfodata (2756)
+#define tls_tid (-9796)
+#define tls_ptid (2904)
+#define tls__ctinfo (-9792)
+#define tls_p_ctinfo (2908)
+#define tls_andreas (-9788)
+#define tls_pandreas (2912)
+#define tls_wq (-9784)
+#define tls_pwq (2916)
+#define tls_sig (-9756)
+#define tls_psig (2944)
+#define tls_incyg (-9752)
+#define tls_pincyg (2948)
+#define tls_spinning (-9748)
+#define tls_pspinning (2952)
+#define tls_stacklock (-9744)
+#define tls_pstacklock (2956)
+#define tls_stackptr (-9740)
+#define tls_pstackptr (2960)
+#define tls_stack (-9736)
+#define tls_pstack (2964)
+#define tls_initialized (-8712)
+#define tls_pinitialized (3988)
diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h
index e966d4567..e04fca103 100644
--- a/winsup/cygwin/tlsoffsets64.h
+++ b/winsup/cygwin/tlsoffsets64.h
@@ -3,115 +3,115 @@
//; $tls::start_offset = -12800;
//; $tls::locals = -12800;
//; $tls::plocals = 0;
-//; $tls::local_clib = -11240;
-//; $tls::plocal_clib = 1560;
-//; $tls::__dontuse = -11240;
-//; $tls::p__dontuse = 1560;
-//; $tls::func = -9352;
-//; $tls::pfunc = 3448;
-//; $tls::saved_errno = -9344;
-//; $tls::psaved_errno = 3456;
-//; $tls::sa_flags = -9340;
-//; $tls::psa_flags = 3460;
-//; $tls::oldmask = -9336;
-//; $tls::poldmask = 3464;
-//; $tls::deltamask = -9328;
-//; $tls::pdeltamask = 3472;
-//; $tls::errno_addr = -9320;
-//; $tls::perrno_addr = 3480;
-//; $tls::sigmask = -9312;
-//; $tls::psigmask = 3488;
-//; $tls::sigwait_mask = -9304;
-//; $tls::psigwait_mask = 3496;
-//; $tls::sigwait_info = -9296;
-//; $tls::psigwait_info = 3504;
-//; $tls::signal_arrived = -9288;
-//; $tls::psignal_arrived = 3512;
-//; $tls::will_wait_for_signal = -9280;
-//; $tls::pwill_wait_for_signal = 3520;
-//; $tls::thread_context = -9272;
-//; $tls::pthread_context = 3528;
-//; $tls::thread_id = -8440;
-//; $tls::pthread_id = 4360;
-//; $tls::infodata = -8436;
-//; $tls::pinfodata = 4364;
-//; $tls::tid = -8288;
-//; $tls::ptid = 4512;
-//; $tls::_ctinfo = -8280;
-//; $tls::p_ctinfo = 4520;
-//; $tls::andreas = -8272;
-//; $tls::pandreas = 4528;
-//; $tls::wq = -8264;
-//; $tls::pwq = 4536;
-//; $tls::sig = -8216;
-//; $tls::psig = 4584;
-//; $tls::incyg = -8212;
-//; $tls::pincyg = 4588;
-//; $tls::spinning = -8208;
-//; $tls::pspinning = 4592;
-//; $tls::stacklock = -8204;
-//; $tls::pstacklock = 4596;
-//; $tls::stackptr = -8200;
-//; $tls::pstackptr = 4600;
-//; $tls::stack = -8192;
-//; $tls::pstack = 4608;
-//; $tls::initialized = -6144;
-//; $tls::pinitialized = 6656;
+//; $tls::local_clib = -11248;
+//; $tls::plocal_clib = 1552;
+//; $tls::__dontuse = -11248;
+//; $tls::p__dontuse = 1552;
+//; $tls::func = -9360;
+//; $tls::pfunc = 3440;
+//; $tls::saved_errno = -9352;
+//; $tls::psaved_errno = 3448;
+//; $tls::sa_flags = -9348;
+//; $tls::psa_flags = 3452;
+//; $tls::oldmask = -9344;
+//; $tls::poldmask = 3456;
+//; $tls::deltamask = -9336;
+//; $tls::pdeltamask = 3464;
+//; $tls::errno_addr = -9328;
+//; $tls::perrno_addr = 3472;
+//; $tls::sigmask = -9320;
+//; $tls::psigmask = 3480;
+//; $tls::sigwait_mask = -9312;
+//; $tls::psigwait_mask = 3488;
+//; $tls::sigwait_info = -9304;
+//; $tls::psigwait_info = 3496;
+//; $tls::signal_arrived = -9296;
+//; $tls::psignal_arrived = 3504;
+//; $tls::will_wait_for_signal = -9288;
+//; $tls::pwill_wait_for_signal = 3512;
+//; $tls::thread_context = -9280;
+//; $tls::pthread_context = 3520;
+//; $tls::thread_id = -8448;
+//; $tls::pthread_id = 4352;
+//; $tls::infodata = -8444;
+//; $tls::pinfodata = 4356;
+//; $tls::tid = -8296;
+//; $tls::ptid = 4504;
+//; $tls::_ctinfo = -8288;
+//; $tls::p_ctinfo = 4512;
+//; $tls::andreas = -8280;
+//; $tls::pandreas = 4520;
+//; $tls::wq = -8272;
+//; $tls::pwq = 4528;
+//; $tls::sig = -8224;
+//; $tls::psig = 4576;
+//; $tls::incyg = -8220;
+//; $tls::pincyg = 4580;
+//; $tls::spinning = -8216;
+//; $tls::pspinning = 4584;
+//; $tls::stacklock = -8212;
+//; $tls::pstacklock = 4588;
+//; $tls::stackptr = -8208;
+//; $tls::pstackptr = 4592;
+//; $tls::stack = -8200;
+//; $tls::pstack = 4600;
+//; $tls::initialized = -6152;
+//; $tls::pinitialized = 6648;
//; __DATA__
#define tls_locals (-12800)
#define tls_plocals (0)
-#define tls_local_clib (-11240)
-#define tls_plocal_clib (1560)
-#define tls___dontuse (-11240)
-#define tls_p__dontuse (1560)
-#define tls_func (-9352)
-#define tls_pfunc (3448)
-#define tls_saved_errno (-9344)
-#define tls_psaved_errno (3456)
-#define tls_sa_flags (-9340)
-#define tls_psa_flags (3460)
-#define tls_oldmask (-9336)
-#define tls_poldmask (3464)
-#define tls_deltamask (-9328)
-#define tls_pdeltamask (3472)
-#define tls_errno_addr (-9320)
-#define tls_perrno_addr (3480)
-#define tls_sigmask (-9312)
-#define tls_psigmask (3488)
-#define tls_sigwait_mask (-9304)
-#define tls_psigwait_mask (3496)
-#define tls_sigwait_info (-9296)
-#define tls_psigwait_info (3504)
-#define tls_signal_arrived (-9288)
-#define tls_psignal_arrived (3512)
-#define tls_will_wait_for_signal (-9280)
-#define tls_pwill_wait_for_signal (3520)
-#define tls_thread_context (-9272)
-#define tls_pthread_context (3528)
-#define tls_thread_id (-8440)
-#define tls_pthread_id (4360)
-#define tls_infodata (-8436)
-#define tls_pinfodata (4364)
-#define tls_tid (-8288)
-#define tls_ptid (4512)
-#define tls__ctinfo (-8280)
-#define tls_p_ctinfo (4520)
-#define tls_andreas (-8272)
-#define tls_pandreas (4528)
-#define tls_wq (-8264)
-#define tls_pwq (4536)
-#define tls_sig (-8216)
-#define tls_psig (4584)
-#define tls_incyg (-8212)
-#define tls_pincyg (4588)
-#define tls_spinning (-8208)
-#define tls_pspinning (4592)
-#define tls_stacklock (-8204)
-#define tls_pstacklock (4596)
-#define tls_stackptr (-8200)
-#define tls_pstackptr (4600)
-#define tls_stack (-8192)
-#define tls_pstack (4608)
-#define tls_initialized (-6144)
-#define tls_pinitialized (6656)
+#define tls_local_clib (-11248)
+#define tls_plocal_clib (1552)
+#define tls___dontuse (-11248)
+#define tls_p__dontuse (1552)
+#define tls_func (-9360)
+#define tls_pfunc (3440)
+#define tls_saved_errno (-9352)
+#define tls_psaved_errno (3448)
+#define tls_sa_flags (-9348)
+#define tls_psa_flags (3452)
+#define tls_oldmask (-9344)
+#define tls_poldmask (3456)
+#define tls_deltamask (-9336)
+#define tls_pdeltamask (3464)
+#define tls_errno_addr (-9328)
+#define tls_perrno_addr (3472)
+#define tls_sigmask (-9320)
+#define tls_psigmask (3480)
+#define tls_sigwait_mask (-9312)
+#define tls_psigwait_mask (3488)
+#define tls_sigwait_info (-9304)
+#define tls_psigwait_info (3496)
+#define tls_signal_arrived (-9296)
+#define tls_psignal_arrived (3504)
+#define tls_will_wait_for_signal (-9288)
+#define tls_pwill_wait_for_signal (3512)
+#define tls_thread_context (-9280)
+#define tls_pthread_context (3520)
+#define tls_thread_id (-8448)
+#define tls_pthread_id (4352)
+#define tls_infodata (-8444)
+#define tls_pinfodata (4356)
+#define tls_tid (-8296)
+#define tls_ptid (4504)
+#define tls__ctinfo (-8288)
+#define tls_p_ctinfo (4512)
+#define tls_andreas (-8280)
+#define tls_pandreas (4520)
+#define tls_wq (-8272)
+#define tls_pwq (4528)
+#define tls_sig (-8224)
+#define tls_psig (4576)
+#define tls_incyg (-8220)
+#define tls_pincyg (4580)
+#define tls_spinning (-8216)
+#define tls_pspinning (4584)
+#define tls_stacklock (-8212)
+#define tls_pstacklock (4588)
+#define tls_stackptr (-8208)
+#define tls_pstackptr (4592)
+#define tls_stack (-8200)
+#define tls_pstack (4600)
+#define tls_initialized (-6152)
+#define tls_pinitialized (6648)
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 5a0177b82..be7bd34f2 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -562,15 +562,18 @@ cygheap_pwdgrp::init ()
db_prefix: auto
db_cache: yes
db_separator: +
+ db_enum: cache builtin
*/
pwd_src = (NSS_FILES | NSS_DB);
grp_src = (NSS_FILES | NSS_DB);
prefix = NSS_AUTO;
separator[0] = L'+';
caching = true;
+ enums = (ENUM_CACHE | ENUM_BUILTIN);
+ enum_tdoms = NULL;
}
-/* The /etc/nssswitch.conf file is read exactly once by the root process of a
+/* The /etc/nsswitch.conf file is read exactly once by the root process of a
process tree. We can't afford methodical changes during the lifetime of a
process tree. */
void
@@ -662,6 +665,58 @@ cygheap_pwdgrp::nss_init_line (const char *line)
else
debug_printf ("Invalid nsswitch.conf content: %s", line);
}
+ else if (!strncmp (c, "enum:", 5))
+ {
+ tmp_pathbuf tp;
+ char *tdoms = tp.c_get ();
+ char *td = tdoms;
+ int new_enums = ENUM_NONE;
+
+ td[0] = '\0';
+ c += 5;
+ c += strspn (c, " \t");
+ while (!strchr (" \t", *c))
+ {
+ const char *e = c + strcspn (c, " \t");
+ if (!strncmp (c, "none", 4) && strchr (" \t", c[4]))
+ new_enums = ENUM_NONE;
+ else if (!strncmp (c, "builtin", 7) && strchr (" \t", c[7]))
+ new_enums |= ENUM_BUILTIN;
+ else if (!strncmp (c, "cache", 5) && strchr (" \t", c[5]))
+ new_enums |= ENUM_CACHE;
+ else if (!strncmp (c, "files", 5) && strchr (" \t", c[5]))
+ new_enums |= ENUM_FILES;
+ else if (!strncmp (c, "local", 5) && strchr (" \t", c[5]))
+ new_enums |= ENUM_LOCAL;
+ else if (!strncmp (c, "primary", 7) && strchr (" \t", c[7]))
+ new_enums |= ENUM_PRIMARY;
+ else if (!strncmp (c, "alltrusted", 10) && strchr (" \t", c[10]))
+ new_enums |= ENUM_TDOMS | ENUM_TDOMS_ALL;
+ else if (!strncmp (c, "all", 3) && strchr (" \t", c[3]))
+ new_enums |= ENUM_ALL;
+ else
+ {
+ td = stpcpy (stpncpy (td, c, e - c), " ");
+ new_enums |= ENUM_TDOMS;
+ }
+ c = e;
+ c += strspn (c, " \t");
+ }
+ if ((new_enums & (ENUM_TDOMS | ENUM_TDOMS_ALL)) == ENUM_TDOMS)
+ {
+ if (td > tdoms)
+ {
+ PWCHAR spc;
+ sys_mbstowcs_alloc (&enum_tdoms, HEAP_BUF, tdoms);
+ /* Convert string to REG_MULTI_SZ-style. */
+ while ((spc = wcsrchr (enum_tdoms, L' ')))
+ *spc = L'\0';
+ }
+ else
+ new_enums &= ~(ENUM_TDOMS | ENUM_TDOMS_ALL);
+ }
+ enums = new_enums;
+ }
break;
case '\0':
case '#':
@@ -867,15 +922,17 @@ get_logon_sid ()
}
void *
-pwdgrp::add_account_post_fetch (char *line)
+pwdgrp::add_account_post_fetch (char *line, bool lock)
{
if (line)
{
void *ret;
- pglock.init ("pglock")->acquire ();
+ if (lock)
+ pglock.init ("pglock")->acquire ();
add_line (line);
ret = ((char *) pwdgrp_buf) + (curr_lines - 1) * pwdgrp_buf_elem_size;
- pglock.release ();
+ if (lock)
+ pglock.release ();
return ret;
}
return NULL;
@@ -890,7 +947,7 @@ pwdgrp::add_account_from_file (cygpsid &sid)
arg.type = SID_arg;
arg.sid = &sid;
char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line);
+ return (struct passwd *) add_account_post_fetch (line, true);
}
void *
@@ -902,7 +959,7 @@ pwdgrp::add_account_from_file (const char *name)
arg.type = NAME_arg;
arg.name = name;
char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line);
+ return (struct passwd *) add_account_post_fetch (line, true);
}
void *
@@ -914,7 +971,7 @@ pwdgrp::add_account_from_file (uint32_t id)
arg.type = ID_arg;
arg.id = id;
char *line = fetch_account_from_file (arg);
- return (struct passwd *) add_account_post_fetch (line);
+ return (struct passwd *) add_account_post_fetch (line, true);
}
void *
@@ -927,8 +984,8 @@ pwdgrp::add_account_from_windows (cygpsid &sid, bool group)
if (!line)
return NULL;
if (cygheap->pg.nss_db_caching ())
- return add_account_post_fetch (line);
- return (prep_tls_pwbuf ())->add_account_post_fetch (line);
+ return add_account_post_fetch (line, true);
+ return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}
void *
@@ -941,8 +998,8 @@ pwdgrp::add_account_from_windows (const char *name, bool group)
if (!line)
return NULL;
if (cygheap->pg.nss_db_caching ())
- return add_account_post_fetch (line);
- return (prep_tls_pwbuf ())->add_account_post_fetch (line);
+ return add_account_post_fetch (line, true);
+ return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}
void *
@@ -955,8 +1012,8 @@ pwdgrp::add_account_from_windows (uint32_t id, bool group)
if (!line)
return NULL;
if (cygheap->pg.nss_db_caching ())
- return add_account_post_fetch (line);
- return (prep_tls_pwbuf ())->add_account_post_fetch (line);
+ return add_account_post_fetch (line, true);
+ return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}
/* Check if file exists and if it has been written to since last checked.
@@ -1149,6 +1206,28 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
case SID_arg:
sid = *arg.sid;
ret = LookupAccountSidW (NULL, sid, name, &nlen, dom, &dlen, &acc_type);
+ if (!ret
+ && cygheap->dom.member_machine ()
+ && sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
+ && sid_sub_auth (sid, 0) == SECURITY_BUILTIN_DOMAIN_RID)
+ {
+ /* LookupAccountSid called on a non-DC cannot resolve aliases which
+ are not defined in the local SAM. If we encounter an alias which
+ can't be resolved, and if we're a domain member machine, ask a DC.
+ Do *not* use LookupAccountSidW. It can take ages when called on a
+ DC for some weird reason. Use LDAP instead. */
+ PWCHAR val;
+
+ if ((ldap_open = cldap.open (NULL))
+ && cldap.fetch_ad_account (sid, group)
+ && (val = cldap.get_group_name ()))
+ {
+ wcpcpy (name, val);
+ wcpcpy (dom, L"BUILTIN");
+ acc_type = SidTypeAlias;
+ ret = true;
+ }
+ }
if (!ret)
debug_printf ("LookupAccountSid(%W), %E", sid.string (sidstr));
break;
@@ -1478,7 +1557,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
/* Set comment variable for below attribute loop. */
comment = ui->usri4_comment;
}
- else /* SidTypeGroup || SidTypeAlias */
+ else if (acc_type == SidTypeAlias)
{
nas = NetLocalGroupGetInfo (NULL, name, 1, (PBYTE *) &gi);
if (nas != NERR_Success)
@@ -1489,6 +1568,8 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group)
/* Set comment variable for below attribute loop. */
comment = gi->lgrpi1_comment;
}
+ else /* SidTypeGroup. No way to add a comment to "None" :( */
+ break;
/* Local SAM accounts have only a handful attributes
available to home users. Therefore, fetch additional
passwd/group attributes from the "Description" field