* 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.
This commit is contained in:
Corinna Vinschen
2014-02-17 15:36:33 +00:00
parent 1e705e2932
commit a8cf6887a2
12 changed files with 1072 additions and 294 deletions

View File

@ -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,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)
{