* autoload.cc (DsGetDcNameW): Replace DsGetDcNameA.

* dcrt0.cc (child_info_spawn::handle_spawn): Drop artificial
	supplementary group list from calling setgroups in parent.
	* grp.cc (internal_getgroups): Drop 9x-only code.  Reformat.
	* sec_auth.cc (get_logon_server): Do everything in WCHAR only.
	(get_user_groups): Ditto.  Use wlogonserver in LookupAccountNameW
	calls, too.
	(is_group_member): Get logon server as first argument and use in call
	to NetLocalGroupGetMembers.
	(get_user_local_groups): Get logon server as first argument and use in
	calls to NetLocalGroupEnum and LookupAccountNameW.  Revamp to work
	more correctly in domain environments.
	(get_server_groups): Accommodate aforementioned changed function calls.
	* security.h (get_logon_server): Change prototype accordingly.
	* uinfo.cc (cygheap_user::env_logsrv): Accommodate changed
	get_logon_server call.
This commit is contained in:
Corinna Vinschen 2008-07-09 11:58:38 +00:00
parent 8f7208243e
commit 5558de95e5
7 changed files with 118 additions and 129 deletions

View File

@ -1,3 +1,22 @@
2008-07-09 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (DsGetDcNameW): Replace DsGetDcNameA.
* dcrt0.cc (child_info_spawn::handle_spawn): Drop artificial
supplementary group list from calling setgroups in parent.
* grp.cc (internal_getgroups): Drop 9x-only code. Reformat.
* sec_auth.cc (get_logon_server): Do everything in WCHAR only.
(get_user_groups): Ditto. Use wlogonserver in LookupAccountNameW
calls, too.
(is_group_member): Get logon server as first argument and use in call
to NetLocalGroupGetMembers.
(get_user_local_groups): Get logon server as first argument and use in
calls to NetLocalGroupEnum and LookupAccountNameW. Revamp to work
more correctly in domain environments.
(get_server_groups): Accommodate aforementioned changed function calls.
* security.h (get_logon_server): Change prototype accordingly.
* uinfo.cc (cygheap_user::env_logsrv): Accommodate changed
get_logon_server call.
2008-07-09 Corinna Vinschen <corinna@vinschen.de> 2008-07-09 Corinna Vinschen <corinna@vinschen.de>
* grp.cc (internal_getgroups): Also add integrity-enabled groups. * grp.cc (internal_getgroups): Also add integrity-enabled groups.

View File

@ -302,7 +302,7 @@ wsock_init ()
LoadDLLprime (ws2_32, _wsock_init) LoadDLLprime (ws2_32, _wsock_init)
/* 127 == ERROR_PROC_NOT_FOUND */ /* 127 == ERROR_PROC_NOT_FOUND */
LoadDLLfuncEx2 (DsGetDcNameA, 24, netapi32, 1, 127) LoadDLLfuncEx2 (DsGetDcNameW, 24, netapi32, 1, 127)
LoadDLLfunc (NetApiBufferFree, 4, netapi32) LoadDLLfunc (NetApiBufferFree, 4, netapi32)
LoadDLLfuncEx (NetGetAnyDCName, 12, netapi32, 1) LoadDLLfuncEx (NetGetAnyDCName, 12, netapi32, 1)
LoadDLLfuncEx (NetGetDCName, 12, netapi32, 1) LoadDLLfuncEx (NetGetDCName, 12, netapi32, 1)

View File

@ -671,6 +671,7 @@ child_info_spawn::handle_spawn ()
cygheap->fdtab.move_fd (__stdin, 0); cygheap->fdtab.move_fd (__stdin, 0);
if (__stdout >= 0) if (__stdout >= 0)
cygheap->fdtab.move_fd (__stdout, 1); cygheap->fdtab.move_fd (__stdout, 1);
cygheap->user.groups.clear_supp ();
ready (true); ready (true);

View File

