* 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.
This commit is contained in:
parent
b39fa2c88d
commit
6cc7c925ce
|
@ -1,3 +1,28 @@
|
||||||
|
2014-02-28 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* 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 <corinna@vinschen.de>
|
2014-02-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* autoload.cc (CheckTokenMembership): Import.
|
* autoload.cc (CheckTokenMembership): Import.
|
||||||
|
|
|
@ -156,8 +156,8 @@ public:
|
||||||
}
|
}
|
||||||
void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
|
void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
|
||||||
void set_saved_sid () { saved_cygsid = effec_cygsid; }
|
void set_saved_sid () { saved_cygsid = effec_cygsid; }
|
||||||
PSID sid () { return effec_cygsid; }
|
cygpsid &sid () { return effec_cygsid; }
|
||||||
PSID saved_sid () { return saved_cygsid; }
|
cygpsid &saved_sid () { return saved_cygsid; }
|
||||||
const char *ontherange (homebodies what, struct passwd * = NULL);
|
const char *ontherange (homebodies what, struct passwd * = NULL);
|
||||||
#define NO_IMPERSONATION NULL
|
#define NO_IMPERSONATION NULL
|
||||||
bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
|
bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
|
||||||
|
@ -400,12 +400,17 @@ class cygheap_pwdgrp
|
||||||
NSS_PRIMARY,
|
NSS_PRIMARY,
|
||||||
NSS_ALWAYS
|
NSS_ALWAYS
|
||||||
};
|
};
|
||||||
|
enum cache_t {
|
||||||
|
NSS_NO_CACHING = 0,
|
||||||
|
NSS_CACHING,
|
||||||
|
NSS_FULL_CACHING
|
||||||
|
};
|
||||||
bool nss_inited;
|
bool nss_inited;
|
||||||
int pwd_src;
|
int pwd_src;
|
||||||
int grp_src;
|
int grp_src;
|
||||||
pfx_t prefix;
|
pfx_t prefix;
|
||||||
WCHAR separator[2];
|
WCHAR separator[2];
|
||||||
bool caching;
|
cache_t caching;
|
||||||
int enums;
|
int enums;
|
||||||
PWCHAR enum_tdoms;
|
PWCHAR enum_tdoms;
|
||||||
|
|
||||||
|
@ -433,7 +438,9 @@ public:
|
||||||
inline bool nss_prefix_primary () const { return prefix == NSS_PRIMARY; }
|
inline bool nss_prefix_primary () const { return prefix == NSS_PRIMARY; }
|
||||||
inline bool nss_prefix_always () const { return prefix == NSS_ALWAYS; }
|
inline bool nss_prefix_always () const { return prefix == NSS_ALWAYS; }
|
||||||
inline PCWSTR nss_separator () const { return separator; }
|
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 int nss_db_enums () const { return enums; }
|
||||||
inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
|
inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -459,21 +459,20 @@ endgrent_filtered (void *gr)
|
||||||
((gr_ent *) gr)->endgrent ();
|
((gr_ent *) gr)->endgrent ();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
int
|
||||||
getgroups32 (int gidsetsize, gid_t *grouplist)
|
internal_getgroups (int gidsetsize, gid_t *grouplist, cyg_ldap *pldap)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
HANDLE tok;
|
HANDLE tok;
|
||||||
ULONG size;
|
ULONG size;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
cyg_ldap cldap;
|
|
||||||
|
|
||||||
if (cygheap->user.groups.issetgroups ())
|
if (cygheap->user.groups.issetgroups ())
|
||||||
{
|
{
|
||||||
for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
|
for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
|
||||||
if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg],
|
if ((grp = internal_getgrsid (cygheap->user.groups.sgsids.sids[pg],
|
||||||
&cldap)))
|
pldap)))
|
||||||
{
|
{
|
||||||
if (cnt < gidsetsize)
|
if (cnt < gidsetsize)
|
||||||
grouplist[cnt] = grp->gr_gid;
|
grouplist[cnt] = grp->gr_gid;
|
||||||
|
@ -500,7 +499,7 @@ getgroups32 (int gidsetsize, gid_t *grouplist)
|
||||||
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
|
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
|
||||||
{
|
{
|
||||||
cygpsid sid = groups->Groups[pg].Sid;
|
cygpsid sid = groups->Groups[pg].Sid;
|
||||||
if ((grp = internal_getgrsid (sid, &cldap)))
|
if ((grp = internal_getgrsid (sid, pldap)))
|
||||||
{
|
{
|
||||||
if ((groups->Groups[pg].Attributes
|
if ((groups->Groups[pg].Attributes
|
||||||
& (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
|
& (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
|
||||||
|
@ -525,6 +524,14 @@ error:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
getgroups32 (int gidsetsize, gid_t *grouplist)
|
||||||
|
{
|
||||||
|
cyg_ldap cldap;
|
||||||
|
|
||||||
|
return internal_getgroups (gidsetsize, grouplist, &cldap);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
EXPORT_ALIAS (getgroups32, getgroups)
|
EXPORT_ALIAS (getgroups32, getgroups)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -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_getgrgid (gid_t, cyg_ldap * = NULL);
|
||||||
extern struct group *internal_getgrnam (const char *, 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. */
|
/* These functions are called from mkpasswd/mkgroup via cygwin_internal. */
|
||||||
void *setpwent_filtered (int enums, PCWSTR enum_tdoms);
|
void *setpwent_filtered (int enums, PCWSTR enum_tdoms);
|
||||||
void *getpwent_filtered (void *gr);
|
void *getpwent_filtered (void *gr);
|
||||||
|
|
|
@ -116,30 +116,38 @@ cygheap_user::init ()
|
||||||
void
|
void
|
||||||
internal_getlogin (cygheap_user &user)
|
internal_getlogin (cygheap_user &user)
|
||||||
{
|
{
|
||||||
struct passwd *pw = NULL;
|
struct passwd *pwd;
|
||||||
struct group *gr, *gr2;
|
struct group *pgrp, *grp, *grp2;
|
||||||
cyg_ldap cldap;
|
cyg_ldap cldap;
|
||||||
|
|
||||||
cygpsid psid = user.sid ();
|
/* Fetch (and potentially generate) passwd and group entries for the user
|
||||||
pw = internal_getpwsid (psid, &cldap);
|
and the primary group in the token. */
|
||||||
|
pwd = internal_getpwsid (user.sid (), &cldap);
|
||||||
if (!pw && !(pw = internal_getpwnam (user.name (), &cldap)))
|
pgrp = internal_getgrsid (user.groups.pgsid, &cldap);
|
||||||
debug_printf ("user not found in /etc/passwd");
|
if (cygheap->pg.nss_db_full_caching ())
|
||||||
|
internal_getgroups (0, NULL, &cldap);
|
||||||
|
if (!pwd)
|
||||||
|
debug_printf ("user not found in passwd DB");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cygsid gsid;
|
cygsid gsid;
|
||||||
|
|
||||||
myself->uid = pw->pw_uid;
|
user.set_name (pwd->pw_name);
|
||||||
myself->gid = pw->pw_gid;
|
myself->uid = pwd->pw_uid;
|
||||||
user.set_name (pw->pw_name);
|
myself->gid = pwd->pw_gid;
|
||||||
if (gsid.getfromgr (gr = internal_getgrgid (pw->pw_gid, &cldap)))
|
/* 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)
|
||||||
|
{
|
||||||
|
if (gsid.getfromgr (grp = internal_getgrgid (pwd->pw_gid, &cldap)))
|
||||||
{
|
{
|
||||||
/* We might have a group file with a group entry for the current
|
/* 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.
|
user's primary group, but the current user has no entry in
|
||||||
If so, pw_gid is taken from windows and might disagree with the
|
passwd. If so, pw_gid is taken from windows and might
|
||||||
gr_gid from the group file. Overwrite it brutally. */
|
disagree with gr_gid from the group file. Overwrite it. */
|
||||||
if ((gr2 = internal_getgrsid (gsid, &cldap)) && gr2 != gr)
|
if ((grp2 = internal_getgrsid (gsid, &cldap)) && grp2 != grp)
|
||||||
myself->gid = pw->pw_gid = gr2->gr_gid;
|
myself->gid = pwd->pw_gid = grp2->gr_gid;
|
||||||
/* Set primary group to the group in /etc/passwd. */
|
/* Set primary group to the group in /etc/passwd. */
|
||||||
if (gsid != user.groups.pgsid)
|
if (gsid != user.groups.pgsid)
|
||||||
{
|
{
|
||||||
|
@ -147,17 +155,24 @@ internal_getlogin (cygheap_user &user)
|
||||||
TokenPrimaryGroup,
|
TokenPrimaryGroup,
|
||||||
&gsid, sizeof gsid);
|
&gsid, sizeof gsid);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("NtSetInformationToken (TokenPrimaryGroup), %y",
|
{
|
||||||
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
|
else
|
||||||
user.groups.pgsid = gsid;
|
user.groups.pgsid = gsid;
|
||||||
clear_procimptoken ();
|
clear_procimptoken ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
debug_printf ("gsid not found in augmented /etc/group");
|
debug_printf ("group not found in group DB");
|
||||||
}
|
}
|
||||||
cygheap->user.ontherange (CH_HOME, pw);
|
}
|
||||||
|
cygheap->user.ontherange (CH_HOME, pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -569,7 +584,7 @@ cygheap_pwdgrp::init ()
|
||||||
grp_src = (NSS_FILES | NSS_DB);
|
grp_src = (NSS_FILES | NSS_DB);
|
||||||
prefix = NSS_AUTO;
|
prefix = NSS_AUTO;
|
||||||
separator[0] = L'+';
|
separator[0] = L'+';
|
||||||
caching = true;
|
caching = NSS_FULL_CACHING;
|
||||||
enums = (ENUM_CACHE | ENUM_BUILTIN);
|
enums = (ENUM_CACHE | ENUM_BUILTIN);
|
||||||
enum_tdoms = NULL;
|
enum_tdoms = NULL;
|
||||||
}
|
}
|
||||||
|
@ -659,10 +674,12 @@ cygheap_pwdgrp::nss_init_line (const char *line)
|
||||||
{
|
{
|
||||||
c += 6;
|
c += 6;
|
||||||
c += strspn (c, " \t");
|
c += strspn (c, " \t");
|
||||||
if (!strncmp (c, "yes", 3) && strchr (" \t", c[3]))
|
if (!strncmp (c, "full", 3) && strchr (" \t", c[3]))
|
||||||
caching = true;
|
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]))
|
else if (!strncmp (c, "no", 2) && strchr (" \t", c[2]))
|
||||||
caching = false;
|
caching = NSS_NO_CACHING;
|
||||||
else
|
else
|
||||||
debug_printf ("Invalid nsswitch.conf content: %s", line);
|
debug_printf ("Invalid nsswitch.conf content: %s", line);
|
||||||
}
|
}
|
||||||
|
@ -986,6 +1003,8 @@ pwdgrp::add_account_from_windows (cygpsid &sid, bool group, cyg_ldap *pldap)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (cygheap->pg.nss_db_caching ())
|
if (cygheap->pg.nss_db_caching ())
|
||||||
return add_account_post_fetch (line, true);
|
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);
|
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,6 +1019,8 @@ pwdgrp::add_account_from_windows (const char *name, bool group, cyg_ldap *pldap)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (cygheap->pg.nss_db_caching ())
|
if (cygheap->pg.nss_db_caching ())
|
||||||
return add_account_post_fetch (line, true);
|
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);
|
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,6 +1035,8 @@ pwdgrp::add_account_from_windows (uint32_t id, bool group, cyg_ldap *pldap)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (cygheap->pg.nss_db_caching ())
|
if (cygheap->pg.nss_db_caching ())
|
||||||
return add_account_post_fetch (line, true);
|
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);
|
return (prep_tls_pwbuf ())->add_account_post_fetch (line, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1481,7 +1504,16 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group,
|
||||||
if (acc_type != SidTypeUser)
|
if (acc_type != SidTypeUser)
|
||||||
break;
|
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. */
|
/* Use LDAP to fetch domain account infos. */
|
||||||
if (!cldap->open (NULL))
|
if (!cldap->open (NULL))
|
||||||
break;
|
break;
|
||||||
|
@ -1724,6 +1756,12 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, bool group,
|
||||||
PDS_DOMAIN_TRUSTSW td = NULL;
|
PDS_DOMAIN_TRUSTSW td = NULL;
|
||||||
|
|
||||||
sid_sub_auth_count (sid) = sid_sub_auth_count (sid) - 1;
|
sid_sub_auth_count (sid) = sid_sub_auth_count (sid) - 1;
|
||||||
|
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)
|
for (ULONG idx = 0; (td = cygheap->dom.trusted_domain (idx)); ++idx)
|
||||||
if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
|
if (td->DomainSid && RtlEqualSid (sid, td->DomainSid))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue