* 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.
This commit is contained in:
Corinna Vinschen 2006-11-27 12:59:59 +00:00
parent b6bb405954
commit b825c587ba
10 changed files with 685 additions and 184 deletions

View File

@ -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> 2006-11-23 Corinna Vinschen <corinna@vinschen.de>
* security.h (DBGSID): Define for debugging purposes. * security.h (DBGSID): Define for debugging purposes.

149
winsup/cygwin/cyglsa.h Normal file
View File

@ -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 */

View File

@ -34,7 +34,9 @@ extern bool ignore_case_with_glob;
extern bool allow_winsymlinks; extern bool allow_winsymlinks;
extern bool strip_title_path; extern bool strip_title_path;
extern int pcheck_case; extern int pcheck_case;
#if 0
extern int subauth_id; extern int subauth_id;
#endif
bool reset_com = false; bool reset_com = false;
static bool envcache = true; static bool envcache = true;
#ifdef USE_SERVER #ifdef USE_SERVER
@ -530,6 +532,7 @@ codepage_init (const char *buf)
debug_printf ("Wrong codepage name: %s", buf); debug_printf ("Wrong codepage name: %s", buf);
} }
#if 0
static void static void
subauth_id_init (const char *buf) subauth_id_init (const char *buf)
{ {
@ -542,6 +545,7 @@ subauth_id_init (const char *buf)
if (i > 127 && i != 132 && i <= 255) if (i > 127 && i != 132 && i <= 255)
subauth_id = i; subauth_id = i;
} }
#endif
static void static void
set_chunksize (const char *buf) set_chunksize (const char *buf)
@ -620,7 +624,9 @@ static struct parse_thing
#endif #endif
{"smbntsec", {func: set_smbntsec}, isfunc, NULL, {{0}, {s: "yes"}}}, {"smbntsec", {func: set_smbntsec}, isfunc, NULL, {{0}, {s: "yes"}}},
{"strip_title", {&strip_title_path}, justset, NULL, {{false}, {true}}}, {"strip_title", {&strip_title_path}, justset, NULL, {{false}, {true}}},
#if 0
{"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}}, {"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}},
#endif
{"title", {&display_title}, justset, NULL, {{false}, {true}}}, {"title", {&display_title}, justset, NULL, {{false}, {true}}},
{"traverse", {func: set_traverse}, isfunc, NULL, {{0}, {s: "yes"}}}, {"traverse", {func: set_traverse}, isfunc, NULL, {{0}, {s: "yes"}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}}, {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},

View File

@ -348,7 +348,7 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
cygsid sid; cygsid sid;
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)
{ {
@ -484,10 +484,10 @@ initgroups32 (const char *name, __gid32_t gid)
if (!get_server_groups (tmp_gsids, usersid, pw)) if (!get_server_groups (tmp_gsids, usersid, pw))
goto out; goto out;
tmp_gsids += grpsid; tmp_gsids += grpsid;
cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count); cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count ());
for (int i = 0; i < tmp_gsids.count; i++) for (int i = 0; i < tmp_gsids.count (); i++)
new_gsids.sids[i] = tmp_gsids.sids[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); cygheap->user.groups.update_supp (new_gsids);
} }
ret = 0; ret = 0;

View File

