diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2014-02-17 15:36:33 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2014-02-17 15:36:33 +0000 |
commit | a8cf6887a2ea00524ebf330eb50a05cf8e67bc5c (patch) | |
tree | 63b01096a3b6deb0afe5fdfddc43ec5ddd1487c6 /winsup/cygwin/passwd.cc | |
parent | 1e705e29329a0bca000bfb1f199042ffedfe477b (diff) | |
download | cygnal-a8cf6887a2ea00524ebf330eb50a05cf8e67bc5c.tar.gz cygnal-a8cf6887a2ea00524ebf330eb50a05cf8e67bc5c.tar.bz2 cygnal-a8cf6887a2ea00524ebf330eb50a05cf8e67bc5c.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r-- | winsup/cygwin/passwd.cc | 368 |
1 files changed, 351 insertions, 17 deletions
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) { |