@ -331,8 +331,6 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
DWORD size; DWORD size;
int cnt = 0; int cnt = 0;
struct __group32 *gr; struct __group32 *gr;
__gid32_t gid;
const char *username;
if (!srchsid && cygheap->user.groups.issetgroups ()) if (!srchsid && cygheap->user.groups.issetgroups ())
{ {
@ -340,8 +338,8 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (sid.getfromgr (gr)) if (sid.getfromgr (gr))
for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg) for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg)
if (sid == cygheap->user.groups.sgsids.sids[pg] && if (sid == cygheap->user.groups.sgsids.sids[pg]
sid != well_known_world_sid) && sid != well_known_world_sid)
{ {
if (cnt < gidsetsize) if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid; grouplist[cnt] = gr->gr_gid;
@ -360,67 +358,41 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
else else
hToken = hProcToken; hToken = hProcToken;
if (hToken) if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size)
|| GetLastError () == ERROR_INSUFFICIENT_BUFFER)
{ {
if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size) PTOKEN_GROUPS groups = (PTOKEN_GROUPS) alloca (size);
|| GetLastError () == ERROR_INSUFFICIENT_BUFFER)
if (GetTokenInformation (hToken, TokenGroups, groups, size, &size))
{ {
PTOKEN_GROUPS groups = (PTOKEN_GROUPS) alloca (size); cygsid sid;
if (GetTokenInformation (hToken, TokenGroups, groups, size, &size)) if (srchsid)
{ {
cygsid sid; for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
if ((cnt = (*srchsid == groups->Groups[pg].Sid)))
if (srchsid) break;
{
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
if ((cnt = (*srchsid == groups->Groups[pg].Sid)))
break;
}
else
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (sid.getfromgr (gr))
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
if (sid == groups->Groups[pg].Sid
&& (groups->Groups[pg].Attributes
& (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
&& sid != well_known_world_sid)
{
if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
goto error;
break;
}
} }
else
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (sid.getfromgr (gr))
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
if (sid == groups->Groups[pg].Sid
&& (groups->Groups[pg].Attributes
& (SE_GROUP_ENABLED | SE_GROUP_INTEGRITY_ENABLED))
&& sid != well_known_world_sid)
{
if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
goto error;
break;
}
} }
else
debug_printf ("%d = GetTokenInformation(NULL) %E", size);
return cnt;
} }
else
gid = myself->gid; debug_printf ("%d = GetTokenInformation(NULL) %E", size);
username = cygheap->user.name ();
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (gid == gr->gr_gid)
{
if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
goto error;
}
else if (gr->gr_mem)
for (int gi = 0; gr->gr_mem[gi]; ++gi)
if (strcasematch (username, gr->gr_mem[gi]))
{
if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
goto error;
}
return cnt; return cnt;
error: error:

View File