@ -67,15 +67,8 @@ MKSID (well_known_system_sid, "S-1-5-18",
MKSID (well_known_admins_sid, "S-1-5-32-544", MKSID (well_known_admins_sid, "S-1-5-32-544",
SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS); DOMAIN_ALIAS_RID_ADMINS);
MKSID (fake_logon_sid, "S-1-5-5-0-0",
#define SECURITY_MANDATORY_INTEGRITY_AUTHORITY {0,0,0,0,0,16} SECURITY_NT_AUTHORITY, 3, SECURITY_LOGON_IDS_RID, 0, 0);
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);
bool bool
cygpsid::operator== (const char *nsidstr) const cygpsid::operator== (const char *nsidstr) const
@ -135,7 +128,7 @@ cygpsid::string (char *nsidstr) const
} }
PSID PSID
cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r) cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r, bool well_known)
{ {
DWORD i; DWORD i;
SID_IDENTIFIER_AUTHORITY sid_auth = {0,0,0,0,0,0}; 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); InitializeSid (psid, &sid_auth, cnt);
for (i = 0; i < cnt; ++i) for (i = 0; i < cnt; ++i)
memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD)); memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
well_known_sid = well_known;
return psid; return psid;
} }
const PSID const PSID
cygsid::getfromstr (const char *nsidstr) cygsid::getfromstr (const char *nsidstr, bool well_known)
{ {
char *lasts; char *lasts;
DWORD s, cnt = 0; DWORD s, cnt = 0;
@ -166,7 +160,7 @@ cygsid::getfromstr (const char *nsidstr)
while (cnt < 8 && *lasts == '-') while (cnt < 8 && *lasts == '-')
r[cnt++] = strtoul (lasts + 1, &lasts, 10); r[cnt++] = strtoul (lasts + 1, &lasts, 10);
if (!*lasts) if (!*lasts)
return get_sid (s, cnt, r); return get_sid (s, cnt, r, well_known);
} }
return psid = NO_SID; return psid = NO_SID;
} }
@ -185,6 +179,48 @@ cygsid::getfromgr (const struct __group32 *gr)
return (*this = sp) != NULL; 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 bool
get_sids_info (cygpsid owner_sid, cygpsid group_sid, __uid32_t * uidret, __gid32_t * gidret) get_sids_info (cygpsid owner_sid, cygpsid group_sid, __uid32_t * uidret, __gid32_t * gidret)
{ {

View File

@ -41,6 +41,8 @@ details. */
#include "ntdll.h" #include "ntdll.h"
#include "lm.h" #include "lm.h"
#include "pwdgrp.h" #include "pwdgrp.h"
#include "cyglsa.h"
#include <cygwin/version.h>
bool allow_ntsec; bool allow_ntsec;
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check). /* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
@ -48,25 +50,6 @@ bool allow_ntsec;
bool allow_smbntsec; bool allow_smbntsec;
bool allow_traverse; 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 extern "C" void
cygwin_set_impersonation_token (const HANDLE hToken) 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 Note: Allowing those groups in our group list renders external
tokens invalid, so that it becomes impossible to logon with tokens invalid, so that it becomes impossible to logon with
password and valid logon token. */ 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 if ((buf[bidx].lgrmi1_sidusage == SidTypeGroup
|| buf[bidx].lgrmi1_sidusage == SidTypeWellKnownGroup) || buf[bidx].lgrmi1_sidusage == SidTypeWellKnownGroup)
&& EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi1_sid)) && 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)) if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, 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); NetApiBufferFree (buf);
return true; return true;
@ -480,7 +462,7 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
goto found; goto found;
continue; continue;
found: found:
if (gsid.getfromgr (gr) && !grp_list.contains (gsid)) if (gsid.getfromgr (gr))
grp_list += gsid; 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))*/ /*if (sid_in_token_groups (my_grps, well_known_local_sid))*/
grp_list += well_known_local_sid; grp_list += well_known_local_sid;
if (sid_in_token_groups (my_grps, well_known_dialup_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)) 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)) 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 /* This is a problem on 2K3 (only domain controllers?!?) which only
enables tools for selected special groups. A subauth token is enables tools for selected special groups. A subauth token is
only NETWORK, but NETWORK has no access to these tools. Therefore only NETWORK, but NETWORK has no access to these tools. Therefore
we always add INTERACTIVE here. */ we always add INTERACTIVE here. */
/*if (sid_in_token_groups (my_grps, well_known_interactive_sid))*/ /*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)) 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)) 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 else
{ {
grp_list += well_known_local_sid; 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 */ 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) if (my_grps->Groups[i].Attributes & SE_GROUP_LOGON_ID)
{ {
grp_list += my_grps->Groups[i].Sid; grp_list += my_grps->Groups[i].Sid;
auth_pos = grp_list.count - 1; auth_pos = grp_list.count () - 1;
break; break;
} }
} }
@ -541,22 +523,24 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
if (well_known_system_sid == usersid) 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); get_unix_group_sidlist (pw, grp_list);
return true; return true;
} }
if (!grp_list.contains (well_known_world_sid)) grp_list *= well_known_world_sid;
grp_list += well_known_world_sid; grp_list *= well_known_authenticated_users_sid;
if (!grp_list.contains (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) if (get_logon_server (domain, server, wserver, false)
&& !get_user_groups (wserver, grp_list, user, domain) && !get_user_groups (wserver, grp_list, user, domain)
&& get_logon_server (domain, server, wserver, true)) && get_logon_server (domain, server, wserver, true))
get_user_groups (wserver, grp_list, user, domain); get_user_groups (wserver, grp_list, user, domain);
get_unix_group_sidlist (pw, grp_list); if (get_user_local_groups (grp_list, usersid))
return get_user_local_groups (grp_list, usersid); {
get_unix_group_sidlist (pw, grp_list);
return true;
}
return false;
} }
static bool static bool
@ -564,8 +548,8 @@ get_initgroups_sidlist (cygsidlist &grp_list,
PSID usersid, PSID pgrpsid, struct passwd *pw, PSID usersid, PSID pgrpsid, struct passwd *pw,
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos) PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos)
{ {
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;
if (well_known_system_sid == usersid) if (well_known_system_sid == usersid)
auth_pos = -1; auth_pos = -1;
else else
@ -574,24 +558,22 @@ get_initgroups_sidlist (cygsidlist &grp_list,
return false; return false;
/* special_pgrp true if pgrpsid is not in normal groups */ /* special_pgrp true if pgrpsid is not in normal groups */
if (!grp_list.contains (pgrpsid)) grp_list += pgrpsid;
grp_list += pgrpsid;
return true; return true;
} }
static void static void
get_setgroups_sidlist (cygsidlist &tmp_list, PTOKEN_GROUPS my_grps, get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, struct passwd *pw,
user_groups &groups, LUID auth_luid, int &auth_pos) 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_world_sid; tmp_list *= well_known_authenticated_users_sid;
tmp_list += well_known_authenticated_users_sid;
get_token_group_sidlist (tmp_list, my_grps, auth_luid, auth_pos); get_token_group_sidlist (tmp_list, my_grps, auth_luid, auth_pos);
for (int gidx = 0; gidx < groups.sgsids.count; gidx++) get_server_groups (tmp_list, usersid, pw);
if (!tmp_list.contains (groups.sgsids.sids[gidx])) for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
tmp_list += groups.sgsids.sids[gidx]; tmp_list += groups.sgsids.sids[gidx];
if (!groups.sgsids.contains (pgpsid)) tmp_list += groups.pgsid;
tmp_list += pgpsid;
} }
static const cygpriv_idx sys_privs[] = { 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) #define SYSTEM_PRIVILEGES_COUNT (sizeof sys_privs / sizeof *sys_privs)
PTOKEN_PRIVILEGES static PTOKEN_PRIVILEGES
get_system_priv_list (cygsidlist &grp_list) get_system_priv_list (cygsidlist &grp_list, size_t &size)
{ {
const LUID *priv; const LUID *priv;
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) size = sizeof (ULONG)
malloc (sizeof (ULONG) + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES);
+ SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES)); PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (size);
if (!privs) if (!privs)
{ {
debug_printf ("malloc (system_privs) failed."); debug_printf ("malloc (system_privs) failed.");
@ -653,8 +635,9 @@ get_system_priv_list (cygsidlist &grp_list)
return privs; return privs;
} }
PTOKEN_PRIVILEGES static PTOKEN_PRIVILEGES
get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list,
size_t &size)
{ {
PLSA_UNICODE_STRING privstrs; PLSA_UNICODE_STRING privstrs;
ULONG cnt; 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]; char buf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
if (usersid == well_known_system_sid) 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) 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_count = privs ? privs->PrivilegeCount : 0;
tmp = (PTOKEN_PRIVILEGES) size = sizeof (DWORD)
realloc (privs, sizeof (ULONG) + + (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES);
(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES)); tmp = (PTOKEN_PRIVILEGES) realloc (privs, size);
if (!tmp) if (!tmp)
{ {
if (privs) if (privs)
@ -794,7 +777,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
{ {
cygsid gsid; cygsid gsid;
struct __group32 *gr; struct __group32 *gr;
bool saw[groups.sgsids.count]; bool saw[groups.sgsids.count ()];
memset (saw, 0, sizeof(saw)); memset (saw, 0, sizeof(saw));
/* token groups found in /etc/group match the user.gsids ? */ /* 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; goto done;
} }
/* user.sgsids groups must be in the token */ /* 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])) if (!saw[gidx] && !sid_in_token_groups (my_grps, groups.sgsids.sids[gidx]))
goto done; goto done;
} }
@ -857,6 +840,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
PTOKEN_GROUPS my_tok_gsids = NULL; PTOKEN_GROUPS my_tok_gsids = NULL;
DWORD size; DWORD size;
size_t psize = 0;
/* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
push_self_privilege (SE_CREATE_TOKEN_PRIV, true); 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. */ /* Create list of groups, the user is member in. */
int auth_pos; int auth_pos;
if (new_groups.issetgroups ()) if (new_groups.issetgroups ())
get_setgroups_sidlist (tmp_gsids, my_tok_gsids, new_groups, auth_luid, get_setgroups_sidlist (tmp_gsids, usersid, pw, my_tok_gsids, new_groups,
auth_pos); auth_luid, auth_pos);
else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw, else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw,
my_tok_gsids, auth_luid, auth_pos)) my_tok_gsids, auth_luid, auth_pos))
goto out; 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. */ /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
new_tok_gsids = (PTOKEN_GROUPS) new_tok_gsids = (PTOKEN_GROUPS)
alloca (sizeof (ULONG) + (tmp_gsids.count + 1 ) alloca (sizeof (DWORD) + tmp_gsids.count ()
* sizeof (SID_AND_ATTRIBUTES)); * 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) for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i)
{ {
new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[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) if (auth_pos >= 0)
new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID; 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. */ /* 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; goto out;
/* Let's be heroic... */ /* Let's be heroic... */
@ -1023,10 +973,16 @@ out:
free (my_tok_gsids); free (my_tok_gsids);
close_local_policy (lsa); close_local_policy (lsa);
debug_printf ("%d = create_token ()", primary_token); debug_printf ("0x%x = create_token ()", primary_token);
return 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" extern "C"
{ {
BOOL WINAPI Wow64DisableWow64FsRedirection (PVOID *); BOOL WINAPI Wow64DisableWow64FsRedirection (PVOID *);
@ -1047,7 +1003,7 @@ HANDLE
subauth (struct passwd *pw) subauth (struct passwd *pw)
{ {
LSA_STRING name; LSA_STRING name;
HANDLE lsa_hdl; HANDLE lsa_hdl = NULL;
LSA_OPERATIONAL_MODE sec_mode; LSA_OPERATIONAL_MODE sec_mode;
NTSTATUS ret, ret2; NTSTATUS ret, ret2;
ULONG package_id, size; ULONG package_id, size;
@ -1141,7 +1097,6 @@ subauth (struct passwd *pw)
{ {
debug_printf ("LsaLookupAuthenticationPackage: %d", ret); debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret)); __seterrno_from_win_error (LsaNtStatusToWinError (ret));
LsaDeregisterLogonProcess (lsa_hdl);
goto out; goto out;
} }
/* Create origin. */ /* Create origin. */
@ -1170,7 +1125,6 @@ subauth (struct passwd *pw)
{ {
debug_printf ("LsaLogonUser: %d", ret); debug_printf ("LsaLogonUser: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret)); __seterrno_from_win_error (LsaNtStatusToWinError (ret));
LsaDeregisterLogonProcess (lsa_hdl);
goto out; goto out;
} }
LsaFreeReturnBuffer (profile); LsaFreeReturnBuffer (profile);
@ -1180,11 +1134,254 @@ subauth (struct passwd *pw)
__seterrno (); __seterrno ();
out: out:
if (lsa_hdl)
LsaDeregisterLogonProcess (lsa_hdl);
pop_self_privilege (); pop_self_privilege ();
if (user_token) if (user_token)
CloseHandle (user_token); CloseHandle (user_token);
return primary_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. /* read_sd reads a security descriptor from a file.
In case of error, -1 is returned and errno is set. In case of error, -1 is returned and errno is set.

View File

@ -80,11 +80,12 @@ public:
class cygsid : public cygpsid { class cygsid : public cygpsid {
char sbuf[MAX_SID_LEN]; char sbuf[MAX_SID_LEN];
bool well_known_sid;
const PSID getfromstr (const char *nsidstr); const PSID getfromstr (const char *nsidstr, bool well_known);
PSID get_sid (DWORD s, DWORD cnt, DWORD *r); 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) if (!nsid)
psid = NO_SID; psid = NO_SID;
@ -92,21 +93,32 @@ class cygsid : public cygpsid {
{ {
psid = (PSID) sbuf; psid = (PSID) sbuf;
CopySid (MAX_SID_LEN, psid, nsid); CopySid (MAX_SID_LEN, psid, nsid);
well_known_sid = well_known;
} }
return psid; return psid;
} }
public: public:
inline operator const PSID () { return psid; } 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) inline const PSID operator= (cygsid &nsid)
{ return assign (nsid); } { return assign (nsid, nsid.well_known_sid); }
inline const PSID operator= (const PSID nsid) inline const PSID operator= (const PSID nsid)
{ return assign (nsid); } { return assign (nsid, false); }
inline const PSID operator= (const char *nsidstr) inline const PSID operator= (const char *nsidstr)
{ return getfromstr (nsidstr); } { 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) {} inline cygsid () : cygpsid ((PSID) sbuf), well_known_sid (false) {}
inline cygsid (const PSID nsid) { *this = nsid; } inline cygsid (const PSID nsid) { *this = nsid; }
inline cygsid (const char *nstrsid) { *this = nstrsid; } inline cygsid (const char *nstrsid) { *this = nstrsid; }
@ -114,21 +126,28 @@ public:
BOOL getfrompw (const struct passwd *pw); BOOL getfrompw (const struct passwd *pw);
BOOL getfromgr (const struct __group32 *gr); 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; typedef enum { cygsidlist_empty, cygsidlist_alloc, cygsidlist_auto } cygsidlist_type;
class cygsidlist { class cygsidlist {
int maxcount; int maxcnt;
int cnt;
BOOL add (const PSID nsi, bool well_known); /* Only with auto for now */
public: public:
int count;
cygsid *sids; cygsid *sids;
cygsidlist_type type; cygsidlist_type type;
cygsidlist (cygsidlist_type t, int m) cygsidlist (cygsidlist_type t, int m)
: maxcnt (m), cnt (0), type (t)
{ {
type = t;
count = 0;
maxcount = m;
if (t == cygsidlist_alloc) if (t == cygsidlist_alloc)
sids = alloc_sids (m); sids = alloc_sids (m);
else else
@ -136,49 +155,56 @@ public:
} }
~cygsidlist () { if (type == cygsidlist_auto) delete [] sids; } ~cygsidlist () { if (type == cygsidlist_auto) delete [] sids; }
BOOL add (const PSID nsi) /* Only with auto for now */
{
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;
}
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 */ BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
{ return sids[count].getfromgr (gr) && ++count; } { return sids[cnt].getfromgr (gr) && ++cnt; }
BOOL operator+= (cygsid &si) { return add (si); } /* += adds a "normal" SID, *= adds a well-known SID. See comment in class
BOOL operator+= (const char *sidstr) { return add (sidstr); } cygsid above. */
BOOL operator+= (const PSID psid) { return add (psid); } 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
{
int wcnt = 0;
for (int i = 0; i < cnt; ++i)
if (!sids[i].is_well_known_sid ())
++wcnt;
return wcnt;
}
int position (const PSID sid) const int position (const PSID sid) const
{ {
for (int i = 0; i < count; ++i) for (int i = 0; i < cnt; ++i)
if (sids[i] == sid) if (sids[i] == sid)
return i; return i;
return -1; 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; } BOOL contains (const PSID sid) const { return position (sid) >= 0; }
cygsid *alloc_sids (int n); cygsid *alloc_sids (int n);
void free_sids (); void free_sids ();
void debug_print (const char *prefix = NULL) const void debug_print (const char *prefix = NULL) const
{ {
debug_printf ("-- begin sidlist ---"); debug_printf ("-- begin sidlist ---");
if (!count) if (!cnt)
debug_printf ("No elements"); debug_printf ("No elements");
for (int i = 0; i < count; ++i) for (int i = 0; i < cnt; ++i)
sids[i].debug_print (prefix); sids[i].debug_print (prefix);
debug_printf ("-- ende sidlist ---"); 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_this_org_sid;
extern cygpsid well_known_system_sid; extern cygpsid well_known_system_sid;
extern cygpsid well_known_admins_sid; extern cygpsid well_known_admins_sid;
extern cygpsid mandatory_medium_integrity_sid; extern cygpsid fake_logon_sid;
extern cygpsid mandatory_high_integrity_sid;
extern cygpsid mandatory_system_integrity_sid;
/* Order must be same as cygpriv in sec_helper.cc. */ /* Order must be same as cygpriv in sec_helper.cc. */
enum cygpriv_idx { enum cygpriv_idx {
@ -348,11 +372,15 @@ struct _UNICODE_STRING;
void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3))); void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3)));
void __stdcall str2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2))); void __stdcall str2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2)));
/* Try a subauthentication. */ /* Function creating a token by calling NtCreateToken. */
HANDLE subauth (struct passwd *pw);
/* Try creating a token directly. */
HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw, HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw,
HANDLE subauth_token); 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 */ /* Verify an existing token */
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL); bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
/* Get groups of a user */ /* Get groups of a user */

