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:
-rw-r--r--winsup/cygwin/ChangeLog54
-rw-r--r--winsup/cygwin/cyglsa.h149
-rw-r--r--winsup/cygwin/environ.cc6
-rw-r--r--winsup/cygwin/grp.cc8
-rw-r--r--winsup/cygwin/sec_helper.cc60
-rw-r--r--winsup/cygwin/security.cc415
-rw-r--r--winsup/cygwin/security.h118
-rw-r--r--winsup/cygwin/syscalls.cc46
-rw-r--r--winsup/cygwin/wincap.cc13
-rw-r--r--winsup/cygwin/wincap.h2
10 files changed, 686 insertions, 185 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index e35ed5734..177e77c36 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,57 @@
+2006-11-27 Corinna Vinschen <corinna@vinschen.de>
+
+ * cyglsa.h: New header file.
+ * environ.cc: Disable subauth settings.
+ * grp.cc: Accomodate cygsidlist's count now being a method.
+ * sec_helper.cc (SECURITY_MANDATORY_INTEGRITY_AUTHORITY): Remove.
+ (mandatory_medium_integrity_sid): Remove.
+ (mandatory_high_integrity_sid): Remove.
+ (mandatory_system_integrity_sid): Remove.
+ (fake_logon_sid): Add.
+ (cygsid::get_sid): Add well_known parameter. Set well_known_sid
+ accordingly.
+ (cygsid::getfromstr): Ditto.
+ (cygsidlist::alloc_sids): Move here from security.cc.
+ (cygsidlist::free_sids): Ditto.
+ (cygsidlist::add): Move here from security.h. Add well_known parameter.
+ Set well_known_sid accordingly. Don't allow duplicate SIDs.
+ * security.cc: Include cyglsa.h and cygwin/version.h. Throughout
+ accomodate cygsidlist's count now being a method. Throughout drop
+ redundant "contains" tests.
+ (get_user_local_groups): Add local groups as well known SIDs.
+ (get_token_group_sidlist): Add well known groups as well known SIDs.
+ (get_server_groups): Ditto. Only call get_unix_group_sidlist after
+ get_user_local_groups to maintain "well_known_sid" attribute.
+ (get_initgroups_sidlist): Add well known groups as well known SIDs.
+ (get_setgroups_sidlist): Add usersid and struct passwd parameter to
+ allow calling get_server_groups from here.
+ (get_system_priv_list): Make static. Return size of TOKEN_PRIVILEGES
+ structure.
+ (get_priv_list): Ditto.
+ (create_token): Accomodate above changes. Drop misguided attempt to
+ add MIC SIDs to created user token. Print returned token as hex value.
+ (subauth): Disable.
+ (lsaauth): New function implementing client side of LSA authentication.
+ * security.h (class cygsid): Add well_known_sid attribute. Accomodate
+ throughout. Add *= operator to create a well known SID.
+ (class cygsidlist): Rename count to cnt. Make count a method.
+ (cygsidlist::add): Move to sec_helper.cc.
+ (cygsidlist::operator *=): New method to add well known SID.
+ (cygsidlist::non_well_known_count): New method returning number of
+ non well known SIDs in list.
+ (cygsidlist::next_non_well_known_sid): New method returning next non
+ well known SID by index.
+ (mandatory_medium_integrity_sid): Drop declaration.
+ (mandatory_high_integrity_sid): Drop declaration.
+ (mandatory_system_integrity_sid): Drop declaration.
+ (fake_logon_sid): Add declaration.
+ (subauth): Disable declaration.
+ (lsaauth): Add declaration.
+ * syscalls.cc (seteuid32): Disable subauthentication. Add LSA
+ authentication.
+ * wincap.h: Define needs_logon_sid_in_sid_list throughout.
+ * wincap.cc: Ditto.
+
2006-11-23 Corinna Vinschen <corinna@vinschen.de>
* security.h (DBGSID): Define for debugging purposes.
diff --git a/winsup/cygwin/cyglsa.h b/winsup/cygwin/cyglsa.h
new file mode 100644
index 000000000..4af9e8cd0
--- /dev/null
+++ b/winsup/cygwin/cyglsa.h
@@ -0,0 +1,149 @@
+/* cyglsa.h: Header file for Cygwin LSA authentication
+
+ Copyright 2006 Red Hat, Inc.
+
+ Written by Corinna Vinschen <corinna@vinschen.de>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */
+
+#ifndef _CYGLSA_H
+#define _CYGLSA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CYG_LSA_PKGNAME "CygwinLsa"
+
+#define CYG_LSA_MAGIC 0x0379f014LU
+
+/* Datastructures not defined in w32api. */
+typedef PVOID *PLSA_CLIENT_REQUEST;
+
+typedef struct _SECPKG_CLIENT_INFO
+{
+ LUID LogonId;
+ ULONG ProcessID;
+ ULONG ThreadID;
+ BOOLEAN HasTcbPrivilege;
+ BOOLEAN Impersonating;
+ BOOLEAN Restricted;
+} SECPKG_CLIENT_INFO, *PSECPKG_CLIENT_INFO;
+
+/* The table returned by LsaApInitializePackage is actually a
+ LSA_SECPKG_FUNCTION_TABLE even though that's not documented.
+ We need only a subset of this table, basically the LSA_DISPATCH_TABLE
+ plus the pointer to the GetClientInfo function. */
+typedef struct _LSA_SECPKG_FUNCS
+{
+ NTSTATUS (NTAPI *CreateLogonSession)(PLUID);
+ NTSTATUS (NTAPI *DeleteLogonSession)(PLUID);
+ NTSTATUS (NTAPI *AddCredentials)(PVOID); /* wrong prototype, unused */
+ NTSTATUS (NTAPI *GetCredentials)(PVOID); /* wrong prototype, unused */
+ NTSTATUS (NTAPI *DeleteCredentials)(PVOID); /* wrong prototype, unused */
+ PVOID (NTAPI *AllocateLsaHeap)(ULONG);
+ VOID (NTAPI *FreeLsaHeap)(PVOID);
+ NTSTATUS (NTAPI *AllocateClientBuffer)(PLSA_CLIENT_REQUEST, ULONG, PVOID *);
+ NTSTATUS (NTAPI *FreeClientBuffer)(PLSA_CLIENT_REQUEST, PVOID);
+ NTSTATUS (NTAPI *CopyToClientBuffer)(PLSA_CLIENT_REQUEST, ULONG,
+ PVOID, PVOID);
+ NTSTATUS (NTAPI *CopyFromClientBuffer)(PLSA_CLIENT_REQUEST, ULONG,
+ PVOID, PVOID);
+ NTSTATUS (NTAPI *ImpersonateClient)(VOID);
+ NTSTATUS (NTAPI *UnloadPackage)(VOID);
+ NTSTATUS (NTAPI *DuplicateHandle)(HANDLE,PHANDLE);
+ NTSTATUS (NTAPI *SaveSupplementalCredentials)(VOID);
+ NTSTATUS (NTAPI *CreateThread)(PVOID); /* wrong prototype, unused */
+ NTSTATUS (NTAPI *GetClientInfo)(PSECPKG_CLIENT_INFO);
+} LSA_SECPKG_FUNCS, *PLSA_SECPKG_FUNCS;
+
+typedef enum _LSA_TOKEN_INFORMATION_TYPE
+{
+ LsaTokenInformationNull,
+ LsaTokenInformationV1,
+ LsaTokenInformationV2
+} LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
+
+typedef struct _LSA_TOKEN_INFORMATION_V2
+{
+ LARGE_INTEGER ExpirationTime;
+ TOKEN_USER User;
+ PTOKEN_GROUPS Groups;
+ TOKEN_PRIMARY_GROUP PrimaryGroup;
+ PTOKEN_PRIVILEGES Privileges;
+ TOKEN_OWNER Owner;
+ TOKEN_DEFAULT_DACL DefaultDacl;
+} LSA_TOKEN_INFORMATION_V2, *PLSA_TOKEN_INFORMATION_V2;
+
+/* These structures are eqivalent to the appropriate Windows structures,
+ using 32 bit offsets instead of pointers. These datastructures are
+ used to transfer the logon information to the LSA authentication package.
+ We can't use the LSA_TOKEN_INFORMATION_V2 structure directly, because
+ its size differs between 32 bit and 64 bit Windows. */
+
+typedef DWORD OFFSET;
+
+typedef struct _CYG_SID_AND_ATTRIBUTES
+{
+ OFFSET Sid;
+ DWORD Attributes;
+} CYG_SID_AND_ATTRIBUTES, *PCYG_SID_AND_ATTRIBUTES;
+
+typedef struct _CYG_TOKEN_USER
+{
+ CYG_SID_AND_ATTRIBUTES User;
+} CYG_TOKEN_USER, *PCYG_TOKEN_USER;
+
+typedef struct _CYG_TOKEN_GROUPS
+{
+ DWORD GroupCount;
+ CYG_SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
+} CYG_TOKEN_GROUPS, *PCYG_TOKEN_GROUPS;
+
+typedef struct _CYG_TOKEN_PRIMARY_GROUP
+{
+ OFFSET PrimaryGroup;
+} CYG_TOKEN_PRIMARY_GROUP, *PCYG_TOKEN_PRIMARY_GROUP;
+
+typedef struct _CYG_TOKEN_OWNER
+{
+ OFFSET Owner;
+} CYG_TOKEN_OWNER, *PCYG_TOKEN_OWNER;
+
+typedef struct _CYG_TOKEN_DEFAULT_DACL
+{
+ OFFSET DefaultDacl;
+} CYG_TOKEN_DEFAULT_DACL, *PCYG_TOKEN_DEFAULT_DACL;
+
+typedef struct _CYG_LSA_TOKEN_INFORMATION
+{
+ LARGE_INTEGER ExpirationTime;
+ CYG_TOKEN_USER User;
+ OFFSET Groups;
+ CYG_TOKEN_PRIMARY_GROUP PrimaryGroup;
+ OFFSET Privileges;
+ CYG_TOKEN_OWNER Owner;
+ CYG_TOKEN_DEFAULT_DACL DefaultDacl;
+} CYG_LSA_TOKEN_INFORMATION, *PCYG_LSA_TOKEN_INFORMATION;
+
+/* This is the structure created by security.cc:lsaauth(), which is given to
+ LsaApLogonUser to create the token information returned to the LSA. */
+typedef struct
+{
+ DWORD magic;
+ DWORD checksum;
+ CHAR username[UNLEN + 1];
+ CHAR domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ ULONG inf_size;
+ CYG_LSA_TOKEN_INFORMATION inf;
+ BYTE data[1];
+} cyglsa_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CYGLSA_H */
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 58b1e5070..ec4edf521 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -34,7 +34,9 @@ extern bool ignore_case_with_glob;
extern bool allow_winsymlinks;
extern bool strip_title_path;
extern int pcheck_case;
+#if 0
extern int subauth_id;
+#endif
bool reset_com = false;
static bool envcache = true;
#ifdef USE_SERVER
@@ -530,6 +532,7 @@ codepage_init (const char *buf)
debug_printf ("Wrong codepage name: %s", buf);
}
+#if 0
static void
subauth_id_init (const char *buf)
{
@@ -542,6 +545,7 @@ subauth_id_init (const char *buf)
if (i > 127 && i != 132 && i <= 255)
subauth_id = i;
}
+#endif
static void
set_chunksize (const char *buf)
@@ -620,7 +624,9 @@ static struct parse_thing
#endif
{"smbntsec", {func: set_smbntsec}, isfunc, NULL, {{0}, {s: "yes"}}},
{"strip_title", {&strip_title_path}, justset, NULL, {{false}, {true}}},
+#if 0
{"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}},
+#endif
{"title", {&display_title}, justset, NULL, {{false}, {true}}},
{"traverse", {func: set_traverse}, isfunc, NULL, {{0}, {s: "yes"}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index 20698ad5f..13d334a5d 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -348,7 +348,7 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
cygsid sid;
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
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] &&
sid != well_known_world_sid)
{
@@ -484,10 +484,10 @@ initgroups32 (const char *name, __gid32_t gid)
if (!get_server_groups (tmp_gsids, usersid, pw))
goto out;
tmp_gsids += grpsid;
- cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count);
- for (int i = 0; i < tmp_gsids.count; i++)
+ cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count ());
+ for (int i = 0; i < tmp_gsids.count (); i++)
new_gsids.sids[i] = tmp_gsids.sids[i];
- new_gsids.count = tmp_gsids.count;
+ new_gsids.count (tmp_gsids.count ());
cygheap->user.groups.update_supp (new_gsids);
}
ret = 0;
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index ecb19fc2b..f1caf487d 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -67,15 +67,8 @@ MKSID (well_known_system_sid, "S-1-5-18",
MKSID (well_known_admins_sid, "S-1-5-32-544",
SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS);
-
-#define SECURITY_MANDATORY_INTEGRITY_AUTHORITY {0,0,0,0,0,16}
-
-MKSID (mandatory_medium_integrity_sid, "S-1-64-8192",
- SECURITY_MANDATORY_INTEGRITY_AUTHORITY, 1, 8192);
-MKSID (mandatory_high_integrity_sid, "S-1-64-12288",
- SECURITY_MANDATORY_INTEGRITY_AUTHORITY, 1, 12288);
-MKSID (mandatory_system_integrity_sid, "S-1-64-16384",
- SECURITY_MANDATORY_INTEGRITY_AUTHORITY, 1, 16384);
+MKSID (fake_logon_sid, "S-1-5-5-0-0",
+ SECURITY_NT_AUTHORITY, 3, SECURITY_LOGON_IDS_RID, 0, 0);
bool
cygpsid::operator== (const char *nsidstr) const
@@ -135,7 +128,7 @@ cygpsid::string (char *nsidstr) const
}
PSID
-cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
+cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known)
{
DWORD i;
SID_IDENTIFIER_AUTHORITY sid_auth = {0,0,0,0,0,0};
@@ -150,11 +143,12 @@ cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
InitializeSid (psid, &sid_auth, cnt);
for (i = 0; i < cnt; ++i)
memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
+ well_known_sid = well_known;
return psid;
}
const PSID
-cygsid::getfromstr (const char *nsidstr)
+cygsid::getfromstr (const char *nsidstr, bool well_known)
{
char *lasts;
DWORD s, cnt = 0;
@@ -166,7 +160,7 @@ cygsid::getfromstr (const char *nsidstr)
while (cnt < 8 && *lasts == '-')
r[cnt++] = strtoul (lasts + 1, &lasts, 10);
if (!*lasts)
- return get_sid (s, cnt, r);
+ return get_sid (s, cnt, r, well_known);
}
return psid = NO_SID;
}
@@ -185,6 +179,48 @@ cygsid::getfromgr (const struct __group32 *gr)
return (*this = sp) != NULL;
}
+cygsid *
+cygsidlist::alloc_sids (int n)
+{
+ if (n > 0)
+ return (cygsid *) cmalloc (HEAP_STR, n * sizeof (cygsid));
+ else
+ return NULL;
+}
+
+void
+cygsidlist::free_sids ()
+{
+ if (sids)
+ cfree (sids);
+ sids = NULL;
+ cnt = maxcnt = 0;
+ type = cygsidlist_empty;
+}
+
+BOOL
+cygsidlist::add (const PSID nsi, bool well_known)
+{
+ if (contains (nsi))
+ return TRUE;
+ if (cnt >= maxcnt)
+ {
+ cygsid *tmp = new cygsid [2 * maxcnt];
+ if (!tmp)
+ return FALSE;
+ maxcnt *= 2;
+ for (int i = 0; i < cnt; ++i)
+ tmp[i] = sids[i];
+ delete [] sids;
+ sids = tmp;
+ }
+ if (well_known)
+ sids[cnt++] *= nsi;
+ else
+ sids[cnt++] = nsi;
+ return TRUE;
+}
+
bool
get_sids_info (cygpsid owner_sid, cygpsid group_sid, __uid32_t * uidret, __gid32_t * gidret)
{
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 96d903f79..79c3c2f50 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -41,6 +41,8 @@ details. */
#include "ntdll.h"
#include "lm.h"
#include "pwdgrp.h"
+#include "cyglsa.h"
+#include <cygwin/version.h>
bool allow_ntsec;
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
@@ -48,25 +50,6 @@ bool allow_ntsec;
bool allow_smbntsec;
bool allow_traverse;
-cygsid *
-cygsidlist::alloc_sids (int n)
-{
- if (n > 0)
- return (cygsid *) cmalloc (HEAP_STR, n * sizeof (cygsid));
- else
- return NULL;
-}
-
-void
-cygsidlist::free_sids ()
-{
- if (sids)
- cfree (sids);
- sids = NULL;
- count = maxcount = 0;
- type = cygsidlist_empty;
-}
-
extern "C" void
cygwin_set_impersonation_token (const HANDLE hToken)
{
@@ -346,7 +329,7 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
Note: Allowing those groups in our group list renders external
tokens invalid, so that it becomes impossible to logon with
password and valid logon token. */
- for (int glidx = 0; glidx < grp_list.count; ++glidx)
+ for (int glidx = 0; glidx < grp_list.count (); ++glidx)
if ((buf[bidx].lgrmi1_sidusage == SidTypeGroup
|| buf[bidx].lgrmi1_sidusage == SidTypeWellKnownGroup)
&& EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi1_sid))
@@ -409,8 +392,7 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
}
if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use);
- else if (!grp_list.contains (gsid))
- grp_list += gsid;
+ grp_list *= gsid;
}
NetApiBufferFree (buf);
return true;
@@ -480,7 +462,7 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
goto found;
continue;
found:
- if (gsid.getfromgr (gr) && !grp_list.contains (gsid))
+ if (gsid.getfromgr (gr))
grp_list += gsid;
}
@@ -498,26 +480,26 @@ get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
/*if (sid_in_token_groups (my_grps, well_known_local_sid))*/
grp_list += well_known_local_sid;
if (sid_in_token_groups (my_grps, well_known_dialup_sid))
- grp_list += well_known_dialup_sid;
+ grp_list *= well_known_dialup_sid;
if (sid_in_token_groups (my_grps, well_known_network_sid))
- grp_list += well_known_network_sid;
+ grp_list *= well_known_network_sid;
if (sid_in_token_groups (my_grps, well_known_batch_sid))
- grp_list += well_known_batch_sid;
+ grp_list *= well_known_batch_sid;
/* This is a problem on 2K3 (only domain controllers?!?) which only
enables tools for selected special groups. A subauth token is
only NETWORK, but NETWORK has no access to these tools. Therefore
we always add INTERACTIVE here. */
/*if (sid_in_token_groups (my_grps, well_known_interactive_sid))*/
- grp_list += well_known_interactive_sid;
+ grp_list *= well_known_interactive_sid;
if (sid_in_token_groups (my_grps, well_known_service_sid))
- grp_list += well_known_service_sid;
+ grp_list *= well_known_service_sid;
if (sid_in_token_groups (my_grps, well_known_this_org_sid))
- grp_list += well_known_this_org_sid;
+ grp_list *= well_known_this_org_sid;
}
else
{
grp_list += well_known_local_sid;
- grp_list += well_known_interactive_sid;
+ grp_list *= well_known_interactive_sid;
}
if (get_ll (auth_luid) != 999LL) /* != SYSTEM_LUID */
{
@@ -525,7 +507,7 @@ get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
if (my_grps->Groups[i].Attributes & SE_GROUP_LOGON_ID)
{
grp_list += my_grps->Groups[i].Sid;
- auth_pos = grp_list.count - 1;
+ auth_pos = grp_list.count () - 1;
break;
}
}
@@ -541,22 +523,24 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
if (well_known_system_sid == usersid)
{
- grp_list += well_known_admins_sid;
+ grp_list *= well_known_admins_sid;
get_unix_group_sidlist (pw, grp_list);
return true;
}
- if (!grp_list.contains (well_known_world_sid))
- grp_list += well_known_world_sid;
- if (!grp_list.contains (well_known_authenticated_users_sid))
- grp_list += well_known_authenticated_users_sid;
+ 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);
- get_unix_group_sidlist (pw, grp_list);
- return get_user_local_groups (grp_list, usersid);
+ if (get_user_local_groups (grp_list, usersid))
+ {
+ get_unix_group_sidlist (pw, grp_list);
+ return true;
+ }
+ return false;
}
static bool
@@ -564,8 +548,8 @@ get_initgroups_sidlist (cygsidlist &grp_list,
PSID usersid, PSID pgrpsid, struct passwd *pw,
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos)
{
- grp_list += well_known_world_sid;
- grp_list += well_known_authenticated_users_sid;
+ grp_list *= well_known_world_sid;
+ grp_list *= well_known_authenticated_users_sid;
if (well_known_system_sid == usersid)
auth_pos = -1;
else
@@ -574,24 +558,22 @@ get_initgroups_sidlist (cygsidlist &grp_list,
return false;
/* special_pgrp true if pgrpsid is not in normal groups */
- if (!grp_list.contains (pgrpsid))
- grp_list += pgrpsid;
+ grp_list += pgrpsid;
return true;
}
static void
-get_setgroups_sidlist (cygsidlist &tmp_list, PTOKEN_GROUPS my_grps,
- user_groups &groups, LUID auth_luid, int &auth_pos)
+get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, struct passwd *pw,
+ PTOKEN_GROUPS my_grps, user_groups &groups,
+ LUID auth_luid, int &auth_pos)
{
- PSID pgpsid = groups.pgsid;
- tmp_list += well_known_world_sid;
- tmp_list += well_known_authenticated_users_sid;
+ tmp_list *= well_known_world_sid;
+ tmp_list *= well_known_authenticated_users_sid;
get_token_group_sidlist (tmp_list, my_grps, auth_luid, auth_pos);
- for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
- if (!tmp_list.contains (groups.sgsids.sids[gidx]))
- tmp_list += groups.sgsids.sids[gidx];
- if (!groups.sgsids.contains (pgpsid))
- tmp_list += pgpsid;
+ get_server_groups (tmp_list, usersid, pw);
+ for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
+ tmp_list += groups.sgsids.sids[gidx];
+ tmp_list += groups.pgsid;
}
static const cygpriv_idx sys_privs[] = {
@@ -628,13 +610,13 @@ static const cygpriv_idx sys_privs[] = {
#define SYSTEM_PRIVILEGES_COUNT (sizeof sys_privs / sizeof *sys_privs)
-PTOKEN_PRIVILEGES
-get_system_priv_list (cygsidlist &grp_list)
+static PTOKEN_PRIVILEGES
+get_system_priv_list (cygsidlist &grp_list, size_t &size)
{
const LUID *priv;
- PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES)
- malloc (sizeof (ULONG)
- + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES));
+ size = sizeof (ULONG)
+ + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES);
+ PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (size);
if (!privs)
{
debug_printf ("malloc (system_privs) failed.");
@@ -653,8 +635,9 @@ get_system_priv_list (cygsidlist &grp_list)
return privs;
}
-PTOKEN_PRIVILEGES
-get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
+static PTOKEN_PRIVILEGES
+get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list,
+ size_t &size)
{
PLSA_UNICODE_STRING privstrs;
ULONG cnt;
@@ -663,9 +646,9 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
char buf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
if (usersid == well_known_system_sid)
- return get_system_priv_list (grp_list);
+ return get_system_priv_list (grp_list, size);
- for (int grp = -1; grp < grp_list.count; ++grp)
+ for (int grp = -1; grp < grp_list.count (); ++grp)
{
if (grp == -1)
{
@@ -699,9 +682,9 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
}
tmp_count = privs ? privs->PrivilegeCount : 0;
- tmp = (PTOKEN_PRIVILEGES)
- realloc (privs, sizeof (ULONG) +
- (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
+ size = sizeof (DWORD)
+ + (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES);
+ tmp = (PTOKEN_PRIVILEGES) realloc (privs, size);
if (!tmp)
{
if (privs)
@@ -794,7 +777,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
{
cygsid gsid;
struct __group32 *gr;
- bool saw[groups.sgsids.count];
+ bool saw[groups.sgsids.count ()];
memset (saw, 0, sizeof(saw));
/* token groups found in /etc/group match the user.gsids ? */
@@ -811,7 +794,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
goto done;
}
/* user.sgsids groups must be in the token */
- for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
+ for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
if (!saw[gidx] && !sid_in_token_groups (my_grps, groups.sgsids.sids[gidx]))
goto done;
}
@@ -857,6 +840,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
PTOKEN_GROUPS my_tok_gsids = NULL;
DWORD size;
+ size_t psize = 0;
/* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
push_self_privilege (SE_CREATE_TOKEN_PRIV, true);
@@ -929,8 +913,8 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
/* Create list of groups, the user is member in. */
int auth_pos;
if (new_groups.issetgroups ())
- get_setgroups_sidlist (tmp_gsids, my_tok_gsids, new_groups, auth_luid,
- auth_pos);
+ get_setgroups_sidlist (tmp_gsids, usersid, pw, my_tok_gsids, new_groups,
+ auth_luid, auth_pos);
else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw,
my_tok_gsids, auth_luid, auth_pos))
goto out;
@@ -940,9 +924,9 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
/* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
new_tok_gsids = (PTOKEN_GROUPS)
- alloca (sizeof (ULONG) + (tmp_gsids.count + 1 )
+ alloca (sizeof (DWORD) + tmp_gsids.count ()
* sizeof (SID_AND_ATTRIBUTES));
- new_tok_gsids->GroupCount = tmp_gsids.count;
+ new_tok_gsids->GroupCount = tmp_gsids.count ();
for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i)
{
new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i];
@@ -952,42 +936,8 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
}
if (auth_pos >= 0)
new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID;
-
- /* On systems supporting Mandatory Integrity Control, add a MIC SID. */
- if (wincap.has_mandatory_integrity_control ())
- {
- bool add_mic_sid = true;
- new_tok_gsids->Groups[new_tok_gsids->GroupCount].Attributes = 0;
-
- /* The subauth token usually contains a MIC SID. Copy it into our
- group SID list. */
- if (my_tok_gsids)
- for (DWORD i = 0; i < my_tok_gsids->GroupCount; ++i)
- if (EqualPrefixSid (mandatory_medium_integrity_sid,
- my_tok_gsids->Groups[i].Sid))
- {
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = my_tok_gsids->Groups[i].Sid;
- add_mic_sid = false;
- break;
- }
- /* If no MIC SID was available add a matching one for the account type. */
- if (add_mic_sid)
- {
- if (usersid == well_known_system_sid)
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_system_integrity_sid;
- else if (tmp_gsids.contains (well_known_admins_sid))
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_high_integrity_sid;
- else
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_medium_integrity_sid;
- }
- }
-
/* Retrieve list of privileges of that user. */
- if (!privs && !(privs = get_priv_list (lsa, usersid, tmp_gsids)))
+ if (!privs && !(privs = get_priv_list (lsa, usersid, tmp_gsids, psize)))
goto out;
/* Let's be heroic... */
@@ -1023,10 +973,16 @@ out:
free (my_tok_gsids);
close_local_policy (lsa);
- debug_printf ("%d = create_token ()", primary_token);
+ debug_printf ("0x%x = create_token ()", primary_token);
return primary_token;
}
+/* Subauthentication gets useless now that real LSA authentication is
+ available. The accompanying code in seteuid32 and environ.cc is
+ also disabled.
+ TODO: Deprecate and delete code entirely.
+ TODO: Delete from documentation. */
+#if 0
extern "C"
{
BOOL WINAPI Wow64DisableWow64FsRedirection (PVOID *);
@@ -1047,7 +1003,7 @@ HANDLE
subauth (struct passwd *pw)
{
LSA_STRING name;
- HANDLE lsa_hdl;
+ HANDLE lsa_hdl = NULL;
LSA_OPERATIONAL_MODE sec_mode;
NTSTATUS ret, ret2;
ULONG package_id, size;
@@ -1141,7 +1097,6 @@ subauth (struct passwd *pw)
{
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret));
- LsaDeregisterLogonProcess (lsa_hdl);
goto out;
}
/* Create origin. */
@@ -1170,7 +1125,6 @@ subauth (struct passwd *pw)
{
debug_printf ("LsaLogonUser: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret));
- LsaDeregisterLogonProcess (lsa_hdl);
goto out;
}
LsaFreeReturnBuffer (profile);
@@ -1180,11 +1134,254 @@ subauth (struct passwd *pw)
__seterrno ();
out:
+ if (lsa_hdl)
+ LsaDeregisterLogonProcess (lsa_hdl);
pop_self_privilege ();
if (user_token)
CloseHandle (user_token);
return primary_token;
}
+#endif
+
+HANDLE
+lsaauth (cygsid &usersid, user_groups &new_groups, struct passwd *pw)
+{
+ cygsidlist tmp_gsids (cygsidlist_auto, 12);
+ cygpsid pgrpsid;
+ LSA_STRING name;
+ HANDLE lsa_hdl = NULL, lsa;
+ LSA_OPERATIONAL_MODE sec_mode;
+ NTSTATUS ret, ret2;
+ ULONG package_id, size;
+ LUID auth_luid = SYSTEM_LUID;
+ struct {
+ LSA_STRING str;
+ CHAR buf[16];
+ } origin;
+ cyglsa_t *authinf = NULL;
+ ULONG authinf_size;
+ TOKEN_SOURCE ts;
+ PCYG_TOKEN_GROUPS gsids = NULL;
+ PTOKEN_PRIVILEGES privs = NULL;
+ PACL dacl = NULL;
+ PVOID profile = NULL;
+ LUID luid;
+ QUOTA_LIMITS quota;
+ size_t psize = 0, gsize = 0, dsize = 0;
+ OFFSET offset, sids_offset;
+ int tmpidx, non_well_known_cnt;
+
+ HANDLE user_token = NULL;
+
+ push_self_privilege (SE_TCB_PRIV, true);
+
+ /* Register as logon process. */
+ str2lsa (name, "Cygwin");
+ SetLastError (0);
+ ret = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaRegisterLogonProcess: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+ else if (GetLastError () == ERROR_PROC_NOT_FOUND)
+ {
+ debug_printf ("Couldn't load Secur32.dll");
+ goto out;
+ }
+ /* Get handle to our own LSA package. */
+ str2lsa (name, CYG_LSA_PKGNAME);
+ ret = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLookupAuthenticationPackage: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+
+ /* Open policy object. */
+ if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE)
+ goto out;
+
+ /* Create origin. */
+ str2buf2lsa (origin.str, origin.buf, "Cygwin");
+ /* Create token source. */
+ memcpy (ts.SourceName, "Cygwin.1", 8);
+ ts.SourceIdentifier.HighPart = 0;
+ ts.SourceIdentifier.LowPart = 0x0103;
+
+ /* Create list of groups, the user is member in. */
+ int auth_pos;
+ if (new_groups.issetgroups ())
+ get_setgroups_sidlist (tmp_gsids, usersid, pw, NULL, new_groups, auth_luid,
+ auth_pos);
+ else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw,
+ NULL, auth_luid, auth_pos))
+ goto out;
+ /* The logon SID entry is not generated automatically on Windows 2000
+ and earlier for some reason. So add fake logon sid here, which is
+ filled with logon id values in the authentication package. */
+ if (wincap.needs_logon_sid_in_sid_list ())
+ tmp_gsids += fake_logon_sid;
+
+ tmp_gsids.debug_print ("tmp_gsids");
+
+ /* Evaluate size of TOKEN_GROUPS list */
+ non_well_known_cnt = tmp_gsids.non_well_known_count ();
+ gsize = sizeof (DWORD) + non_well_known_cnt * sizeof (SID_AND_ATTRIBUTES);
+ tmpidx = -1;
+ for (int i = 0; i < non_well_known_cnt; ++i)
+ if ((tmpidx = tmp_gsids.next_non_well_known_sid (tmpidx)) >= 0)
+ gsize += GetLengthSid (tmp_gsids.sids[tmpidx]);
+
+ /* Retrieve list of privileges of that user. */
+ if (!(privs = get_priv_list (lsa, usersid, tmp_gsids, psize)))
+ goto out;
+
+ /* Create DefaultDacl. */
+ dsize = sizeof (ACL) + 3 * sizeof (ACCESS_ALLOWED_ACE)
+ + GetLengthSid (usersid)
+ + GetLengthSid (well_known_admins_sid)
+ + GetLengthSid (well_known_system_sid);
+ dacl = (PACL) alloca (dsize);
+ if (!InitializeAcl (dacl, dsize, ACL_REVISION))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL, usersid))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL,
+ well_known_admins_sid))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL,
+ well_known_system_sid))
+ goto out;
+
+ /* Evaluate authinf size and allocate authinf. */
+ authinf_size = (authinf->data - (PBYTE) authinf);
+ authinf_size += GetLengthSid (usersid); /* User SID */
+ authinf_size += gsize; /* Groups + Group SIDs */
+ /* When trying to define the admins group as primary group on Vista,
+ LsaLogonUser fails with error STATUS_INVALID_OWNER. As workaround
+ we define "Local" as primary group here. First, this adds the otherwise
+ missing "Local" group to the group list and second, seteuid32
+ sets the primary group to the group set in /etc/passwd anyway. */
+ pgrpsid = well_known_local_sid;
+ authinf_size += GetLengthSid (pgrpsid); /* Primary Group SID */
+
+ authinf_size += psize; /* Privileges */
+ authinf_size += 0; /* Owner SID */
+ authinf_size += dsize; /* Default DACL */
+
+ authinf = (cyglsa_t *) alloca (authinf_size);
+ authinf->inf_size = authinf_size - ((PBYTE) &authinf->inf - (PBYTE) authinf);
+
+ authinf->magic = CYG_LSA_MAGIC;
+
+ extract_nt_dom_user (pw, authinf->domain, authinf->username);
+
+ /* Store stuff in authinf with offset relative to start of "inf" member,
+ instead of using pointers. */
+ offset = authinf->data - (PBYTE) &authinf->inf;
+
+ authinf->inf.ExpirationTime.LowPart = 0xffffffffL;
+ authinf->inf.ExpirationTime.HighPart = 0x7fffffffL;
+ /* User SID */
+ authinf->inf.User.User.Sid = offset;
+ authinf->inf.User.User.Attributes = 0;
+ CopySid (GetLengthSid (usersid), (PSID) ((PBYTE) &authinf->inf + offset),
+ usersid);
+ offset += GetLengthSid (usersid);
+ /* Groups */
+ authinf->inf.Groups = offset;
+ gsids = (PCYG_TOKEN_GROUPS) ((PBYTE) &authinf->inf + offset);
+ sids_offset = offset + sizeof (ULONG) + non_well_known_cnt
+ * sizeof (SID_AND_ATTRIBUTES);
+ gsids->GroupCount = non_well_known_cnt;
+ /* Group SIDs */
+ tmpidx = -1;
+ for (int i = 0; i < non_well_known_cnt; ++i)
+ {
+ if ((tmpidx = tmp_gsids.next_non_well_known_sid (tmpidx)) < 0)
+ break;
+ gsids->Groups[i].Sid = sids_offset;
+ gsids->Groups[i].Attributes = SE_GROUP_MANDATORY
+ | SE_GROUP_ENABLED_BY_DEFAULT
+ | SE_GROUP_ENABLED;
+ /* Mark logon SID as logon SID :) */
+ if (wincap.needs_logon_sid_in_sid_list ()
+ && tmp_gsids.sids[tmpidx] == fake_logon_sid)
+ gsids->Groups[i].Attributes += SE_GROUP_LOGON_ID;
+ CopySid (GetLengthSid (tmp_gsids.sids[tmpidx]),
+ (PSID) ((PBYTE) &authinf->inf + sids_offset),
+ tmp_gsids.sids[tmpidx]);
+ sids_offset += GetLengthSid (tmp_gsids.sids[tmpidx]);
+ }
+ offset += gsize;
+ /* Primary Group SID */
+ authinf->inf.PrimaryGroup.PrimaryGroup = offset;
+ CopySid (GetLengthSid (pgrpsid), (PSID) ((PBYTE) &authinf->inf + offset),
+ pgrpsid);
+ offset += GetLengthSid (pgrpsid);
+ /* Privileges */
+ authinf->inf.Privileges = offset;
+ memcpy ((PBYTE) &authinf->inf + offset, privs, psize);
+ offset += psize;
+ /* Owner */
+ authinf->inf.Owner.Owner = 0;
+ /* Default DACL */
+ authinf->inf.DefaultDacl.DefaultDacl = offset;
+ memcpy ((PBYTE) &authinf->inf + offset, dacl, dsize);
+
+ authinf->checksum = CYGWIN_VERSION_MAGIC (CYGWIN_VERSION_DLL_MAJOR,
+ CYGWIN_VERSION_DLL_MINOR);
+ PDWORD csp = (PDWORD) &authinf->username;
+ PDWORD csp_end = (PDWORD) ((PBYTE) authinf + authinf_size);
+ while (csp < csp_end)
+ authinf->checksum += *csp++;
+
+ /* Try to logon... */
+ ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Interactive, package_id,
+ authinf, authinf_size, NULL, &ts, &profile, &size, &luid,
+ &user_token, &quota, &ret2);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLogonUser: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+ if (profile)
+ LsaFreeReturnBuffer (profile);
+
+ if (wincap.has_mandatory_integrity_control ())
+ {
+ typedef struct _TOKEN_LINKED_TOKEN
+ {
+ HANDLE LinkedToken;
+ } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
+# define TokenLinkedToken ((TOKEN_INFORMATION_CLASS) 19)
+
+ TOKEN_LINKED_TOKEN linked;
+
+ if (GetTokenInformation (user_token, TokenLinkedToken,
+ (PVOID) &linked, sizeof linked, &size))
+ {
+ debug_printf ("Linked Token: %lu", linked.LinkedToken);
+ if (linked.LinkedToken)
+ user_token = linked.LinkedToken;
+ }
+ }
+
+out:
+ if (privs)
+ free (privs);
+ close_local_policy (lsa);
+ if (lsa_hdl)
+ LsaDeregisterLogonProcess (lsa_hdl);
+ pop_self_privilege ();
+
+ debug_printf ("0x%x = lsaauth ()", user_token);
+ return user_token;
+}
/* read_sd reads a security descriptor from a file.
In case of error, -1 is returned and errno is set.
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 0f0fdb049..9823ca2b4 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -80,11 +80,12 @@ public:
class cygsid : public cygpsid {
char sbuf[MAX_SID_LEN];
+ bool well_known_sid;
- const PSID getfromstr (const char *nsidstr);
- PSID get_sid (DWORD s, DWORD cnt, DWORD *r);
+ const PSID getfromstr (const char *nsidstr, bool well_known);
+ PSID get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known);
- inline const PSID assign (const PSID nsid)
+ inline const PSID assign (const PSID nsid, bool well_known)
{
if (!nsid)
psid = NO_SID;
@@ -92,21 +93,32 @@ class cygsid : public cygpsid {
{
psid = (PSID) sbuf;
CopySid (MAX_SID_LEN, psid, nsid);
+ well_known_sid = well_known;
}
return psid;
}
public:
inline operator const PSID () { return psid; }
+ inline bool is_well_known_sid () { return well_known_sid; }
+ /* Both, = and *= are assignment operators. = creates a "normal" SID,
+ *= marks the SID as being a well-known SID. This difference is
+ important when creating a SID list for LSA authentication. */
inline const PSID operator= (cygsid &nsid)
- { return assign (nsid); }
+ { return assign (nsid, nsid.well_known_sid); }
inline const PSID operator= (const PSID nsid)
- { return assign (nsid); }
+ { return assign (nsid, false); }
inline const PSID operator= (const char *nsidstr)
- { return getfromstr (nsidstr); }
-
- inline cygsid () : cygpsid ((PSID) sbuf) {}
+ { return getfromstr (nsidstr, false); }
+ inline const PSID operator*= (cygsid &nsid)
+ { return assign (nsid, true); }
+ inline const PSID operator*= (const PSID nsid)
+ { return assign (nsid, true); }
+ inline const PSID operator*= (const char *nsidstr)
+ { return getfromstr (nsidstr, true); }
+
+ inline cygsid () : cygpsid ((PSID) sbuf), well_known_sid (false) {}
inline cygsid (const PSID nsid) { *this = nsid; }
inline cygsid (const char *nstrsid) { *this = nstrsid; }
@@ -114,21 +126,28 @@ public:
BOOL getfrompw (const struct passwd *pw);
BOOL getfromgr (const struct __group32 *gr);
+
+ void debug_print (const char *prefix = NULL) const
+ {
+ char buf[256] __attribute__ ((unused));
+ debug_printf ("%s %s%s", prefix ?: "", string (buf) ?: "NULL", well_known_sid ? " (*)" : " (+)");
+ }
};
typedef enum { cygsidlist_empty, cygsidlist_alloc, cygsidlist_auto } cygsidlist_type;
class cygsidlist {
- int maxcount;
+ int maxcnt;
+ int cnt;
+
+ BOOL add (const PSID nsi, bool well_known); /* Only with auto for now */
+
public:
- int count;
cygsid *sids;
cygsidlist_type type;
cygsidlist (cygsidlist_type t, int m)
+ : maxcnt (m), cnt (0), type (t)
{
- type = t;
- count = 0;
- maxcount = m;
if (t == cygsidlist_alloc)
sids = alloc_sids (m);
else
@@ -136,49 +155,56 @@ public:
}
~cygsidlist () { if (type == cygsidlist_auto) delete [] sids; }
- BOOL add (const PSID nsi) /* Only with auto for now */
+ BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
+ { return sids[cnt].getfromgr (gr) && ++cnt; }
+
+ /* += adds a "normal" SID, *= adds a well-known SID. See comment in class
+ cygsid above. */
+ BOOL operator+= (cygsid &si) { return add ((PSID) si, false); }
+ BOOL operator+= (const char *sidstr) { cygsid nsi (sidstr);
+ return add ((PSID) nsi, false); }
+ BOOL operator+= (const PSID psid) { return add (psid, false); }
+ BOOL operator*= (cygsid &si) { return add ((PSID) si, true); }
+ BOOL operator*= (const char *sidstr) { cygsid nsi (sidstr);
+ return add ((PSID) nsi, true); }
+ BOOL operator*= (const PSID psid) { return add (psid, true); }
+
+ void count (int ncnt)
+ { cnt = ncnt; }
+ int count () const { return cnt; }
+ int non_well_known_count () const
{
- if (count >= maxcount)
- {
- cygsid *tmp = new cygsid [ 2 * maxcount];
- if (!tmp)
- return FALSE;
- maxcount *= 2;
- for (int i = 0; i < count; ++i)
- tmp[i] = sids[i];
- delete [] sids;
- sids = tmp;
- }
- sids[count++] = nsi;
- return TRUE;
+ int wcnt = 0;
+ for (int i = 0; i < cnt; ++i)
+ if (!sids[i].is_well_known_sid ())
+ ++wcnt;
+ return wcnt;
}
- BOOL add (cygsid &nsi) { return add ((PSID) nsi); }
- BOOL add (const char *sidstr)
- { cygsid nsi (sidstr); return add (nsi); }
- BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
- { return sids[count].getfromgr (gr) && ++count; }
-
- BOOL operator+= (cygsid &si) { return add (si); }
- BOOL operator+= (const char *sidstr) { return add (sidstr); }
- BOOL operator+= (const PSID psid) { return add (psid); }
int position (const PSID sid) const
{
- for (int i = 0; i < count; ++i)
+ for (int i = 0; i < cnt; ++i)
if (sids[i] == sid)
return i;
return -1;
}
+ int next_non_well_known_sid (int idx)
+ {
+ while (++idx < cnt)
+ if (!sids[idx].is_well_known_sid ())
+ return idx;
+ return -1;
+ }
BOOL contains (const PSID sid) const { return position (sid) >= 0; }
cygsid *alloc_sids (int n);
void free_sids ();
void debug_print (const char *prefix = NULL) const
{
debug_printf ("-- begin sidlist ---");
- if (!count)
+ if (!cnt)
debug_printf ("No elements");
- for (int i = 0; i < count; ++i)
+ for (int i = 0; i < cnt; ++i)
sids[i].debug_print (prefix);
debug_printf ("-- ende sidlist ---");
}
@@ -256,9 +282,7 @@ extern cygpsid well_known_authenticated_users_sid;
extern cygpsid well_known_this_org_sid;
extern cygpsid well_known_system_sid;
extern cygpsid well_known_admins_sid;
-extern cygpsid mandatory_medium_integrity_sid;
-extern cygpsid mandatory_high_integrity_sid;
-extern cygpsid mandatory_system_integrity_sid;
+extern cygpsid fake_logon_sid;
/* Order must be same as cygpriv in sec_helper.cc. */
enum cygpriv_idx {
@@ -348,11 +372,15 @@ struct _UNICODE_STRING;
void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3)));
void __stdcall str2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2)));
-/* Try a subauthentication. */
-HANDLE subauth (struct passwd *pw);
-/* Try creating a token directly. */
+/* Function creating a token by calling NtCreateToken. */
HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw,
HANDLE subauth_token);
+#if 0
+/* Subauthentication function. */
+HANDLE subauth (struct passwd *pw);
+#endif
+/* LSA authentication function. */
+HANDLE lsaauth (cygsid &, user_groups &, struct passwd *);
/* Verify an existing token */
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
/* Get groups of a user */
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 241efd490..91c696073 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2111,30 +2111,46 @@ seteuid32 (__uid32_t uid)
debug_printf ("Found token %d", new_token);
/* If no impersonation token is available, try to
- authenticate using NtCreateToken () or subauthentication. */
+ authenticate using NtCreateToken () or LSA authentication. */
if (new_token == INVALID_HANDLE_VALUE)
{
- new_token = subauth (pw_new);
- debug_printf ("subauth %s, try create_token.",
- new_token == INVALID_HANDLE_VALUE ? "failed" : "succeeded");
- HANDLE new_token2 = create_token (usersid, groups, pw_new, new_token);
- if (new_token2 == INVALID_HANDLE_VALUE)
- {
+ if (!(new_token = lsaauth (usersid, groups, pw_new)))
+ {
+#if 0
+ new_token = subauth (pw_new);
+ debug_printf ("subauth %s, try create_token.",
+ new_token == INVALID_HANDLE_VALUE ? "failed" : "succeeded");
+ HANDLE new_token2 = create_token (usersid, groups, pw_new, new_token);
+ if (new_token2 == INVALID_HANDLE_VALUE)
+ {
+ if (new_token == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("create_token failed, bail out of here");
+ cygheap->user.reimpersonate ();
+ return -1;
+ }
+ debug_printf ("create_token failed, use original subauth token");
+ }
+ else
+ {
+ debug_printf ("create_token succeeded");
+ if (new_token != INVALID_HANDLE_VALUE)
+ CloseHandle (new_token);
+ new_token = new_token2;
+ }
+#else
+ debug_printf ("lsaauth failed, try create_token.");
+ new_token = create_token (usersid, groups, pw_new,
+ INVALID_HANDLE_VALUE);
if (new_token == INVALID_HANDLE_VALUE)
{
debug_printf ("create_token failed, bail out of here");
cygheap->user.reimpersonate ();
return -1;
}
- debug_printf ("create_token failed, use original subauth token");
- }
- else
- {
- debug_printf ("create_token succeeded");
- if (new_token != INVALID_HANDLE_VALUE)
- CloseHandle (new_token);
- new_token = new_token2;
+#endif
}
+
/* Keep at most one internal token */
if (cygheap->user.internal_token != NO_IMPERSONATION)
CloseHandle (cygheap->user.internal_token);
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 8879f9e06..85405bae1 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -69,6 +69,7 @@ static NO_COPY wincaps wincap_unknown = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_95 = {
@@ -129,6 +130,7 @@ static NO_COPY wincaps wincap_95 = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_95osr2 = {
@@ -189,6 +191,7 @@ static NO_COPY wincaps wincap_95osr2 = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_98 = {
@@ -249,6 +252,7 @@ static NO_COPY wincaps wincap_98 = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_98se = {
@@ -309,6 +313,7 @@ static NO_COPY wincaps wincap_98se = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_me = {
@@ -369,6 +374,7 @@ static NO_COPY wincaps wincap_me = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_nt3 = {
@@ -429,6 +435,7 @@ static NO_COPY wincaps wincap_nt3 = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:true,
};
static NO_COPY wincaps wincap_nt4 = {
@@ -489,6 +496,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_exclusiveaddruse:false,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:true,
};
static NO_COPY wincaps wincap_nt4sp4 = {
@@ -549,6 +557,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_exclusiveaddruse:true,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:true,
};
static NO_COPY wincaps wincap_2000 = {
@@ -609,6 +618,7 @@ static NO_COPY wincaps wincap_2000 = {
has_exclusiveaddruse:true,
has_buggy_restart_scan:true,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:true,
};
static NO_COPY wincaps wincap_xp = {
@@ -669,6 +679,7 @@ static NO_COPY wincaps wincap_xp = {
has_exclusiveaddruse:true,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_2003 = {
@@ -729,6 +740,7 @@ static NO_COPY wincaps wincap_2003 = {
has_exclusiveaddruse:true,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:false,
+ needs_logon_sid_in_sid_list:false,
};
static NO_COPY wincaps wincap_vista = {
@@ -789,6 +801,7 @@ static NO_COPY wincaps wincap_vista = {
has_exclusiveaddruse:true,
has_buggy_restart_scan:false,
has_mandatory_integrity_control:true,
+ needs_logon_sid_in_sid_list:false,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 63f87422b..d40d12c1a 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -70,6 +70,7 @@ struct wincaps
unsigned has_exclusiveaddruse : 1;
unsigned has_buggy_restart_scan : 1;
unsigned has_mandatory_integrity_control : 1;
+ unsigned needs_logon_sid_in_sid_list : 1;
};
class wincapc
@@ -146,6 +147,7 @@ public:
bool IMPLEMENT (has_exclusiveaddruse)
bool IMPLEMENT (has_buggy_restart_scan)
bool IMPLEMENT (has_mandatory_integrity_control)
+ bool IMPLEMENT (needs_logon_sid_in_sid_list)
#undef IMPLEMENT
};