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 + + * 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 * 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 #include #include #include @@ -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,29 +313,102 @@ getgrnam (const char *name) } #endif -extern "C" void -endgrent () +/* getgrent functions are not reentrant. */ +static gr_ent grent; + +void * +gr_ent::enumerate_caches () { - _my_tls.locals.grp_pos = 0; + if (!max && from_files) + { + 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 (from_db && cygheap->pg.nss_db_caching ()) + { + pwdgrp &grw = cygheap->pg.grp_cache.win; + 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 () +getgrent32 (void) { - pwdgrp &grf = cygheap->pg.grp_cache.file; - if (cygheap->pg.nss_grp_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; - } - if ((cygheap->pg.nss_grp_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; - } - return NULL; + return grent.getgrent (); } #ifdef __x86_64__ @@ -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 #include #include #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,23 +279,365 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s return 0; } +/* getpwent functions are not reentrant. */ +static pw_ent pwent; + +void +pg_ent::clear_cache () +{ + if (pg.curr_lines) + { + 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 (); + } + 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 (cnt < prw.cached_users ()) + return &prw.passwd ()[cnt++].p; + } + cnt = max = 0; + return NULL; +} + +void * +pw_ent::enumerate_local () +{ + return NULL; +} + +struct passwd * +pw_ent::getpwent (void) +{ + if (state == rewound) + setent (false); + else + clear_cache (); + return (struct passwd *) getent (); +} + +extern "C" void +setpwent () +{ + pwent.setpwent (); +} + extern "C" struct passwd * getpwent (void) { - pwdgrp &prf = cygheap->pg.pwd_cache.file; - if (cygheap->pg.nss_pwd_files ()) - { - 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 ((cygheap->pg.nss_pwd_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; - } - return NULL; + return pwent.getpwent (); +} + +extern "C" void +endpwent (void) +{ + pwent.endpwent (); } #ifndef __x86_64__ @@ -302,18 +648,6 @@ getpwduid (__uid16_t) } #endif -extern "C" void -setpwent (void) -{ - _my_tls.locals.pw_pos = 0; -} - -extern "C" void -endpwent (void) -{ - _my_tls.locals.pw_pos = 0; -} - 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