View File

@ -2111,30 +2111,46 @@ seteuid32 (__uid32_t uid)
debug_printf ("Found token %d", new_token); debug_printf ("Found token %d", new_token);
/* If no impersonation token is available, try to /* 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) if (new_token == INVALID_HANDLE_VALUE)
{ {
new_token = subauth (pw_new); if (!(new_token = lsaauth (usersid, groups, pw_new)))
debug_printf ("subauth %s, try create_token.", {
new_token == INVALID_HANDLE_VALUE ? "failed" : "succeeded"); #if 0
HANDLE new_token2 = create_token (usersid, groups, pw_new, new_token); new_token = subauth (pw_new);
if (new_token2 == INVALID_HANDLE_VALUE) 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) if (new_token == INVALID_HANDLE_VALUE)
{ {
debug_printf ("create_token failed, bail out of here"); debug_printf ("create_token failed, bail out of here");
cygheap->user.reimpersonate (); cygheap->user.reimpersonate ();
return -1; return -1;
} }
debug_printf ("create_token failed, use original subauth token"); #endif
}
else
{
debug_printf ("create_token succeeded");
if (new_token != INVALID_HANDLE_VALUE)
CloseHandle (new_token);
new_token = new_token2;
} }
/* Keep at most one internal token */ /* Keep at most one internal token */
if (cygheap->user.internal_token != NO_IMPERSONATION) if (cygheap->user.internal_token != NO_IMPERSONATION)
CloseHandle (cygheap->user.internal_token); CloseHandle (cygheap->user.internal_token);