@ -11,6 +11,7 @@ details. */
#include "winsup.h" #include "winsup.h"
#include <stdlib.h> #include <stdlib.h>
#include <wchar.h>
#include <wininet.h> #include <wininet.h>
#include <ntsecapi.h> #include <ntsecapi.h>
#include <dsgetdc.h> #include <dsgetdc.h>
@ -166,52 +167,43 @@ close_local_policy (LSA_HANDLE &lsa)
} }
bool bool
get_logon_server (const char *domain, char *server, WCHAR *wserver, get_logon_server (PWCHAR wdomain, WCHAR *wserver, bool rediscovery)
bool rediscovery)
{ {
DWORD dret; DWORD dret;
PDOMAIN_CONTROLLER_INFOA pci; PDOMAIN_CONTROLLER_INFOW pci;
WCHAR *buf; WCHAR *buf;
DWORD size = INTERNET_MAX_HOST_NAME_LENGTH + 1; DWORD size = INTERNET_MAX_HOST_NAME_LENGTH + 1;
WCHAR wdomain[size];
/* Empty domain is interpreted as local system */ /* Empty domain is interpreted as local system */
if ((GetComputerName (server + 2, &size)) && if ((GetComputerNameW (wserver + 2, &size)) &&
(strcasematch (domain, server + 2) || !domain[0])) (!wcscasecmp (wdomain, wserver + 2) || !wdomain[0]))
{ {
server[0] = server[1] = '\\'; wserver[0] = wserver[1] = L'\\';
if (wserver)
sys_mbstowcs (wserver, INTERNET_MAX_HOST_NAME_LENGTH + 1, server);
return true; return true;
} }
/* Try to get any available domain controller for this domain */ /* Try to get any available domain controller for this domain */
dret = DsGetDcNameA (NULL, domain, NULL, NULL, dret = DsGetDcNameW (NULL, wdomain, NULL, NULL,
rediscovery ? DS_FORCE_REDISCOVERY : 0, &pci); rediscovery ? DS_FORCE_REDISCOVERY : 0, &pci);
if (dret == ERROR_SUCCESS) if (dret == ERROR_SUCCESS)
{ {
strcpy (server, pci->DomainControllerName); wcscpy (wserver, pci->DomainControllerName);
sys_mbstowcs (wserver, INTERNET_MAX_HOST_NAME_LENGTH + 1, server);
NetApiBufferFree (pci); NetApiBufferFree (pci);
debug_printf ("DC: rediscovery: %d, server: %s", rediscovery, server); debug_printf ("DC: rediscovery: %d, server: %W", rediscovery, wserver);
return true; return true;
} }
else if (dret == ERROR_PROC_NOT_FOUND) else if (dret == ERROR_PROC_NOT_FOUND)
{ {
/* NT4 w/o DSClient */ /* NT4 w/o DSClient */
sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, domain);
if (rediscovery) if (rediscovery)
dret = NetGetAnyDCName (NULL, wdomain, (LPBYTE *) &buf); dret = NetGetAnyDCName (NULL, wdomain, (LPBYTE *) &buf);
else else
dret = NetGetDCName (NULL, wdomain, (LPBYTE *) &buf); dret = NetGetDCName (NULL, wdomain, (LPBYTE *) &buf);
if (dret == NERR_Success) if (dret == NERR_Success)
{ {
sys_wcstombs (server, INTERNET_MAX_HOST_NAME_LENGTH + 1, buf); wcscpy (wserver, buf);
if (wserver)
for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);)
;
NetApiBufferFree (buf); NetApiBufferFree (buf);
debug_printf ("NT: rediscovery: %d, server: %s", rediscovery, server); debug_printf ("NT: rediscovery: %d, server: %W", rediscovery, wserver);
return true; return true;
} }
} }
@ -220,12 +212,10 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver,
} }
static bool static bool
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list,
char *domain) PWCHAR wuser, PWCHAR wdomain)
{ {
char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; WCHAR dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
WCHAR wuser[UNLEN + 1];
sys_mbstowcs (wuser, UNLEN + 1, user);
LPGROUP_USERS_INFO_0 buf; LPGROUP_USERS_INFO_0 buf;
DWORD cnt, tot, len; DWORD cnt, tot, len;
NET_API_STATUS ret; NET_API_STATUS ret;
@ -240,26 +230,26 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user,
return ret == NERR_UserNotFound; return ret == NERR_UserNotFound;
} }
len = strlen (domain); len = wcslen (wdomain);
strcpy (dgroup, domain); wcscpy (dgroup, wdomain);
dgroup[len++] = '\\'; dgroup[len++] = L'\\';
for (DWORD i = 0; i < cnt; ++i) for (DWORD i = 0; i < cnt; ++i)
{ {
cygsid gsid; cygsid gsid;
DWORD glen = MAX_SID_LEN; DWORD glen = MAX_SID_LEN;
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; WCHAR domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
DWORD dlen = sizeof (domain); DWORD dlen = sizeof (domain);
SID_NAME_USE use = SidTypeInvalid; SID_NAME_USE use = SidTypeInvalid;
sys_wcstombs (dgroup + len, GNLEN + 1, buf[i].grui0_name); wcscpy (dgroup + len, buf[i].grui0_name);
if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use)) if (!LookupAccountNameW (wlogonserver, dgroup, gsid, &glen,
domain, &dlen, &use))
debug_printf ("LookupAccountName(%s), %E", dgroup); debug_printf ("LookupAccountName(%s), %E", dgroup);
else if (legal_sid_type (use)) else if (legal_sid_type (use))
grp_list += gsid; grp_list += gsid;
else else
debug_printf ("Global group %s invalid. Domain: %s Use: %d", debug_printf ("Global group %s invalid. Use: %d", dgroup, use);
dgroup, domain, use);
} }
NetApiBufferFree (buf); NetApiBufferFree (buf);
@ -267,14 +257,15 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user,
} }
static bool static bool
is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list) is_group_member (PWCHAR wlogonserver, PWCHAR wgroup, PSID pusersid,
cygsidlist &grp_list)
{ {
LPLOCALGROUP_MEMBERS_INFO_1 buf; LPLOCALGROUP_MEMBERS_INFO_1 buf;
DWORD cnt, tot; DWORD cnt, tot;
NET_API_STATUS ret; NET_API_STATUS ret;
/* Members can be users or global groups */ /* Members can be users or global groups */
ret = NetLocalGroupGetMembers (NULL, wgroup, 1, (LPBYTE *) &buf, ret = NetLocalGroupGetMembers (wlogonserver, wgroup, 1, (LPBYTE *) &buf,
MAX_PREFERRED_LENGTH, &cnt, &tot, NULL); MAX_PREFERRED_LENGTH, &cnt, &tot, NULL);
if (ret) if (ret)
return false; return false;
@ -310,13 +301,14 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
} }
static bool static bool
get_user_local_groups (cygsidlist &grp_list, PSID pusersid) get_user_local_groups (PWCHAR wlogonserver, PWCHAR wdomain,
cygsidlist &grp_list, PSID pusersid)
{ {
LPLOCALGROUP_INFO_0 buf; LPLOCALGROUP_INFO_0 buf;
DWORD cnt, tot; DWORD cnt, tot;
NET_API_STATUS ret; NET_API_STATUS ret;
ret = NetLocalGroupEnum (NULL, 0, (LPBYTE *) &buf, ret = NetLocalGroupEnum (wlogonserver, 0, (LPBYTE *) &buf,
MAX_PREFERRED_LENGTH, &cnt, &tot, NULL); MAX_PREFERRED_LENGTH, &cnt, &tot, NULL);
if (ret) if (ret)
{ {
@ -324,42 +316,43 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
return false; return false;
} }
char bgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; WCHAR domlocal_grp[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; WCHAR builtin_grp[sizeof ("BUILTIN\\") + GNLEN + 2];
DWORD blen, llen; PWCHAR dg_ptr, bg_ptr;
SID_NAME_USE use; SID_NAME_USE use;
blen = llen = INTERNET_MAX_HOST_NAME_LENGTH + 1; dg_ptr = wcpcpy (domlocal_grp, wdomain);
if (!LookupAccountSid (NULL, well_known_admins_sid, lgroup, &llen, bgroup, &blen, &use) *dg_ptr++ = L'\\';
|| !GetComputerNameA (lgroup, &(llen = INTERNET_MAX_HOST_NAME_LENGTH + 1))) bg_ptr = wcpcpy (builtin_grp, L"BUILTIN\\");
{
__seterrno ();
return false;
}
bgroup[blen++] = lgroup[llen++] = '\\';
for (DWORD i = 0; i < cnt; ++i) for (DWORD i = 0; i < cnt; ++i)
if (is_group_member (buf[i].lgrpi0_name, pusersid, grp_list)) if (is_group_member (wlogonserver, buf[i].lgrpi0_name, pusersid, grp_list))
{ {
cygsid gsid; cygsid gsid;
DWORD glen = MAX_SID_LEN; DWORD glen = MAX_SID_LEN;
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; WCHAR dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
DWORD dlen = sizeof (domain); DWORD domlen = sizeof (dom);
bool builtin = false;
use = SidTypeInvalid; use = SidTypeInvalid;
sys_wcstombs (bgroup + blen, GNLEN + 1, buf[i].lgrpi0_name); wcscpy (dg_ptr, buf[i].lgrpi0_name);
if (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use)) if (!LookupAccountNameW (wlogonserver, domlocal_grp, gsid, &glen,
dom, &domlen, &use))
{ {
if (GetLastError () != ERROR_NONE_MAPPED) if (GetLastError () != ERROR_NONE_MAPPED)
debug_printf ("LookupAccountName(%s), %E", bgroup); debug_printf ("LookupAccountName(%W), %E", domlocal_grp);
strcpy (lgroup + llen, bgroup + blen); wcscpy (bg_ptr, dg_ptr);
if (!LookupAccountName (NULL, lgroup, gsid, &glen, if (!LookupAccountNameW (wlogonserver, builtin_grp, gsid, &glen,
domain, &dlen, &use)) dom, &domlen, &use))
debug_printf ("LookupAccountName(%s), %E", lgroup); debug_printf ("LookupAccountName(%W), %E", builtin_grp);
builtin = true;
} }
if (!legal_sid_type (use)) if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use); debug_printf ("Rejecting local %W. use: %d", dg_ptr, use);
grp_list *= gsid; else if (builtin)
grp_list *= gsid;
else
grp_list += gsid;
} }
NetApiBufferFree (buf); NetApiBufferFree (buf);
return true; return true;
@ -439,9 +432,10 @@ bool
get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw) get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
{ {
char user[UNLEN + 1]; char user[UNLEN + 1];
WCHAR wuser[UNLEN + 1];
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR wdomain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3]; WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3];
char server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
if (well_known_system_sid == usersid) if (well_known_system_sid == usersid)
{ {
@ -453,11 +447,13 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
grp_list *= well_known_world_sid; grp_list *= well_known_world_sid;
grp_list *= well_known_authenticated_users_sid; grp_list *= well_known_authenticated_users_sid;
extract_nt_dom_user (pw, domain, user); extract_nt_dom_user (pw, domain, user);
if (get_logon_server (domain, server, wserver, false) sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, domain);
&& !get_user_groups (wserver, grp_list, user, domain) sys_mbstowcs (wuser, UNLEN + 1, user);
&& get_logon_server (domain, server, wserver, true)) if (get_logon_server (wdomain, wserver, false)
get_user_groups (wserver, grp_list, user, domain); && !get_user_groups (wserver, grp_list, wuser, wdomain)
if (get_user_local_groups (grp_list, usersid)) && get_logon_server (wdomain, wserver, true))
get_user_groups (wserver, grp_list, wuser, wdomain);
if (get_user_local_groups (wserver, wdomain, grp_list, usersid))
{ {
get_unix_group_sidlist (pw, grp_list); get_unix_group_sidlist (pw, grp_list);
return true; return true;

View File

@ -380,8 +380,7 @@ bool get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw);
/* Extract U-domain\user field from passwd entry. */ /* Extract U-domain\user field from passwd entry. */
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user); void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
/* Get default logonserver for a domain. */ /* Get default logonserver for a domain. */
bool get_logon_server (const char * domain, char * server, WCHAR *wserver, bool get_logon_server (PWCHAR domain, PWCHAR wserver, bool rediscovery);
bool rediscovery);
/* sec_helper.cc: Security helper functions. */ /* sec_helper.cc: Security helper functions. */
int set_privilege (HANDLE token, DWORD privilege, bool enable); int set_privilege (HANDLE token, DWORD privilege, bool enable);

View File

@ -369,10 +369,12 @@ cygheap_user::env_logsrv (const char *name, size_t namelen)
if (!mydomain || ascii_strcasematch (myname, "SYSTEM")) if (!mydomain || ascii_strcasematch (myname, "SYSTEM"))
return almost_null; return almost_null;
char logsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3]; WCHAR wdomain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR wlogsrv[INTERNET_MAX_HOST_NAME_LENGTH + 3];
sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, mydomain);
cfree_and_set (plogsrv, almost_null); cfree_and_set (plogsrv, almost_null);
if (get_logon_server (mydomain, logsrv, NULL, false)) if (get_logon_server (wdomain, wlogsrv, false))
plogsrv = cstrdup (logsrv); sys_wcstombs_alloc (&plogsrv, HEAP_STR, wlogsrv);
return plogsrv; return plogsrv;
} }