Skip to content

Commit

Permalink
* cygheap.h (cygheap_user::sid): Return reference to cygpsid rather
Browse files Browse the repository at this point in the history
	than PSID.
	(cygheap_user::saved_sid): Ditto.
	(cygheap_pwdgrp::cache_t): New type.
	(cygheap_pwdgrp::caching): Convert to cache_t.
	(cygheap_pwdgrp::nss_db_caching): Change accordingly.
	(cygheap_pwdgrp::nss_db_full_caching): New inline method.
	* grp.cc (internal_getgroups): Reinvent.  Take cyg_ldap pointer as
	third parameter and use throughout.
	(getgroups32): Call internal_getgroups.
	* pwdgrp.h (internal_getgroups): Declare.
	* uinfo.cc (internal_getlogin): Partial rewrite to accommodate having
	no connection to the DC.  Give primary group from user token more
	weight.  Generate group entries for all groups in the user token if
	caching is set to NSS_FULL_CACHING.
	(cygheap_pwdgrp::init): Initialize caching to NSS_FULL_CACHING.
	(cygheap_pwdgrp::nss_init_line): Handle "db_cache: full".
	(pwdgrp::add_account_from_windows): Fix group handling in non-caching
	mode.
	(pwdgrp::fetch_account_from_windows): Default primary group for the
	current user to primary group from user token.  Check for primary
	domain first after LookupAccountSid failed.
  • Loading branch information
github-cygwin committed Feb 28, 2014
1 parent b39fa2c commit 6cc7c92
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 59 deletions.
25 changes: 25 additions & 0 deletions winsup/cygwin/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
2014-02-28 Corinna Vinschen <[email protected]>

* cygheap.h (cygheap_user::sid): Return reference to cygpsid rather
than PSID.
(cygheap_user::saved_sid): Ditto.
(cygheap_pwdgrp::cache_t): New type.
(cygheap_pwdgrp::caching): Convert to cache_t.
(cygheap_pwdgrp::nss_db_caching): Change accordingly.
(cygheap_pwdgrp::nss_db_full_caching): New inline method.
* grp.cc (internal_getgroups): Reinvent. Take cyg_ldap pointer as
third parameter and use throughout.
(getgroups32): Call internal_getgroups.
* pwdgrp.h (internal_getgroups): Declare.
* uinfo.cc (internal_getlogin): Partial rewrite to accommodate having
no connection to the DC. Give primary group from user token more
weight. Generate group entries for all groups in the user token if
caching is set to NSS_FULL_CACHING.
(cygheap_pwdgrp::init): Initialize caching to NSS_FULL_CACHING.
(cygheap_pwdgrp::nss_init_line): Handle "db_cache: full".
(pwdgrp::add_account_from_windows): Fix group handling in non-caching
mode.
(pwdgrp::fetch_account_from_windows): Default primary group for the
current user to primary group from user token. Check for primary
domain first after LookupAccountSid failed.

2014-02-27 Corinna Vinschen <[email protected]>

* autoload.cc (CheckTokenMembership): Import.
Expand Down
29 changes: 18 additions & 11 deletions winsup/cygwin/cygheap.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ class cygheap_user
}
void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
void set_saved_sid () { saved_cygsid = effec_cygsid; }
PSID sid () { return effec_cygsid; }
PSID saved_sid () { return saved_cygsid; }
cygpsid &sid () { return effec_cygsid; }
cygpsid &saved_sid () { return saved_cygsid; }
const char *ontherange (homebodies what, struct passwd * = NULL);
#define NO_IMPERSONATION NULL
bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
Expand Down Expand Up @@ -400,14 +400,19 @@ class cygheap_pwdgrp
NSS_PRIMARY,
NSS_ALWAYS
};
bool nss_inited;
int pwd_src;
int grp_src;
pfx_t prefix;
WCHAR separator[2];
bool caching;
int enums;
PWCHAR enum_tdoms;
enum cache_t {
NSS_NO_CACHING = 0,
NSS_CACHING,
NSS_FULL_CACHING
};
bool nss_inited;
int pwd_src;
int grp_src;
pfx_t prefix;
WCHAR separator[2];
cache_t caching;
int enums;
PWCHAR enum_tdoms;

void nss_init_line (const char *line);
void _nss_init ();
Expand All @@ -433,7 +438,9 @@ class cygheap_pwdgrp
inline bool nss_prefix_primary () const { return prefix == NSS_PRIMARY; }
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 bool nss_db_caching () const { return caching != NSS_NO_CACHING; }
inline bool nss_db_full_caching () const
{ return caching == NSS_FULL_CACHING; }
inline int nss_db_enums () const { return enums; }
inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
};
Expand Down
17 changes: 12 additions & 5 deletions winsup/cygwin/grp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -459,21 +459,20 @@ endgrent_filtered (void *gr)
((gr_ent *) gr)->endgrent ();
}

