diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 6383646cc7..6b2f647724 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -219,7 +219,8 @@ enum
enum
{
NSS_SRC_FILES = 1,
- NSS_SRC_DB = 2
+ NSS_SRC_DB = 2,
+ NSS_SRC_DB_ACCURATE = 4
};
/* Enumeration source constants for CW_SETENT called from mkpasswd/mkgroup. */
diff --git a/winsup/cygwin/local_includes/cygheap.h b/winsup/cygwin/local_includes/cygheap.h
index f5aecba37a..c33f378500 100644
--- a/winsup/cygwin/local_includes/cygheap.h
+++ b/winsup/cygwin/local_includes/cygheap.h
@@ -454,6 +454,7 @@ class cygheap_pwdgrp
inline int nss_pwd_src () const { return pwd_src; } /* CW_GETNSS_PWD_SRC */
inline bool nss_grp_files () const { return !!(grp_src & NSS_SRC_FILES); }
inline bool nss_grp_db () const { return !!(grp_src & NSS_SRC_DB); }
+ inline bool nss_grp_db_accurate () const { return !!(grp_src & NSS_SRC_DB_ACCURATE); }
inline int nss_grp_src () const { return grp_src; } /* CW_GETNSS_GRP_SRC */
inline bool nss_cygserver_caching () const { return caching; }
inline void nss_disable_cygserver_caching () { caching = false; }
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index a25f39f427..fefd984f84 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -637,6 +637,11 @@ cygheap_pwdgrp::nss_init_line (const char *line)
*src |= NSS_SRC_DB;
c += 2;
}
+ else if (NSS_CMP ("db-accurate"))
+ {
+ *src |= NSS_SRC_DB | NSS_SRC_DB_ACCURATE;
+ c += 11;
+ }
else
{
c += strcspn (c, " \t");
@@ -1906,6 +1911,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
gid_t gid = ILLEGAL_GID;
bool is_domain_account = true;
PCWSTR domain = NULL;
+ bool get_default_group_from_current_user_token = false;
char *shell = NULL;
char *home = NULL;
char *gecos = NULL;
@@ -2371,9 +2377,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
uid = posix_offset + sid_sub_auth_rid (sid);
if (!is_group () && acc_type == SidTypeUser)
{
- /* Default primary group. Make the educated guess that the user
- is in group "Domain Users" or "None". */
- gid = posix_offset + DOMAIN_GROUP_RID_USERS;
+ /* Default primary group. If the sid is the current user, and
+ we are not configured for accurate mode, 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 (!cygheap->pg.nss_grp_db_accurate() && sid == cygheap->user.sid ())
+ {
+ get_default_group_from_current_user_token = true;
+ gid = posix_offset
+ + sid_sub_auth_rid (cygheap->user.groups.pgsid);
+ }
+ else
+ gid = posix_offset + DOMAIN_GROUP_RID_USERS;
}
if (is_domain_account)
@@ -2384,9 +2400,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
/* On AD machines, use LDAP to fetch domain account infos. */
if (cygheap->dom.primary_dns_name ())
{
- /* Fetch primary group from AD and overwrite the one we
- just guessed above. */
- if (cldap->fetch_ad_account (sid, false, domain))
+ /* For the current user we got correctly cased username and
+ the primary group via process token. For any other user
+ we fetch it from AD and overwrite it. */
+ if (!get_default_group_from_current_user_token
+ && cldap->fetch_ad_account (sid, false, domain))
{
if ((val = cldap->get_account_name ()))
wcscpy (name, val);
diff --git a/winsup/doc/ntsec.xml b/winsup/doc/ntsec.xml
index c6871ecf05..d61b585171 100644
--- a/winsup/doc/ntsec.xml
+++ b/winsup/doc/ntsec.xml
@@ -930,7 +930,16 @@ The two lines starting with the keywords passwd: and
information from. files means, fetch the information
from the corresponding file in the /etc directory. db
means, fetch the information from the Windows account databases, the SAM
-for local accounts, Active Directory for domain account. Examples:
+for local accounts, Active Directory for domain account. For the current
+user, the default group is obtained from the current user token to avoid
+additional lookups to the group database. db-accurate
+is only valid on group: line, and performs the same
+lookups as the db option, but disables using the
+current user token to retrieve the default group as this optimization
+is not accurate in all cases. For example, if you run a native process
+with the primary group set to the Administrators builtin group, the
+db option will return a non-existent group as primary
+group. Examples:
@@ -949,6 +958,15 @@ Read passwd entries only from /etc/passwd.
Read group entries only from SAM/AD.
+
+ group: db-accurate
+
+
+
+Read group entries only from SAM/AD. Force the use of the group database
+for the current user.
+
+
group: files # db