Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-02-17 19:36:33 +0400
committerCorinna Vinschen <corinna@vinschen.de>2014-02-17 19:36:33 +0400
commita8cf6887a2ea00524ebf330eb50a05cf8e67bc5c (patch)
tree63b01096a3b6deb0afe5fdfddc43ec5ddd1487c6 /winsup/cygwin/passwd.cc
parent1e705e29329a0bca000bfb1f199042ffedfe477b (diff)
* 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.cc368
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)
{