extern "C" int
getgroups32 (int gidsetsize, gid_t *grouplist)
int
internal_getgroups (int gidsetsize, gid_t *grouplist, cyg_ldap *pldap)
{
NTSTATUS status;
HANDLE tok;
ULONG size;
int cnt = 0;
struct group *grp;
cyg_ldap cldap;

if (cygheap->user.groups.issetgroups ())
{
for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg],
&cldap)))
pldap)))
{
if (cnt < gidsetsize)
grouplist[cnt] = grp->gr_gid;
Expand All @@ -500,7 +499,7 @@ getgroups32 (int gidsetsize, gid_t *grouplist)
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
{
cygpsid sid = groups->Groups[pg].Sid;
if ((grp = internal_getgrsid (sid, &cldap)))
if ((grp = internal_getgrsid (sid, pldap)))
{
if ((groups->Groups[pg].Attributes
& (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
Expand All @@ -525,6 +524,14 @@ getgroups32 (int gidsetsize, gid_t *grouplist)
return -1;
}

extern "C" int
getgroups32 (int gidsetsize, gid_t *grouplist)
{
cyg_ldap cldap;

return internal_getgroups (gidsetsize, grouplist, &cldap);
}

#ifdef __x86_64__
EXPORT_ALIAS (getgroups32, getgroups)
#else
Expand Down
2 changes: 2 additions & 0 deletions winsup/cygwin/pwdgrp.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ extern struct group *internal_getgrsid_from_db (cygpsid &sid);
extern struct group *internal_getgrgid (gid_t, cyg_ldap * = NULL);
extern struct group *internal_getgrnam (const char *, cyg_ldap * = NULL);

extern int internal_getgroups (int, gid_t *, cyg_ldap *);

/* These functions are called from mkpasswd/mkgroup via cygwin_internal. */
void *setpwent_filtered (int enums, PCWSTR enum_tdoms);
void *getpwent_filtered (void *gr);
Expand Down
124 changes: 81 additions & 43 deletions winsup/cygwin/uinfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,48 +116,63 @@ cygheap_user::init ()
void
internal_getlogin (cygheap_user &user)
{
struct passwd *pw = NULL;
struct group *gr, *gr2;
struct passwd *pwd;
struct group *pgrp, *grp, *grp2;
cyg_ldap cldap;

cygpsid psid = user.sid ();
pw = internal_getpwsid (psid, &cldap);

if (!pw && !(pw = internal_getpwnam (user.name (), &cldap)))
debug_printf ("user not found in /etc/passwd");
/* Fetch (and potentially generate) passwd and group entries for the user
and the primary group in the token. */
pwd = internal_getpwsid (user.sid (), &cldap);
pgrp = internal_getgrsid (user.groups.pgsid, &cldap);
if (cygheap->pg.nss_db_full_caching ())
internal_getgroups (0, NULL, &cldap);
if (!pwd)
debug_printf ("user not found in passwd DB");
else
{
cygsid gsid;

myself->uid = pw->pw_uid;
myself->gid = pw->pw_gid;
user.set_name (pw->pw_name);
if (gsid.getfromgr (gr = internal_getgrgid (pw->pw_gid, &cldap)))
user.set_name (pwd->pw_name);
myself->uid = pwd->pw_uid;
myself->gid = pwd->pw_gid;
/* Is the primary group in the passwd DB is different from the primary
group in the user token, we have to find the SID of that group and
try to override the token primary group. */
if (!pgrp || myself->gid != pgrp->gr_gid)
{
/* We might have a group file with a group entry for the current
user's primary group, but the current user has no entry in passwd.
If so, pw_gid is taken from windows and might disagree with the
gr_gid from the group file. Overwrite it brutally. */
if ((gr2 = internal_getgrsid (gsid, &cldap)) && gr2 != gr)
myself->gid = pw->pw_gid = gr2->gr_gid;
/* Set primary group to the group in /etc/passwd. */
if (gsid != user.groups.pgsid)
if (gsid.getfromgr (grp = internal_getgrgid (pwd->pw_gid, &cldap)))
{
NTSTATUS status = NtSetInformationToken (hProcToken,
TokenPrimaryGroup,
&gsid, sizeof gsid);
if (!NT_SUCCESS (status))
debug_printf ("NtSetInformationToken (TokenPrimaryGroup), %y",
status);
else
user.groups.pgsid = gsid;
clear_procimptoken ();
/* We might have a group file with a group entry for the current
user's primary group, but the current user has no entry in
passwd. If so, pw_gid is taken from windows and might
disagree with gr_gid from the group file. Overwrite it. */
if ((grp2 = internal_getgrsid (gsid, &cldap)) && grp2 != grp)
myself->gid = pwd->pw_gid = grp2->gr_gid;
/* Set primary group to the group in /etc/passwd. */
if (gsid != user.groups.pgsid)
{
NTSTATUS status = NtSetInformationToken (hProcToken,
TokenPrimaryGroup,
&gsid, sizeof gsid);
if (!NT_SUCCESS (status))
{
debug_printf ("NtSetInformationToken (TokenPrimaryGroup),"
" %y", status);
/* Revert the primary group setting and override the
setting in the passwd entry. */
if (pgrp)
myself->gid = pwd->pw_gid = pgrp->gr_gid;
}
else
user.groups.pgsid = gsid;
clear_procimptoken ();
}
}
else
debug_printf ("group not found in group DB");
}
else
debug_printf ("gsid not found in augmented /etc/group");
}
cygheap->user.ontherange (CH_HOME, pw);
cygheap->user.ontherange (CH_HOME, pwd);
}

void
Expand Down Expand Up @@ -569,7 +584,7 @@ cygheap_pwdgrp::init ()
grp_src = (NSS_FILES | NSS_DB);
prefix = NSS_AUTO;
separator[0] = L'+';
caching = true;
caching = NSS_FULL_CACHING;
enums = (ENUM_CACHE | ENUM_BUILTIN);
enum_tdoms = NULL;
}
Expand Down Expand Up @@ -659,10 +674,12 @@ cygheap_pwdgrp::nss_init_line (const char *line)
{
c += 6;
c += strspn (c, " \t");
if (!strncmp (c, "yes", 3) && strchr (" \t", c[3]))
caching = true;
if (!strncmp (c, "full", 3) && strchr (" \t", c[3]))
caching = NSS_FULL_CACHING;
else if (!strncmp (c, "yes", 3) && strchr (" \t", c[3]))
caching = NSS_CACHING;
else if (!strncmp (c, "no", 2) && strchr (" \t", c[2]))
caching = false;
caching = NSS_NO_CACHING;
else
debug_printf ("Invalid nsswitch.conf content: %s", line);
}
Expand Down Expand Up @@ -986,6 +1003,8 @@ pwdgrp::add_account_from_windows (cygpsid &sid, bool group, cyg_ldap *pldap)
return NULL;
if (cygheap->pg.nss_db_caching ())
return add_account_post_fetch (line, true);
if (group)
return (prep_tls_grbuf ())->add_account_post_fetch (line, false);
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}

Expand All @@ -1000,6 +1019,8 @@ pwdgrp::add_account_from_windows (const char *name, bool group, cyg_ldap *pldap)
return NULL;
if (cygheap->pg.nss_db_caching ())
return add_account_post_fetch (line, true);
if (group)
return (prep_tls_grbuf ())->add_account_post_fetch (line, false);
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}

Expand All @@ -1014,6 +1035,8 @@ pwdgrp::add_account_from_windows (uint32_t id, bool group, cyg_ldap *pldap)
return NULL;
if (cygheap->pg.nss_db_caching ())
return add_account_post_fetch (line, true);
if (group)
return (prep_tls_grbuf ())->add_account_post_fetch (line, false);
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
}

Expand Down Expand Up @@ -1481,7 +1504,16 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group,
if (acc_type != SidTypeUser)
break;

gid = posix_offset + DOMAIN_GROUP_RID_USERS; /* Default. */
/* Default primary group. If the sid is the current user, fetch
the default group from the current user token, otherwise make
the educated guess that the user is in group "Domain Users"
or "None". */
if (sid == cygheap->user.sid ())
gid = posix_offset
+ sid_sub_auth_rid (cygheap->user.groups.pgsid);
else
gid = posix_offset + DOMAIN_GROUP_RID_USERS;

/* Use LDAP to fetch domain account infos. */
if (!cldap->open (NULL))
break;
Expand Down Expand Up @@ -1724,13 +1756,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group,
PDS_DOMAIN_TRUSTSW td = NULL;

sid_sub_auth_count (sid) = sid_sub_auth_count (sid) - 1;
for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
{
domain = td->NetbiosDomainName;
posix_offset = fetch_posix_offset (td, cldap);
break;
}
if (RtlEqualSid (sid, cygheap->dom.primary_sid ()))
{
domain = cygheap->dom.primary_flat_name ();
posix_offset = 0x100000;
}
else
for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
{
domain = td->NetbiosDomainName;
posix_offset = fetch_posix_offset (td, cldap);
break;
}
}
if (domain)
{
Expand Down

0 comments on commit 6cc7c92

Please sign in to comment.