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

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-11-27 15:59:59 +0300
committerCorinna Vinschen <corinna@vinschen.de>2006-11-27 15:59:59 +0300
commitb825c587ba9e851002570b81f9f35196b7a96100 (patch)
tree4f45a13329a6ac1cf399647ba96988538ccba0bf /winsup/cygwin/security.cc
parentb6bb405954f9713a2153e08dfc781f9146a42b9d (diff)
* 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.
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r--winsup/cygwin/security.cc415
1 files changed, 306 insertions, 109 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 96d903f79..79c3c2f50 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -41,6 +41,8 @@ details. */
#include "ntdll.h"
#include "lm.h"
#include "pwdgrp.h"
+#include "cyglsa.h"
+#include <cygwin/version.h>
bool allow_ntsec;
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
@@ -48,25 +50,6 @@ bool allow_ntsec;
bool allow_smbntsec;
bool allow_traverse;
-cygsid *
-cygsidlist::alloc_sids (int n)
-{
- if (n > 0)
- return (cygsid *) cmalloc (HEAP_STR, n * sizeof (cygsid));
- else
- return NULL;
-}
-
-void
-cygsidlist::free_sids ()
-{
- if (sids)
- cfree (sids);
- sids = NULL;
- count = maxcount = 0;
- type = cygsidlist_empty;
-}
-
extern "C" void
cygwin_set_impersonation_token (const HANDLE hToken)
{
@@ -346,7 +329,7 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
Note: Allowing those groups in our group list renders external
tokens invalid, so that it becomes impossible to logon with
password and valid logon token. */
- for (int glidx = 0; glidx < grp_list.count; ++glidx)
+ for (int glidx = 0; glidx < grp_list.count (); ++glidx)
if ((buf[bidx].lgrmi1_sidusage == SidTypeGroup
|| buf[bidx].lgrmi1_sidusage == SidTypeWellKnownGroup)
&& EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi1_sid))
@@ -409,8 +392,7 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
}
if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use);
- else if (!grp_list.contains (gsid))
- grp_list += gsid;
+ grp_list *= gsid;
}
NetApiBufferFree (buf);
return true;
@@ -480,7 +462,7 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
goto found;
continue;
found:
- if (gsid.getfromgr (gr) && !grp_list.contains (gsid))
+ if (gsid.getfromgr (gr))
grp_list += gsid;
}
@@ -498,26 +480,26 @@ get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
/*if (sid_in_token_groups (my_grps, well_known_local_sid))*/
grp_list += well_known_local_sid;
if (sid_in_token_groups (my_grps, well_known_dialup_sid))
- grp_list += well_known_dialup_sid;
+ grp_list *= well_known_dialup_sid;
if (sid_in_token_groups (my_grps, well_known_network_sid))
- grp_list += well_known_network_sid;
+ grp_list *= well_known_network_sid;
if (sid_in_token_groups (my_grps, well_known_batch_sid))
- grp_list += well_known_batch_sid;
+ grp_list *= well_known_batch_sid;
/* This is a problem on 2K3 (only domain controllers?!?) which only
enables tools for selected special groups. A subauth token is
only NETWORK, but NETWORK has no access to these tools. Therefore
we always add INTERACTIVE here. */
/*if (sid_in_token_groups (my_grps, well_known_interactive_sid))*/
- grp_list += well_known_interactive_sid;
+ grp_list *= well_known_interactive_sid;
if (sid_in_token_groups (my_grps, well_known_service_sid))
- grp_list += well_known_service_sid;
+ grp_list *= well_known_service_sid;
if (sid_in_token_groups (my_grps, well_known_this_org_sid))
- grp_list += well_known_this_org_sid;
+ grp_list *= well_known_this_org_sid;
}
else
{
grp_list += well_known_local_sid;
- grp_list += well_known_interactive_sid;
+ grp_list *= well_known_interactive_sid;
}
if (get_ll (auth_luid) != 999LL) /* != SYSTEM_LUID */
{
@@ -525,7 +507,7 @@ get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
if (my_grps->Groups[i].Attributes & SE_GROUP_LOGON_ID)
{
grp_list += my_grps->Groups[i].Sid;
- auth_pos = grp_list.count - 1;
+ auth_pos = grp_list.count () - 1;
break;
}
}
@@ -541,22 +523,24 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
if (well_known_system_sid == usersid)
{
- grp_list += well_known_admins_sid;
+ grp_list *= well_known_admins_sid;
get_unix_group_sidlist (pw, grp_list);
return true;
}
- if (!grp_list.contains (well_known_world_sid))
- grp_list += well_known_world_sid;
- if (!grp_list.contains (well_known_authenticated_users_sid))
- grp_list += well_known_authenticated_users_sid;
+ grp_list *= well_known_world_sid;
+ grp_list *= well_known_authenticated_users_sid;
extract_nt_dom_user (pw, domain, user);
if (get_logon_server (domain, server, wserver, false)
&& !get_user_groups (wserver, grp_list, user, domain)
&& get_logon_server (domain, server, wserver, true))
get_user_groups (wserver, grp_list, user, domain);
- get_unix_group_sidlist (pw, grp_list);
- return get_user_local_groups (grp_list, usersid);
+ if (get_user_local_groups (grp_list, usersid))
+ {
+ get_unix_group_sidlist (pw, grp_list);
+ return true;
+ }
+ return false;
}
static bool
@@ -564,8 +548,8 @@ get_initgroups_sidlist (cygsidlist &grp_list,
PSID usersid, PSID pgrpsid, struct passwd *pw,
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos)
{
- grp_list += well_known_world_sid;
- grp_list += well_known_authenticated_users_sid;
+ grp_list *= well_known_world_sid;
+ grp_list *= well_known_authenticated_users_sid;
if (well_known_system_sid == usersid)
auth_pos = -1;
else
@@ -574,24 +558,22 @@ get_initgroups_sidlist (cygsidlist &grp_list,
return false;
/* special_pgrp true if pgrpsid is not in normal groups */
- if (!grp_list.contains (pgrpsid))
- grp_list += pgrpsid;
+ grp_list += pgrpsid;
return true;
}
static void
-get_setgroups_sidlist (cygsidlist &tmp_list, PTOKEN_GROUPS my_grps,
- user_groups &groups, LUID auth_luid, int &auth_pos)
+get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, struct passwd *pw,
+ PTOKEN_GROUPS my_grps, user_groups &groups,
+ LUID auth_luid, int &auth_pos)
{
- PSID pgpsid = groups.pgsid;
- tmp_list += well_known_world_sid;
- tmp_list += well_known_authenticated_users_sid;
+ tmp_list *= well_known_world_sid;
+ tmp_list *= well_known_authenticated_users_sid;
get_token_group_sidlist (tmp_list, my_grps, auth_luid, auth_pos);
- for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
- if (!tmp_list.contains (groups.sgsids.sids[gidx]))
- tmp_list += groups.sgsids.sids[gidx];
- if (!groups.sgsids.contains (pgpsid))
- tmp_list += pgpsid;
+ get_server_groups (tmp_list, usersid, pw);
+ for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
+ tmp_list += groups.sgsids.sids[gidx];
+ tmp_list += groups.pgsid;
}
static const cygpriv_idx sys_privs[] = {
@@ -628,13 +610,13 @@ static const cygpriv_idx sys_privs[] = {
#define SYSTEM_PRIVILEGES_COUNT (sizeof sys_privs / sizeof *sys_privs)
-PTOKEN_PRIVILEGES
-get_system_priv_list (cygsidlist &grp_list)
+static PTOKEN_PRIVILEGES
+get_system_priv_list (cygsidlist &grp_list, size_t &size)
{
const LUID *priv;
- PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES)
- malloc (sizeof (ULONG)
- + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES));
+ size = sizeof (ULONG)
+ + SYSTEM_PRIVILEGES_COUNT * sizeof (LUID_AND_ATTRIBUTES);
+ PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (size);
if (!privs)
{
debug_printf ("malloc (system_privs) failed.");
@@ -653,8 +635,9 @@ get_system_priv_list (cygsidlist &grp_list)
return privs;
}
-PTOKEN_PRIVILEGES
-get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
+static PTOKEN_PRIVILEGES
+get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list,
+ size_t &size)
{
PLSA_UNICODE_STRING privstrs;
ULONG cnt;
@@ -663,9 +646,9 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
char buf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
if (usersid == well_known_system_sid)
- return get_system_priv_list (grp_list);
+ return get_system_priv_list (grp_list, size);
- for (int grp = -1; grp < grp_list.count; ++grp)
+ for (int grp = -1; grp < grp_list.count (); ++grp)
{
if (grp == -1)
{
@@ -699,9 +682,9 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
}
tmp_count = privs ? privs->PrivilegeCount : 0;
- tmp = (PTOKEN_PRIVILEGES)
- realloc (privs, sizeof (ULONG) +
- (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
+ size = sizeof (DWORD)
+ + (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES);
+ tmp = (PTOKEN_PRIVILEGES) realloc (privs, size);
if (!tmp)
{
if (privs)
@@ -794,7 +777,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
{
cygsid gsid;
struct __group32 *gr;
- bool saw[groups.sgsids.count];
+ bool saw[groups.sgsids.count ()];
memset (saw, 0, sizeof(saw));
/* token groups found in /etc/group match the user.gsids ? */
@@ -811,7 +794,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
goto done;
}
/* user.sgsids groups must be in the token */
- for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
+ for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
if (!saw[gidx] && !sid_in_token_groups (my_grps, groups.sgsids.sids[gidx]))
goto done;
}
@@ -857,6 +840,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
PTOKEN_GROUPS my_tok_gsids = NULL;
DWORD size;
+ size_t psize = 0;
/* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
push_self_privilege (SE_CREATE_TOKEN_PRIV, true);
@@ -929,8 +913,8 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
/* Create list of groups, the user is member in. */
int auth_pos;
if (new_groups.issetgroups ())
- get_setgroups_sidlist (tmp_gsids, my_tok_gsids, new_groups, auth_luid,
- auth_pos);
+ get_setgroups_sidlist (tmp_gsids, usersid, pw, my_tok_gsids, new_groups,
+ auth_luid, auth_pos);
else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw,
my_tok_gsids, auth_luid, auth_pos))
goto out;
@@ -940,9 +924,9 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
/* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
new_tok_gsids = (PTOKEN_GROUPS)
- alloca (sizeof (ULONG) + (tmp_gsids.count + 1 )
+ alloca (sizeof (DWORD) + tmp_gsids.count ()
* sizeof (SID_AND_ATTRIBUTES));
- new_tok_gsids->GroupCount = tmp_gsids.count;
+ new_tok_gsids->GroupCount = tmp_gsids.count ();
for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i)
{
new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i];
@@ -952,42 +936,8 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw,
}
if (auth_pos >= 0)
new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID;
-
- /* On systems supporting Mandatory Integrity Control, add a MIC SID. */
- if (wincap.has_mandatory_integrity_control ())
- {
- bool add_mic_sid = true;
- new_tok_gsids->Groups[new_tok_gsids->GroupCount].Attributes = 0;
-
- /* The subauth token usually contains a MIC SID. Copy it into our
- group SID list. */
- if (my_tok_gsids)
- for (DWORD i = 0; i < my_tok_gsids->GroupCount; ++i)
- if (EqualPrefixSid (mandatory_medium_integrity_sid,
- my_tok_gsids->Groups[i].Sid))
- {
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = my_tok_gsids->Groups[i].Sid;
- add_mic_sid = false;
- break;
- }
- /* If no MIC SID was available add a matching one for the account type. */
- if (add_mic_sid)
- {
- if (usersid == well_known_system_sid)
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_system_integrity_sid;
- else if (tmp_gsids.contains (well_known_admins_sid))
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_high_integrity_sid;
- else
- new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
- = mandatory_medium_integrity_sid;
- }
- }
-
/* Retrieve list of privileges of that user. */
- if (!privs && !(privs = get_priv_list (lsa, usersid, tmp_gsids)))
+ if (!privs && !(privs = get_priv_list (lsa, usersid, tmp_gsids, psize)))
goto out;
/* Let's be heroic... */
@@ -1023,10 +973,16 @@ out:
free (my_tok_gsids);
close_local_policy (lsa);
- debug_printf ("%d = create_token ()", primary_token);
+ debug_printf ("0x%x = create_token ()", primary_token);
return primary_token;
}
+/* Subauthentication gets useless now that real LSA authentication is
+ available. The accompanying code in seteuid32 and environ.cc is
+ also disabled.
+ TODO: Deprecate and delete code entirely.
+ TODO: Delete from documentation. */
+#if 0
extern "C"
{
BOOL WINAPI Wow64DisableWow64FsRedirection (PVOID *);
@@ -1047,7 +1003,7 @@ HANDLE
subauth (struct passwd *pw)
{
LSA_STRING name;
- HANDLE lsa_hdl;
+ HANDLE lsa_hdl = NULL;
LSA_OPERATIONAL_MODE sec_mode;
NTSTATUS ret, ret2;
ULONG package_id, size;
@@ -1141,7 +1097,6 @@ subauth (struct passwd *pw)
{
debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret));
- LsaDeregisterLogonProcess (lsa_hdl);
goto out;
}
/* Create origin. */
@@ -1170,7 +1125,6 @@ subauth (struct passwd *pw)
{
debug_printf ("LsaLogonUser: %d", ret);
__seterrno_from_win_error (LsaNtStatusToWinError (ret));
- LsaDeregisterLogonProcess (lsa_hdl);
goto out;
}
LsaFreeReturnBuffer (profile);
@@ -1180,11 +1134,254 @@ subauth (struct passwd *pw)
__seterrno ();
out:
+ if (lsa_hdl)
+ LsaDeregisterLogonProcess (lsa_hdl);
pop_self_privilege ();
if (user_token)
CloseHandle (user_token);
return primary_token;
}
+#endif
+
+HANDLE
+lsaauth (cygsid &usersid, user_groups &new_groups, struct passwd *pw)
+{
+ cygsidlist tmp_gsids (cygsidlist_auto, 12);
+ cygpsid pgrpsid;
+ LSA_STRING name;
+ HANDLE lsa_hdl = NULL, lsa;
+ LSA_OPERATIONAL_MODE sec_mode;
+ NTSTATUS ret, ret2;
+ ULONG package_id, size;
+ LUID auth_luid = SYSTEM_LUID;
+ struct {
+ LSA_STRING str;
+ CHAR buf[16];
+ } origin;
+ cyglsa_t *authinf = NULL;
+ ULONG authinf_size;
+ TOKEN_SOURCE ts;
+ PCYG_TOKEN_GROUPS gsids = NULL;
+ PTOKEN_PRIVILEGES privs = NULL;
+ PACL dacl = NULL;
+ PVOID profile = NULL;
+ LUID luid;
+ QUOTA_LIMITS quota;
+ size_t psize = 0, gsize = 0, dsize = 0;
+ OFFSET offset, sids_offset;
+ int tmpidx, non_well_known_cnt;
+
+ HANDLE user_token = NULL;
+
+ push_self_privilege (SE_TCB_PRIV, true);
+
+ /* Register as logon process. */
+ str2lsa (name, "Cygwin");
+ SetLastError (0);
+ ret = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaRegisterLogonProcess: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+ else if (GetLastError () == ERROR_PROC_NOT_FOUND)
+ {
+ debug_printf ("Couldn't load Secur32.dll");
+ goto out;
+ }
+ /* Get handle to our own LSA package. */
+ str2lsa (name, CYG_LSA_PKGNAME);
+ ret = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLookupAuthenticationPackage: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+
+ /* Open policy object. */
+ if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE)
+ goto out;
+
+ /* Create origin. */
+ str2buf2lsa (origin.str, origin.buf, "Cygwin");
+ /* Create token source. */
+ memcpy (ts.SourceName, "Cygwin.1", 8);
+ ts.SourceIdentifier.HighPart = 0;
+ ts.SourceIdentifier.LowPart = 0x0103;
+
+ /* Create list of groups, the user is member in. */
+ int auth_pos;
+ if (new_groups.issetgroups ())
+ get_setgroups_sidlist (tmp_gsids, usersid, pw, NULL, new_groups, auth_luid,
+ auth_pos);
+ else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw,
+ NULL, auth_luid, auth_pos))
+ goto out;
+ /* The logon SID entry is not generated automatically on Windows 2000
+ and earlier for some reason. So add fake logon sid here, which is
+ filled with logon id values in the authentication package. */
+ if (wincap.needs_logon_sid_in_sid_list ())
+ tmp_gsids += fake_logon_sid;
+
+ tmp_gsids.debug_print ("tmp_gsids");
+
+ /* Evaluate size of TOKEN_GROUPS list */
+ non_well_known_cnt = tmp_gsids.non_well_known_count ();
+ gsize = sizeof (DWORD) + non_well_known_cnt * sizeof (SID_AND_ATTRIBUTES);
+ tmpidx = -1;
+ for (int i = 0; i < non_well_known_cnt; ++i)
+ if ((tmpidx = tmp_gsids.next_non_well_known_sid (tmpidx)) >= 0)
+ gsize += GetLengthSid (tmp_gsids.sids[tmpidx]);
+
+ /* Retrieve list of privileges of that user. */
+ if (!(privs = get_priv_list (lsa, usersid, tmp_gsids, psize)))
+ goto out;
+
+ /* Create DefaultDacl. */
+ dsize = sizeof (ACL) + 3 * sizeof (ACCESS_ALLOWED_ACE)
+ + GetLengthSid (usersid)
+ + GetLengthSid (well_known_admins_sid)
+ + GetLengthSid (well_known_system_sid);
+ dacl = (PACL) alloca (dsize);
+ if (!InitializeAcl (dacl, dsize, ACL_REVISION))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL, usersid))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL,
+ well_known_admins_sid))
+ goto out;
+ if (!AddAccessAllowedAce (dacl, ACL_REVISION, GENERIC_ALL,
+ well_known_system_sid))
+ goto out;
+
+ /* Evaluate authinf size and allocate authinf. */
+ authinf_size = (authinf->data - (PBYTE) authinf);
+ authinf_size += GetLengthSid (usersid); /* User SID */
+ authinf_size += gsize; /* Groups + Group SIDs */
+ /* When trying to define the admins group as primary group on Vista,
+ LsaLogonUser fails with error STATUS_INVALID_OWNER. As workaround
+ we define "Local" as primary group here. First, this adds the otherwise
+ missing "Local" group to the group list and second, seteuid32
+ sets the primary group to the group set in /etc/passwd anyway. */
+ pgrpsid = well_known_local_sid;
+ authinf_size += GetLengthSid (pgrpsid); /* Primary Group SID */
+
+ authinf_size += psize; /* Privileges */
+ authinf_size += 0; /* Owner SID */
+ authinf_size += dsize; /* Default DACL */
+
+ authinf = (cyglsa_t *) alloca (authinf_size);
+ authinf->inf_size = authinf_size - ((PBYTE) &authinf->inf - (PBYTE) authinf);
+
+ authinf->magic = CYG_LSA_MAGIC;
+
+ extract_nt_dom_user (pw, authinf->domain, authinf->username);
+
+ /* Store stuff in authinf with offset relative to start of "inf" member,
+ instead of using pointers. */
+ offset = authinf->data - (PBYTE) &authinf->inf;
+
+ authinf->inf.ExpirationTime.LowPart = 0xffffffffL;
+ authinf->inf.ExpirationTime.HighPart = 0x7fffffffL;
+ /* User SID */
+ authinf->inf.User.User.Sid = offset;
+ authinf->inf.User.User.Attributes = 0;
+ CopySid (GetLengthSid (usersid), (PSID) ((PBYTE) &authinf->inf + offset),
+ usersid);
+ offset += GetLengthSid (usersid);
+ /* Groups */
+ authinf->inf.Groups = offset;
+ gsids = (PCYG_TOKEN_GROUPS) ((PBYTE) &authinf->inf + offset);
+ sids_offset = offset + sizeof (ULONG) + non_well_known_cnt
+ * sizeof (SID_AND_ATTRIBUTES);
+ gsids->GroupCount = non_well_known_cnt;
+ /* Group SIDs */
+ tmpidx = -1;
+ for (int i = 0; i < non_well_known_cnt; ++i)
+ {
+ if ((tmpidx = tmp_gsids.next_non_well_known_sid (tmpidx)) < 0)
+ break;
+ gsids->Groups[i].Sid = sids_offset;
+ gsids->Groups[i].Attributes = SE_GROUP_MANDATORY
+ | SE_GROUP_ENABLED_BY_DEFAULT
+ | SE_GROUP_ENABLED;
+ /* Mark logon SID as logon SID :) */
+ if (wincap.needs_logon_sid_in_sid_list ()
+ && tmp_gsids.sids[tmpidx] == fake_logon_sid)
+ gsids->Groups[i].Attributes += SE_GROUP_LOGON_ID;
+ CopySid (GetLengthSid (tmp_gsids.sids[tmpidx]),
+ (PSID) ((PBYTE) &authinf->inf + sids_offset),
+ tmp_gsids.sids[tmpidx]);
+ sids_offset += GetLengthSid (tmp_gsids.sids[tmpidx]);
+ }
+ offset += gsize;
+ /* Primary Group SID */
+ authinf->inf.PrimaryGroup.PrimaryGroup = offset;
+ CopySid (GetLengthSid (pgrpsid), (PSID) ((PBYTE) &authinf->inf + offset),
+ pgrpsid);
+ offset += GetLengthSid (pgrpsid);
+ /* Privileges */
+ authinf->inf.Privileges = offset;
+ memcpy ((PBYTE) &authinf->inf + offset, privs, psize);
+ offset += psize;
+ /* Owner */
+ authinf->inf.Owner.Owner = 0;
+ /* Default DACL */
+ authinf->inf.DefaultDacl.DefaultDacl = offset;
+ memcpy ((PBYTE) &authinf->inf + offset, dacl, dsize);
+
+ authinf->checksum = CYGWIN_VERSION_MAGIC (CYGWIN_VERSION_DLL_MAJOR,
+ CYGWIN_VERSION_DLL_MINOR);
+ PDWORD csp = (PDWORD) &authinf->username;
+ PDWORD csp_end = (PDWORD) ((PBYTE) authinf + authinf_size);
+ while (csp < csp_end)
+ authinf->checksum += *csp++;
+
+ /* Try to logon... */
+ ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Interactive, package_id,
+ authinf, authinf_size, NULL, &ts, &profile, &size, &luid,
+ &user_token, &quota, &ret2);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLogonUser: %p", ret);
+ __seterrno_from_win_error (LsaNtStatusToWinError (ret));
+ goto out;
+ }
+ if (profile)
+ LsaFreeReturnBuffer (profile);
+
+ if (wincap.has_mandatory_integrity_control ())
+ {
+ typedef struct _TOKEN_LINKED_TOKEN
+ {
+ HANDLE LinkedToken;
+ } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
+# define TokenLinkedToken ((TOKEN_INFORMATION_CLASS) 19)
+
+ TOKEN_LINKED_TOKEN linked;
+
+ if (GetTokenInformation (user_token, TokenLinkedToken,
+ (PVOID) &linked, sizeof linked, &size))
+ {
+ debug_printf ("Linked Token: %lu", linked.LinkedToken);
+ if (linked.LinkedToken)
+ user_token = linked.LinkedToken;
+ }
+ }
+
+out:
+ if (privs)
+ free (privs);
+ close_local_policy (lsa);
+ if (lsa_hdl)
+ LsaDeregisterLogonProcess (lsa_hdl);
+ pop_self_privilege ();
+
+ debug_printf ("0x%x = lsaauth ()", user_token);
+ return user_token;
+}
/* read_sd reads a security descriptor from a file.
In case of error, -1 is returned and errno is set.