Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sec_auth.cc')
-rw-r--r--winsup/cygwin/sec_auth.cc112
1 files changed, 71 insertions, 41 deletions
diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc
index 3615588ef..2cdce8bd4 100644
--- a/winsup/cygwin/sec_auth.cc
+++ b/winsup/cygwin/sec_auth.cc
@@ -14,6 +14,7 @@ details. */
#include <wchar.h>
#include <wininet.h>
#include <ntsecapi.h>
+#include <dsgetdc.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
@@ -24,6 +25,7 @@ details. */
#include "tls_pbuf.h"
#include <lm.h>
#include <iptypes.h>
+#include "pwdgrp.h"
#include "cyglsa.h"
#include "cygserver_setpwd.h"
#include <cygwin/version.h>
@@ -219,27 +221,28 @@ lsa_close_policy (HANDLE lsa)
}
bool
-get_logon_server (PWCHAR domain, WCHAR *server, ULONG flags)
+get_logon_server (PWCHAR domain, WCHAR *server, bool rediscovery)
{
DWORD ret;
PDOMAIN_CONTROLLER_INFOW pci;
+ DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
/* Empty domain is interpreted as local system */
- if (cygheap->dom.init ()
- && (!domain[0]
- || !wcscasecmp (domain, cygheap->dom.account_flat_name ())))
+ if ((GetComputerNameW (server + 2, &size)) &&
+ (!wcscasecmp (domain, server + 2) || !domain[0]))
{
- wcpcpy (wcpcpy (server, L"\\\\"), cygheap->dom.account_flat_name ());
+ server[0] = server[1] = L'\\';
return true;
}
/* Try to get any available domain controller for this domain */
- ret = DsGetDcNameW (NULL, domain, NULL, NULL, flags, &pci);
+ ret = DsGetDcNameW (NULL, domain, NULL, NULL,
+ rediscovery ? DS_FORCE_REDISCOVERY : 0, &pci);
if (ret == ERROR_SUCCESS)
{
wcscpy (server, pci->DomainControllerName);
NetApiBufferFree (pci);
- debug_printf ("DC: server: %W", server);
+ debug_printf ("DC: rediscovery: %d, server: %W", rediscovery, server);
return true;
}
__seterrno_from_win_error (ret);
@@ -278,7 +281,7 @@ get_user_groups (WCHAR *logonserver, cygsidlist &grp_list,
for (DWORD i = 0; i < cnt; ++i)
{
cygsid gsid;
- DWORD glen = SECURITY_MAX_SID_SIZE;
+ DWORD glen = MAX_SID_LEN;
WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
DWORD dlen = sizeof (dom);
SID_NAME_USE use = SidTypeInvalid;
@@ -326,7 +329,7 @@ get_user_local_groups (PWCHAR logonserver, PWCHAR domain,
for (DWORD i = 0; i < cnt; ++i)
{
cygsid gsid;
- DWORD glen = SECURITY_MAX_SID_SIZE;
+ DWORD glen = MAX_SID_LEN;
WCHAR dom[MAX_DOMAIN_NAME_LEN + 1];
DWORD domlen = MAX_DOMAIN_NAME_LEN + 1;
@@ -362,7 +365,7 @@ get_user_local_groups (PWCHAR logonserver, PWCHAR domain,
if (bg_ptr)
{
wcscpy (bg_ptr, dg_ptr);
- glen = SECURITY_MAX_SID_SIZE;
+ glen = MAX_SID_LEN;
domlen = MAX_DOMAIN_NAME_LEN + 1;
if (LookupAccountNameW (NULL, builtin_grp, gsid, &glen,
dom, &domlen, &use))
@@ -395,6 +398,28 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygpsid sid)
}
static void
+get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
+{
+ struct group *gr;
+ cygsid gsid;
+
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ {
+ if (gr->gr_gid == pw->pw_gid)
+ goto found;
+ else if (gr->gr_mem)
+ for (int gi = 0; gr->gr_mem[gi]; ++gi)
+ if (strcasematch (pw->pw_name, gr->gr_mem[gi]))
+ goto found;
+ continue;
+ found:
+ if (gsid.getfromgr (gr))
+ grp_list += gsid;
+
+ }
+}
+
+static void
get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
LUID auth_luid, int &auth_pos)
{
@@ -455,6 +480,7 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
if (well_known_system_sid == usersid)
{
grp_list *= well_known_admins_sid;
+ get_unix_group_sidlist (pw, grp_list);
return true;
}
@@ -466,16 +492,12 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
__seterrno ();
return false;
}
- /* If the SID does NOT start with S-1-5-21, the domain is some builtin
- domain. The search for a logon server and fetching group accounts
- is moot. */
- if (sid_id_auth (usersid) == 5 /* SECURITY_NT_AUTHORITY */
- && sid_sub_auth (usersid, 0) == SECURITY_NT_NON_UNIQUE
- && get_logon_server (domain, server, DS_IS_FLAT_NAME))
- {
- get_user_groups (server, grp_list, user, domain);
- get_user_local_groups (server, domain, grp_list, user);
- }
+ if (get_logon_server (domain, server, false)
+ && !get_user_groups (server, grp_list, user, domain)
+ && get_logon_server (domain, server, true))
+ get_user_groups (server, grp_list, user, domain);
+ get_user_local_groups (server, domain, grp_list, user);
+ get_unix_group_sidlist (pw, grp_list);
return true;
}
@@ -683,7 +705,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
*pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
}
/* Verify usersid */
- cygsid tok_usersid (NO_SID);
+ cygsid tok_usersid = NO_SID;
status = NtQueryInformationToken (token, TokenUser, &tok_usersid,
sizeof tok_usersid, &size);
if (!NT_SUCCESS (status))
@@ -695,8 +717,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
is not well_known_null_sid, it must match pgrpsid */
if (intern && !groups.issetgroups ())
{
- const DWORD sd_buf_siz = SECURITY_MAX_SID_SIZE
- + sizeof (SECURITY_DESCRIPTOR);
+ const DWORD sd_buf_siz = MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR);
PSECURITY_DESCRIPTOR sd_buf = (PSECURITY_DESCRIPTOR) alloca (sd_buf_siz);
cygpsid gsid (NO_SID);
NTSTATUS status;
@@ -737,26 +758,35 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
if (groups.issetgroups ()) /* setgroups was called */
{
- cygpsid gsid;
+ cygsid gsid;
+ struct group *gr;
bool saw[groups.sgsids.count ()];
-
- /* Check that all groups in the setgroups () list are in the token.
- A token created through ADVAPI should be allowed to contain more
- groups than requested through setgroups(), especially since Vista
- and the addition of integrity groups. */
memset (saw, 0, sizeof(saw));
- for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
- {
- gsid = groups.sgsids.sids[gidx];
- if (sid_in_token_groups (my_grps, gsid))
- {
- int pos = groups.sgsids.position (gsid);
- if (pos >= 0)
- saw[pos] = true;
- else if (groups.pgsid == gsid)
- sawpg = true;
- }
- }
+
+ /* token groups found in /etc/group match the user.gsids ? */
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ if (gsid.getfromgr (gr) && sid_in_token_groups (my_grps, gsid))
+ {
+ int pos = groups.sgsids.position (gsid);
+ if (pos >= 0)
+ saw[pos] = true;
+ else if (groups.pgsid == gsid)
+ sawpg = true;
+#if 0
+ /* With this `else', verify_token returns false if we find
+ groups in the token, which are not in the group list set
+ with setgroups(). That's rather dangerous. What we're
+ really interested in is that all groups in the setgroups()
+ list are in the token. A token created through ADVAPI
+ should be allowed to contain more groups than requested
+ through setgroups(), esecially since Vista and the
+ addition of integrity groups. So we disable this statement
+ for now. */
+ else if (gsid != well_known_world_sid
+ && gsid != usersid)
+ goto done;
+#endif
+ }
/* user.sgsids groups must be in the token, except for builtin groups.
These can be different on domain member machines compared to
domain controllers, so these builtin groups may be validly missing