From 5558de95e59c62d23d70f64fb7dc510f4f77477f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 9 Jul 2008 11:58:38 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 19 ++++++ winsup/cygwin/autoload.cc | 2 +- winsup/cygwin/dcrt0.cc | 1 + winsup/cygwin/grp.cc | 88 +++++++++----------------- winsup/cygwin/sec_auth.cc | 126 ++++++++++++++++++-------------------- winsup/cygwin/security.h | 3 +- winsup/cygwin/uinfo.cc | 8 ++- 7 files changed, 118 insertions(+), 129 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6b7e0eda9..61d367530 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2008-07-09 Corinna Vinschen + + * 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 * grp.cc (internal_getgroups): Also add integrity-enabled groups. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index f9f02f289..80228e24e 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -302,7 +302,7 @@ wsock_init () LoadDLLprime (ws2_32, _wsock_init) /* 127 == ERROR_PROC_NOT_FOUND */ -LoadDLLfuncEx2 (DsGetDcNameA, 24, netapi32, 1, 127) +LoadDLLfuncEx2 (DsGetDcNameW, 24, netapi32, 1, 127) LoadDLLfunc (NetApiBufferFree, 4, netapi32) LoadDLLfuncEx (NetGetAnyDCName, 12, netapi32, 1) LoadDLLfuncEx (NetGetDCName, 12, netapi32, 1) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index e0fa5b5b1..dddb97f53 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -671,6 +671,7 @@ child_info_spawn::handle_spawn () cygheap->fdtab.move_fd (__stdin, 0); if (__stdout >= 0) cygheap->fdtab.move_fd (__stdout, 1); + cygheap->user.groups.clear_supp (); ready (true); diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 37a0fcd73..f38888e1b 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -331,8 +331,6 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid) DWORD size; int cnt = 0; struct __group32 *gr; - __gid32_t gid; - const char *username; 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) if (sid.getfromgr (gr)) for (int pg = 0; pg < cygheap->user.groups.sgsids.count (); ++pg) - if (sid == cygheap->user.groups.sgsids.sids[pg] && - sid != well_known_world_sid) + if (sid == cygheap->user.groups.sgsids.sids[pg] + && sid != well_known_world_sid) { if (cnt < gidsetsize) grouplist[cnt] = gr->gr_gid; @@ -360,67 +358,41 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid) else hToken = hProcToken; - if (hToken) + if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size) + || GetLastError () == ERROR_INSUFFICIENT_BUFFER) { - if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size) - || GetLastError () == ERROR_INSUFFICIENT_BUFFER) + PTOKEN_GROUPS groups = (PTOKEN_GROUPS) alloca (size); + + 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; - - if (srchsid) - { - 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; - } + 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 - debug_printf ("%d = GetTokenInformation(NULL) %E", size); - return cnt; } - - gid = myself->gid; - 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; - } + else + debug_printf ("%d = GetTokenInformation(NULL) %E", size); return cnt; error: diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc index f78b86539..b2f1fe77d 100644 --- a/winsup/cygwin/sec_auth.cc +++ b/winsup/cygwin/sec_auth.cc @@ -11,6 +11,7 @@ details. */ #include "winsup.h" #include +#include #include #include #include @@ -166,52 +167,43 @@ close_local_policy (LSA_HANDLE &lsa) } bool -get_logon_server (const char *domain, char *server, WCHAR *wserver, - bool rediscovery) +get_logon_server (PWCHAR wdomain, WCHAR *wserver, bool rediscovery) { DWORD dret; - PDOMAIN_CONTROLLER_INFOA pci; + PDOMAIN_CONTROLLER_INFOW pci; WCHAR *buf; DWORD size = INTERNET_MAX_HOST_NAME_LENGTH + 1; - WCHAR wdomain[size]; /* Empty domain is interpreted as local system */ - if ((GetComputerName (server + 2, &size)) && - (strcasematch (domain, server + 2) || !domain[0])) + if ((GetComputerNameW (wserver + 2, &size)) && + (!wcscasecmp (wdomain, wserver + 2) || !wdomain[0])) { - server[0] = server[1] = '\\'; - if (wserver) - sys_mbstowcs (wserver, INTERNET_MAX_HOST_NAME_LENGTH + 1, server); + wserver[0] = wserver[1] = L'\\'; return true; } /* 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); if (dret == ERROR_SUCCESS) { - strcpy (server, pci->DomainControllerName); - sys_mbstowcs (wserver, INTERNET_MAX_HOST_NAME_LENGTH + 1, server); + wcscpy (wserver, pci->DomainControllerName); NetApiBufferFree (pci); - debug_printf ("DC: rediscovery: %d, server: %s", rediscovery, server); + debug_printf ("DC: rediscovery: %d, server: %W", rediscovery, wserver); return true; } else if (dret == ERROR_PROC_NOT_FOUND) { /* NT4 w/o DSClient */ - sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, domain); if (rediscovery) dret = NetGetAnyDCName (NULL, wdomain, (LPBYTE *) &buf); else dret = NetGetDCName (NULL, wdomain, (LPBYTE *) &buf); if (dret == NERR_Success) { - sys_wcstombs (server, INTERNET_MAX_HOST_NAME_LENGTH + 1, buf); - if (wserver) - for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);) - ; + wcscpy (wserver, buf); NetApiBufferFree (buf); - debug_printf ("NT: rediscovery: %d, server: %s", rediscovery, server); + debug_printf ("NT: rediscovery: %d, server: %W", rediscovery, wserver); return true; } } @@ -220,12 +212,10 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver, } static bool -get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, - char *domain) +get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, + PWCHAR wuser, PWCHAR wdomain) { - char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; - WCHAR wuser[UNLEN + 1]; - sys_mbstowcs (wuser, UNLEN + 1, user); + WCHAR dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; LPGROUP_USERS_INFO_0 buf; DWORD cnt, tot, len; NET_API_STATUS ret; @@ -240,26 +230,26 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, return ret == NERR_UserNotFound; } - len = strlen (domain); - strcpy (dgroup, domain); - dgroup[len++] = '\\'; + len = wcslen (wdomain); + wcscpy (dgroup, wdomain); + dgroup[len++] = L'\\'; for (DWORD i = 0; i < cnt; ++i) { cygsid gsid; 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); SID_NAME_USE use = SidTypeInvalid; - sys_wcstombs (dgroup + len, GNLEN + 1, buf[i].grui0_name); - if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use)) + wcscpy (dgroup + len, buf[i].grui0_name); + if (!LookupAccountNameW (wlogonserver, dgroup, gsid, &glen, + domain, &dlen, &use)) debug_printf ("LookupAccountName(%s), %E", dgroup); else if (legal_sid_type (use)) grp_list += gsid; else - debug_printf ("Global group %s invalid. Domain: %s Use: %d", - dgroup, domain, use); + debug_printf ("Global group %s invalid. Use: %d", dgroup, use); } NetApiBufferFree (buf); @@ -267,14 +257,15 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, } 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; DWORD cnt, tot; NET_API_STATUS ret; /* 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); if (ret) return false; @@ -310,13 +301,14 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list) } 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; DWORD cnt, tot; NET_API_STATUS ret; - ret = NetLocalGroupEnum (NULL, 0, (LPBYTE *) &buf, + ret = NetLocalGroupEnum (wlogonserver, 0, (LPBYTE *) &buf, MAX_PREFERRED_LENGTH, &cnt, &tot, NULL); if (ret) { @@ -324,42 +316,43 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid) return false; } - char bgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; - char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; - DWORD blen, llen; + WCHAR domlocal_grp[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; + WCHAR builtin_grp[sizeof ("BUILTIN\\") + GNLEN + 2]; + PWCHAR dg_ptr, bg_ptr; SID_NAME_USE use; - blen = llen = INTERNET_MAX_HOST_NAME_LENGTH + 1; - if (!LookupAccountSid (NULL, well_known_admins_sid, lgroup, &llen, bgroup, &blen, &use) - || !GetComputerNameA (lgroup, &(llen = INTERNET_MAX_HOST_NAME_LENGTH + 1))) - { - __seterrno (); - return false; - } - bgroup[blen++] = lgroup[llen++] = '\\'; + dg_ptr = wcpcpy (domlocal_grp, wdomain); + *dg_ptr++ = L'\\'; + bg_ptr = wcpcpy (builtin_grp, L"BUILTIN\\"); 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; DWORD glen = MAX_SID_LEN; - char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; - DWORD dlen = sizeof (domain); + WCHAR dom[INTERNET_MAX_HOST_NAME_LENGTH + 1]; + DWORD domlen = sizeof (dom); + bool builtin = false; use = SidTypeInvalid; - sys_wcstombs (bgroup + blen, GNLEN + 1, buf[i].lgrpi0_name); - if (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use)) + wcscpy (dg_ptr, buf[i].lgrpi0_name); + if (!LookupAccountNameW (wlogonserver, domlocal_grp, gsid, &glen, + dom, &domlen, &use)) { if (GetLastError () != ERROR_NONE_MAPPED) - debug_printf ("LookupAccountName(%s), %E", bgroup); - strcpy (lgroup + llen, bgroup + blen); - if (!LookupAccountName (NULL, lgroup, gsid, &glen, - domain, &dlen, &use)) - debug_printf ("LookupAccountName(%s), %E", lgroup); + debug_printf ("LookupAccountName(%W), %E", domlocal_grp); + wcscpy (bg_ptr, dg_ptr); + if (!LookupAccountNameW (wlogonserver, builtin_grp, gsid, &glen, + dom, &domlen, &use)) + debug_printf ("LookupAccountName(%W), %E", builtin_grp); + builtin = true; } if (!legal_sid_type (use)) - debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use); - grp_list *= gsid; + debug_printf ("Rejecting local %W. use: %d", dg_ptr, use); + else if (builtin) + grp_list *= gsid; + else + grp_list += gsid; } NetApiBufferFree (buf); return true; @@ -439,9 +432,10 @@ bool get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw) { char user[UNLEN + 1]; + WCHAR wuser[UNLEN + 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]; - char server[INTERNET_MAX_HOST_NAME_LENGTH + 3]; 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_authenticated_users_sid; extract_nt_dom_user (pw, domain, user); - if (get_logon_server (domain, server, wserver, false) - && !get_user_groups (wserver, grp_list, user, domain) - && get_logon_server (domain, server, wserver, true)) - get_user_groups (wserver, grp_list, user, domain); - if (get_user_local_groups (grp_list, usersid)) + sys_mbstowcs (wdomain, INTERNET_MAX_HOST_NAME_LENGTH + 1, domain); + sys_mbstowcs (wuser, UNLEN + 1, user); + if (get_logon_server (wdomain, wserver, false) + && !get_user_groups (wserver, grp_list, wuser, wdomain) + && 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); return true; diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 1eb81b3a2..93524cefe 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -380,8 +380,7 @@ bool get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw); /* Extract U-domain\user field from passwd entry. */ void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user); /* Get default logonserver for a domain. */ -bool get_logon_server (const char * domain, char * server, WCHAR *wserver, - bool rediscovery); +bool get_logon_server (PWCHAR domain, PWCHAR wserver, bool rediscovery); /* sec_helper.cc: Security helper functions. */ int set_privilege (HANDLE token, DWORD privilege, bool enable); diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index c18ad8ebd..8a4b86df8 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -369,10 +369,12 @@ cygheap_user::env_logsrv (const char *name, size_t namelen) if (!mydomain || ascii_strcasematch (myname, "SYSTEM")) 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); - if (get_logon_server (mydomain, logsrv, NULL, false)) - plogsrv = cstrdup (logsrv); + if (get_logon_server (wdomain, wlogsrv, false)) + sys_wcstombs_alloc (&plogsrv, HEAP_STR, wlogsrv); return plogsrv; }