View File

@ -69,6 +69,7 @@ static NO_COPY wincaps wincap_unknown = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_95 = { static NO_COPY wincaps wincap_95 = {
@ -129,6 +130,7 @@ static NO_COPY wincaps wincap_95 = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_95osr2 = { static NO_COPY wincaps wincap_95osr2 = {
@ -189,6 +191,7 @@ static NO_COPY wincaps wincap_95osr2 = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_98 = { static NO_COPY wincaps wincap_98 = {
@ -249,6 +252,7 @@ static NO_COPY wincaps wincap_98 = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_98se = { static NO_COPY wincaps wincap_98se = {
@ -309,6 +313,7 @@ static NO_COPY wincaps wincap_98se = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_me = { static NO_COPY wincaps wincap_me = {
@ -369,6 +374,7 @@ static NO_COPY wincaps wincap_me = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_nt3 = { static NO_COPY wincaps wincap_nt3 = {
@ -429,6 +435,7 @@ static NO_COPY wincaps wincap_nt3 = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
}; };
static NO_COPY wincaps wincap_nt4 = { static NO_COPY wincaps wincap_nt4 = {
@ -489,6 +496,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_exclusiveaddruse:false, has_exclusiveaddruse:false,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
}; };
static NO_COPY wincaps wincap_nt4sp4 = { static NO_COPY wincaps wincap_nt4sp4 = {
@ -549,6 +557,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
}; };
static NO_COPY wincaps wincap_2000 = { static NO_COPY wincaps wincap_2000 = {
@ -609,6 +618,7 @@ static NO_COPY wincaps wincap_2000 = {
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_buggy_restart_scan:true, has_buggy_restart_scan:true,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
}; };
static NO_COPY wincaps wincap_xp = { static NO_COPY wincaps wincap_xp = {
@ -669,6 +679,7 @@ static NO_COPY wincaps wincap_xp = {
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_2003 = { static NO_COPY wincaps wincap_2003 = {
@ -729,6 +740,7 @@ static NO_COPY wincaps wincap_2003 = {
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:false, has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
}; };
static NO_COPY wincaps wincap_vista = { static NO_COPY wincaps wincap_vista = {
@ -789,6 +801,7 @@ static NO_COPY wincaps wincap_vista = {
has_exclusiveaddruse:true, has_exclusiveaddruse:true,
has_buggy_restart_scan:false, has_buggy_restart_scan:false,
has_mandatory_integrity_control:true, has_mandatory_integrity_control:true,
needs_logon_sid_in_sid_list:false,
}; };
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));

View File

@ -70,6 +70,7 @@ struct wincaps
unsigned has_exclusiveaddruse : 1; unsigned has_exclusiveaddruse : 1;
unsigned has_buggy_restart_scan : 1; unsigned has_buggy_restart_scan : 1;
unsigned has_mandatory_integrity_control : 1; unsigned has_mandatory_integrity_control : 1;
unsigned needs_logon_sid_in_sid_list : 1;
}; };
class wincapc class wincapc
@ -146,6 +147,7 @@ public:
bool IMPLEMENT (has_exclusiveaddruse) bool IMPLEMENT (has_exclusiveaddruse)
bool IMPLEMENT (has_buggy_restart_scan) bool IMPLEMENT (has_buggy_restart_scan)
bool IMPLEMENT (has_mandatory_integrity_control) bool IMPLEMENT (has_mandatory_integrity_control)
bool IMPLEMENT (needs_logon_sid_in_sid_list)
#undef IMPLEMENT #undef IMPLEMENT
}; };