* 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:
parent
b6bb405954
commit
b825c587ba
|
@ -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.
|
||||
|
|
|
@ -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 */
|
|
@ -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}}},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
if (get_user_local_groups (grp_list, usersid))
|
||||
{
|
||||
get_unix_group_sidlist (pw, grp_list);
|
||||
return get_user_local_groups (grp_list, usersid);
|
||||
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;
|
||||
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]))
|
||||
get_server_groups (tmp_list, usersid, pw);
|
||||
for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
|
||||
tmp_list += groups.sgsids.sids[gidx];
|
||||
if (!groups.sgsids.contains (pgpsid))
|
||||
tmp_list += pgpsid;
|
||||
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, "a, &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.
|
||||
|
|
|
@ -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); }
|
||||
{ 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 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 */
|
||||
{
|
||||
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 */
|
||||
{ return sids[count].getfromgr (gr) && ++count; }
|
||||
{ return sids[cnt].getfromgr (gr) && ++cnt; }
|
||||
|
||||
BOOL operator+= (cygsid &si) { return add (si); }
|
||||
BOOL operator+= (const char *sidstr) { return add (sidstr); }
|
||||
BOOL operator+= (const PSID psid) { return add (psid); }
|
||||
/* += 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
|
||||
{
|
||||
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
|
||||
{
|
||||
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 */
|
||||
|
|
|
@ -2111,9 +2111,12 @@ 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)
|
||||
{
|
||||
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");
|
||||
|
@ -2135,6 +2138,19 @@ seteuid32 (__uid32_t uid)
|
|||
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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Keep at most one internal token */
|
||||
if (cygheap->user.internal_token != NO_IMPERSONATION)
|
||||
CloseHandle (cygheap->user.internal_token);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue