* security.cc: Change some formatting.

* include/cygwin/version.h: Bump API minor version.

        * cygheap.h (class cygheap_user): Add member groups.
        * security.h (class cygsidlist): Add members type and maxcount,
        methods position, addfromgr, alloc_sids and free_sids and
        operator+= (const PSID psid). Modify contains () to call
        position () and optimize add () to use maxcount.
        (class user_groups): Create.
        Update declarations of verify_token and create_token.
        * security.cc (cygsidlist::alloc_sids): New.
        (cygsidlist::free_sids): New.
        (get_token_group_sidlist): Create from get_group_sidlist.
        (get_initgroups_sidlist): Create from get_group_sidlist.
        (get_group_sidlist): Suppress.
        (get_setgroups_sidlist): Create.
        (verify_token): Modify arguments. Add setgroups case.
        (create_token): Modify arguments. Call get_initgroups_sidlist and
        get_setgroups_sidlist as needed. Set SE_GROUP_LOGON_ID from auth_pos
        outside of the loop. Rename the various group sid lists consistently.
        * syscalls.cc (seteuid32): Modify to use cygheap->user.groups.
        (setegid32): Call cygheap->user.groups.update_pgrp.
        * grp.cc (setgroups): Create.
        (setgroups32): Create.
        * uinfo.cc (internal_getlogin): Initialize and update user.groups.pgsid.
        * cygwin.din: Add setgroups and setgroups32.
This commit is contained in:
Corinna Vinschen
2002-07-29 12:51:52 +00:00
parent eb5720f255
commit 5519d54352
9 changed files with 458 additions and 227 deletions

View File

@@ -47,6 +47,22 @@ BOOL allow_ntsec = true;
The default is TRUE to reflect the old behaviour. */
BOOL allow_smbntsec;
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);
}
extern "C" void
cygwin_set_impersonation_token (const HANDLE hToken)
{
@@ -64,7 +80,7 @@ extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
char *d, *u, *c;
domain[0] = 0;
strlcpy (user, pw->pw_name, UNLEN+1);
strlcpy (user, pw->pw_name, UNLEN + 1);
debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
if ((d = strstr (pw->pw_gecos, "U-")) != NULL &&
@@ -74,11 +90,11 @@ extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
if ((u = strchr (d + 2, '\\')) == NULL || (c != NULL && u > c))
u = d + 1;
else if (u - d <= INTERNET_MAX_HOST_NAME_LENGTH + 2)
strlcpy(domain, d + 2, u - d - 1);
strlcpy (domain, d + 2, u - d - 1);
if (c == NULL)
c = u + UNLEN + 1;
if (c - u <= UNLEN + 1)
strlcpy(user, u + 1, c - u);
strlcpy (user, u + 1, c - u);
}
if (domain[0])
return;
@@ -112,9 +128,9 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
extract_nt_dom_user (pw, nt_domain, nt_user);
debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken)
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken)
|| !SetHandleInformation (hToken,
HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
@@ -152,7 +168,7 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
sys_mbstowcs (buf, srcstr, tgt.MaximumLength);
}
#if 0 //unused
#if 0 /* unused */
static void
lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size)
{
@@ -194,7 +210,7 @@ close_local_policy (LSA_HANDLE &lsa)
lsa = INVALID_HANDLE_VALUE;
}
#if 0 // unused
#if 0 /* unused */
static BOOL
get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain)
{
@@ -226,7 +242,8 @@ get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain)
not member of a domain. The name in the primary domain info is the
name of the workgroup then. */
if (pdi->Sid &&
(ret = NetGetDCName (NULL, primary, (LPBYTE *) &buf)) == STATUS_SUCCESS)
(ret =
NetGetDCName (NULL, primary, (LPBYTE *) &buf)) == STATUS_SUCCESS)
{
sys_wcstombs (name, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1);
strcpy (logonserver, name);
@@ -271,7 +288,8 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver)
{
sys_wcstombs (server, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (wserver)
for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++); ) {}
for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);)
;
NetApiBufferFree (buf);
return TRUE;
}
@@ -280,7 +298,8 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver)
}
static BOOL
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, char *domain)
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user,
char *domain)
{
char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
WCHAR wuser[UNLEN + 1];
@@ -313,11 +332,12 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, char *do
sys_wcstombs (dgroup + len, buf[i].grui0_name, GNLEN + 1);
if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use))
debug_printf ("LookupAccountName(%s): %E", dgroup);
debug_printf ("LookupAccountName(%s): %E", dgroup);
else if (legal_sid_type (use))
grp_list += gsid;
else debug_printf ("Global group %s invalid. Domain: %s Use: %d",
dgroup, domain, use);
grp_list += gsid;
else
debug_printf ("Global group %s invalid. Domain: %s Use: %d",
dgroup, domain, use);
}
NetApiBufferFree (buf);
@@ -369,10 +389,10 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
const DWORD blen = sizeof ("BUILTIN\\") - 1;
DWORD llen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
if (!GetComputerNameA(lgroup, & llen))
if (!GetComputerNameA (lgroup, &llen))
{
__seterrno ();
return FALSE;
__seterrno ();
return FALSE;
}
lgroup[llen++] = '\\';
@@ -389,11 +409,11 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
if (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use))
{
if (GetLastError () != ERROR_NONE_MAPPED)
debug_printf ("LookupAccountName(%s): %E", bgroup);
debug_printf ("LookupAccountName(%s): %E", bgroup);
strcpy (lgroup + llen, bgroup + blen);
if (!LookupAccountName (NULL, lgroup, gsid, &glen,
domain, &dlen, &use))
debug_printf ("LookupAccountName(%s): %E", lgroup);
debug_printf ("LookupAccountName(%s): %E", lgroup);
}
if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use);
@@ -415,7 +435,7 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygsid &sid)
return FALSE;
}
#if 0 /* Unused */
#if 0 /* Unused */
static BOOL
get_user_primary_group (WCHAR *wlogonserver, const char *user,
PSID pusersid, cygsid &pgrpsid)
@@ -441,7 +461,8 @@ get_user_primary_group (WCHAR *wlogonserver, const char *user,
}
pgrpsid = pusersid;
if (IsValidSid (pgrpsid) && (count = *GetSidSubAuthorityCount (pgrpsid)) > 1)
if (IsValidSid (pgrpsid)
&& (count = *GetSidSubAuthorityCount (pgrpsid)) > 1)
{
*GetSidSubAuthority (pgrpsid, count - 1) = buf->usri3_primary_group_id;
retval = TRUE;
@@ -473,57 +494,63 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
}
}
static BOOL
get_group_sidlist (cygsidlist &grp_list,
cygsid &usersid, cygsid &pgrpsid, struct passwd *pw,
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos,
BOOL *special_pgrp)
static void
get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
LUID auth_luid, int &auth_pos)
{
char user[UNLEN + 1];
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3];
char server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
cygsidlist sup_list;
auth_pos = -1;
if (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;
if (sid_in_token_groups (my_grps, 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;
if (sid_in_token_groups (my_grps, 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;
}
else
{
grp_list += well_known_local_sid;
grp_list += well_known_interactive_sid;
}
if (auth_luid.QuadPart != 999) /* != SYSTEM_LUID */
{
char buf[64];
__small_sprintf (buf, "S-1-5-5-%u-%u", auth_luid.HighPart,
auth_luid.LowPart);
grp_list += buf;
auth_pos = grp_list.count - 1;
}
}
static BOOL
get_initgroups_sidlist (cygsidlist &grp_list,
PSID usersid, PSID pgrpsid, struct passwd *pw,
PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos,
BOOL &special_pgrp)
{
grp_list += well_known_world_sid;
grp_list += well_known_authenticated_users_sid;
if (usersid == well_known_system_sid)
{
auth_pos = -1;
grp_list += well_known_admins_sid;
get_unix_group_sidlist (pw, grp_list);
}
else
{
if (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;
if (sid_in_token_groups (my_grps, 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;
if (sid_in_token_groups (my_grps, 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;
}
else
{
grp_list += well_known_local_sid;
grp_list += well_known_interactive_sid;
}
if (auth_luid.QuadPart != 999) /* != SYSTEM_LUID */
{
char buf[64];
__small_sprintf (buf, "S-1-5-5-%u-%u", auth_luid.HighPart,
auth_luid.LowPart);
grp_list += buf;
auth_pos = grp_list.count - 1;
}
char user[UNLEN + 1];
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3];
char server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos);
extract_nt_dom_user (pw, domain, user);
if (get_logon_server (domain, server, wserver))
get_user_groups (wserver, grp_list, user, domain);
@@ -531,16 +558,26 @@ get_group_sidlist (cygsidlist &grp_list,
if (!get_user_local_groups (grp_list, usersid))
return FALSE;
}
/* special_pgrp true if pgrpsid is not null and not in normal groups */
*special_pgrp = FALSE;
if (pgrpsid && !grp_list.contains (pgrpsid))
{
*special_pgrp = TRUE;
grp_list += pgrpsid;
}
/* special_pgrp true if pgrpsid is not in normal groups */
if ((special_pgrp = !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)
{
PSID pgpsid = groups.pgsid;
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++)
tmp_list += groups.sgsids.sids[gidx];
if (!groups.sgsids.contains (pgpsid))
tmp_list += pgpsid;
}
static const char *sys_privs[] = {
SE_TCB_NAME,
SE_ASSIGNPRIMARYTOKEN_NAME,
@@ -569,8 +606,8 @@ PTOKEN_PRIVILEGES
get_system_priv_list (cygsidlist &grp_list)
{
LUID priv;
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (sizeof (ULONG) +
20 * sizeof (LUID_AND_ATTRIBUTES));
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES)
malloc (sizeof (ULONG) + 20 * sizeof (LUID_AND_ATTRIBUTES));
if (!privs)
{
debug_printf ("malloc (system_privs) failed.");
@@ -583,7 +620,7 @@ get_system_priv_list (cygsidlist &grp_list)
{
privs->Privileges[privs->PrivilegeCount].Luid = priv;
privs->Privileges[privs->PrivilegeCount].Attributes =
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
++privs->PrivilegeCount;
}
return privs;
@@ -605,8 +642,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
{
if (grp == -1)
{
if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt))
!= STATUS_SUCCESS)
if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs,
&cnt)) != STATUS_SUCCESS)
continue;
}
else if ((ret = LsaEnumerateAccountRights (lsa, grp_list.sids[grp],
@@ -629,8 +666,8 @@ 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));
realloc (privs, sizeof (ULONG) +
(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
if (!tmp)
{
if (privs)
@@ -643,7 +680,7 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
privs = tmp;
privs->Privileges[privs->PrivilegeCount].Luid = priv;
privs->Privileges[privs->PrivilegeCount].Attributes =
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
++privs->PrivilegeCount;
next_account_right:
@@ -654,8 +691,21 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
return privs;
}
/* Accept a token if
- the requested usersid matches the TokenUser and
- if setgroups has been called:
the token groups that are listed in /etc/group match the union of
the requested primary and supplementary groups in gsids.
- else the (unknown) implicitly requested supplementary groups and those
in the token are the groups associated with the usersid. We assume
they match and verify only the primary groups.
The requested primary group must appear in the token.
The primary group in the token is a group associated with the usersid,
except if the token is internal and the group is in the token SD
(see create_token). In that latter case that group must match the
requested primary group. */
BOOL
verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern)
verify_token (HANDLE token, cygsid &usersid, user_groups &groups, BOOL *pintern)
{
DWORD size;
BOOL intern = FALSE;
@@ -666,36 +716,39 @@ verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern)
if (!GetTokenInformation (cygheap->user.token, TokenSource,
&ts, sizeof ts, &size))
debug_printf ("GetTokenInformation(): %E");
else *pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
else
*pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
}
/* Verify usersid */
cygsid tok_usersid = NO_SID;
if (!GetTokenInformation (token, TokenUser,
&tok_usersid, sizeof tok_usersid, &size))
debug_printf ("GetTokenInformation(): %E");
if (usersid != tok_usersid) return FALSE;
debug_printf ("GetTokenInformation(): %E");
if (usersid != tok_usersid)
return FALSE;
/* In an internal token, if the sd group is not well_known_null_sid,
it must match pgrpsid */
if (intern)
/* For an internal token, if setgroups was not called and if the sd group
is not well_known_null_sid, it must match pgrpsid */
if (intern && !groups.issetgroups ())
{
char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)];
PSID gsid = NO_SID;
if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION,
char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)];
PSID gsid = NO_SID;
if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION,
(PSECURITY_DESCRIPTOR) sd_buf,
sizeof sd_buf, &size))
debug_printf ("GetKernelObjectSecurity(): %E");
else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf,
debug_printf ("GetKernelObjectSecurity(): %E");
else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf,
&gsid, (BOOL *) &size))
debug_printf ("GetSecurityDescriptorGroup(): %E");
if (well_known_null_sid != gsid) return pgrpsid == gsid;
debug_printf ("GetSecurityDescriptorGroup(): %E");
if (well_known_null_sid != gsid)
return gsid == groups.pgsid;
}
/* See if the pgrpsid is the tok_usersid in the token groups */
PTOKEN_GROUPS my_grps = NULL;
BOOL ret = FALSE;
char saw_buf[NGROUPS_MAX] = {};
char *saw = saw_buf, sawpg = FALSE;
if ( pgrpsid == tok_usersid)
return TRUE;
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
debug_printf ("GetTokenInformation(token, TokenGroups): %E\n");
@@ -703,38 +756,70 @@ verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern)
debug_printf ("malloc (my_grps) failed.");
else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size))
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
else
ret = sid_in_token_groups (my_grps, pgrpsid);
else if (!groups.issetgroups ()) /* setgroups was never called */
{
ret = sid_in_token_groups (my_grps, groups.pgsid);
if (ret == FALSE)
ret = (groups.pgsid == tok_usersid);
}
else /* setgroups was called */
{
struct __group32 *gr;
cygsid gsid;
if (groups.sgsids.count > (int) sizeof (saw_buf) &&
!(saw = (char *) calloc (groups.sgsids.count, sizeof (char))))
goto done;
/* token groups found in /etc/group match the user.gsids ? */
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (gsid.getfromgr (gr) && sid_in_token_groups (my_grps, gsid))
{
int pos = groups.sgsids.position (gsid);
if (pos >= 0)
saw[pos] = TRUE;
else if (groups.pgsid == gsid)
sawpg = TRUE;
else
goto done;
}
for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
if (!saw[gidx])
goto done;
if (sawpg || groups.sgsids.contains (groups.pgsid))
ret = TRUE;
}
done:
if (my_grps)
free (my_grps);
if (saw != saw_buf)
free (saw);
return ret;
}
HANDLE
create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw)
{
NTSTATUS ret;
LSA_HANDLE lsa = INVALID_HANDLE_VALUE;
int old_priv_state;
cygsidlist grpsids;
cygsidlist tmp_gsids (cygsidlist_auto, 12);
SECURITY_QUALITY_OF_SERVICE sqos =
{ sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE };
OBJECT_ATTRIBUTES oa =
{ sizeof oa, 0, 0, 0, 0, &sqos };
OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos };
PSECURITY_ATTRIBUTES psa;
BOOL special_pgrp;
BOOL special_pgrp = FALSE;
char sa_buf[1024];
LUID auth_luid = SYSTEM_LUID;
LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL };
LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL };
TOKEN_USER user;
PTOKEN_GROUPS grps = NULL;
PTOKEN_GROUPS new_tok_gsids = NULL;
PTOKEN_PRIVILEGES privs = NULL;
TOKEN_OWNER owner;
TOKEN_PRIMARY_GROUP pgrp;
char acl_buf[MAX_DACL_LEN(5)];
char acl_buf[MAX_DACL_LEN (5)];
TOKEN_DEFAULT_DACL dacl;
TOKEN_SOURCE source;
TOKEN_STATISTICS stats;
@@ -746,7 +831,7 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
HANDLE primary_token = INVALID_HANDLE_VALUE;
HANDLE my_token = INVALID_HANDLE_VALUE;
PTOKEN_GROUPS my_grps = NULL;
PTOKEN_GROUPS my_tok_gsids = NULL;
DWORD size;
/* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
@@ -768,68 +853,73 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
else
{
/* Switching user context to SYSTEM doesn't inherit the authentication
id of the user account running current process. */
id of the user account running current process. */
if (usersid != well_known_system_sid)
if (!GetTokenInformation (my_token, TokenStatistics,
&stats, sizeof stats, &size))
debug_printf ("GetTokenInformation(my_token, TokenStatistics): %E\n");
debug_printf
("GetTokenInformation(my_token, TokenStatistics): %E\n");
else
auth_luid = stats.AuthenticationId;
/* Retrieving current processes group list to be able to inherit
some important well known group sids. */
some important well known group sids. */
if (!GetTokenInformation (my_token, TokenGroups, NULL, 0, &size) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
else if (!(my_grps = (PTOKEN_GROUPS) malloc (size)))
debug_printf ("malloc (my_grps) failed.");
else if (!GetTokenInformation (my_token, TokenGroups, my_grps,
else if (!(my_tok_gsids = (PTOKEN_GROUPS) malloc (size)))
debug_printf ("malloc (my_tok_gsids) failed.");
else if (!GetTokenInformation (my_token, TokenGroups, my_tok_gsids,
size, &size))
{
debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n");
free (my_grps);
my_grps = NULL;
free (my_tok_gsids);
my_tok_gsids = NULL;
}
CloseHandle (my_token);
}
/* Create list of groups, the user is member in. */
int auth_pos;
if (!get_group_sidlist (grpsids, usersid, pgrpsid, pw,
my_grps, auth_luid, auth_pos, &special_pgrp))
if (new_groups.issetgroups ())
get_setgroups_sidlist (tmp_gsids, 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,
special_pgrp))
goto out;
/* Primary group. */
pgrp.PrimaryGroup = pgrpsid;
pgrp.PrimaryGroup = new_groups.pgsid;
/* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
char grps_buf[sizeof (ULONG) + grpsids.count * sizeof (SID_AND_ATTRIBUTES)];
grps = (PTOKEN_GROUPS) grps_buf;
grps->GroupCount = grpsids.count;
for (DWORD i = 0; i < grps->GroupCount; ++i)
char grps_buf[sizeof (ULONG) + tmp_gsids.count * sizeof (SID_AND_ATTRIBUTES)];
new_tok_gsids = (PTOKEN_GROUPS) grps_buf;
new_tok_gsids->GroupCount = tmp_gsids.count;
for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i)
{
grps->Groups[i].Sid = grpsids.sids[i];
grps->Groups[i].Attributes = SE_GROUP_MANDATORY |
SE_GROUP_ENABLED_BY_DEFAULT |
SE_GROUP_ENABLED;
if (auth_pos >= 0 && i == (DWORD) auth_pos)
grps->Groups[i].Attributes |= SE_GROUP_LOGON_ID;
new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i];
new_tok_gsids->Groups[i].Attributes = SE_GROUP_MANDATORY |
SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
}
if (auth_pos >= 0)
new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID;
/* Retrieve list of privileges of that user. */
if (!(privs = get_priv_list (lsa, usersid, grpsids)))
if (!(privs = get_priv_list (lsa, usersid, tmp_gsids)))
goto out;
/* Create default dacl. */
if (!sec_acl ((PACL) acl_buf, FALSE,
grpsids.contains (well_known_admins_sid)?well_known_admins_sid:usersid))
tmp_gsids.contains (well_known_admins_sid) ?
well_known_admins_sid : usersid))
goto out;
dacl.DefaultDacl = (PACL) acl_buf;
/* Let's be heroic... */
ret = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation,
&auth_luid, &exp, &user, grps, privs, &owner, &pgrp,
&dacl, &source);
&auth_luid, &exp, &user, new_tok_gsids, privs, &owner,
&pgrp, &dacl, &source);
if (ret)
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
@@ -842,13 +932,15 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
/* Set security descriptor and primary group */
psa = __sec_user (sa_buf, usersid, TRUE);
if (psa->lpSecurityDescriptor &&
!SetSecurityDescriptorGroup (
(PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor,
special_pgrp ? pgrpsid : well_known_null_sid, FALSE))
debug_printf ("SetSecurityDescriptorGroup %E");
!SetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR)
psa->lpSecurityDescriptor,
special_pgrp ? new_groups.pgsid
: well_known_null_sid,
FALSE))
debug_printf ("SetSecurityDescriptorGroup %E");
/* Convert to primary token. */
if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa,
SecurityImpersonation, TokenPrimary, &primary_token))
if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, SecurityImpersonation,
TokenPrimary, &primary_token))
{
__seterrno ();
debug_printf ("DuplicateTokenEx %E");
@@ -862,8 +954,8 @@ out:
CloseHandle (token);
if (privs)
free (privs);
if (my_grps)
free (my_grps);
if (my_tok_gsids)
free (my_tok_gsids);
close_local_policy (lsa);
debug_printf ("%d = create_token ()", primary_token);
@@ -946,13 +1038,13 @@ subauth (struct passwd *pw)
str2buf2uni (subbuf.auth.Workstation, subbuf.wkstbuf, "");
memcpy (subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH);
str2buf2lsa (subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, "");
str2buf2lsa (subbuf.auth.CaseInsensitiveChallengeResponse, subbuf.authinf2,"");
str2buf2lsa (subbuf.auth.CaseInsensitiveChallengeResponse,subbuf.authinf2,"");
subbuf.auth.ParameterControl = 0 | (subauth_id << 24);
/* Try to logon... */
ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network,
package_id, &subbuf, sizeof subbuf,
NULL, &ts, (PVOID *)&profile, &size,
&luid, &user_token, &quota, &ret2);
package_id, &subbuf, sizeof subbuf,
NULL, &ts, (PVOID *) &profile, &size,
&luid, &user_token, &quota, &ret2);
if (ret != STATUS_SUCCESS)
{
debug_printf ("LsaLogonUser: %d", ret);
@@ -963,8 +1055,7 @@ subauth (struct passwd *pw)
LsaFreeReturnBuffer (profile);
/* Convert to primary token. */
if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
SecurityImpersonation, TokenPrimary,
&primary_token))
SecurityImpersonation, TokenPrimary, &primary_token))
__seterrno ();
out:
@@ -1004,7 +1095,7 @@ read_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size)
DWORD len = 0;
const char *pfile = file;
char fbuf [PATH_MAX];
char fbuf[PATH_MAX];
if (current_codepage == oem_cp)
{
DWORD fname_len = min (sizeof (fbuf) - 1, strlen (file));
@@ -1015,9 +1106,9 @@ read_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size)
if (!GetFileSecurity (pfile,
OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION,
sd_buf, *sd_size, &len))
| GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION,
sd_buf, *sd_size, &len))
{
__seterrno ();
return -1;
@@ -1090,8 +1181,8 @@ write_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size)
&bytes_written, FALSE, TRUE, &context))
{
/* Samba returns ERROR_NOT_SUPPORTED.
FAT returns ERROR_INVALID_SECURITY_DESCR.
This shouldn't return as error, but better be ignored. */
FAT returns ERROR_INVALID_SECURITY_DESCR.
This shouldn't return as error, but better be ignored. */
DWORD ret = GetLastError ();
if (ret != ERROR_NOT_SUPPORTED && ret != ERROR_INVALID_SECURITY_DESCR)
{
@@ -1117,7 +1208,7 @@ get_nt_attribute (const char *file, int *attribute,
syscall_printf ("file: %s", file);
/* Yeah, sounds too much, but I've seen SDs of 2100 bytes!*/
/* Yeah, sounds too much, but I've seen SDs of 2100 bytes! */
DWORD sd_size = 4096;
char sd_buf[4096];
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
@@ -1282,13 +1373,13 @@ get_file_attribute (int use_ntsec, const char *file,
if (allow_ntea)
{
int oatt = *attribute;
res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof(*attribute));
*attribute |= oatt;
}
else
res = 0;
/* symlinks are everything for everyone!*/
/* symlinks are everything for everyone! */
if ((*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
@@ -1296,8 +1387,8 @@ get_file_attribute (int use_ntsec, const char *file,
}
static int
get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribute,
__uid32_t *uidret, __gid32_t *gidret)
get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
{
if (!wincap.has_security ())
return 0;
@@ -1308,18 +1399,15 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
PACL acl;
if (ERROR_SUCCESS != GetSecurityInfo (handle, object_type,
DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION,
&owner_sid,
&group_sid,
&acl,
NULL,
&psd))
{
__seterrno ();
debug_printf ("GetSecurityInfo %E");
return -1;
DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION,
&owner_sid, &group_sid,
&acl, NULL, &psd))
{
__seterrno ();
debug_printf ("GetSecurityInfo %E");
return -1;
}
__uid32_t uid = cygsid (owner_sid).get_uid ();
@@ -1341,8 +1429,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
if (!acl)
{
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
syscall_printf ("No ACL = %x, uid %d, gid %d",
*attribute, uid, gid);
syscall_printf ("No ACL = %x, uid %d, gid %d", *attribute, uid, gid);
LocalFree (psd);
return 0;
}
@@ -1354,7 +1441,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
for (DWORD i = 0; i < acl->AceCount; ++i)
{
if (!GetAce (acl, i, (PVOID *) &ace))
if (!GetAce (acl, i, (PVOID *) & ace))
continue;
if (ace->Header.AceFlags & INHERIT_ONLY)
continue;
@@ -1372,7 +1459,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
continue;
}
cygsid ace_sid ((PSID) &ace->SidStart);
cygsid ace_sid ((PSID) & ace->SidStart);
if (owner_sid && ace_sid == owner_sid)
{
if (ace->Mask & FILE_READ_DATA)
@@ -1438,11 +1525,12 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
int
get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
{
if (allow_ntsec)
{
int res = get_nt_object_attribute (handle, object_type, attribute, uidret, gidret);
int res = get_nt_object_attribute (handle, object_type, attribute,
uidret, gidret);
if (attribute && (*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
return res;
@@ -1456,7 +1544,7 @@ get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
if (!attribute)
return 0;
/* symlinks are everything for everyone!*/
/* symlinks are everything for everyone! */
if ((*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
@@ -1475,8 +1563,7 @@ add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
ACCESS_ALLOWED_ACE *ace;
if (GetAce (acl, offset, (PVOID *) &ace))
ace->Header.AceFlags |= inherit;
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)
+ GetLengthSid (sid);
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
return TRUE;
}
@@ -1492,8 +1579,7 @@ add_access_denied_ace (PACL acl, int offset, DWORD attributes,
ACCESS_DENIED_ACE *ace;
if (GetAce (acl, offset, (PVOID *) &ace))
ace->Header.AceFlags |= inherit;
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)
+ GetLengthSid (sid);
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
return TRUE;
}
@@ -1614,8 +1700,7 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute,
if (attribute & S_IXGRP)
group_allow |= FILE_GENERIC_EXECUTE;
if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP))
== (S_IFDIR | S_IWGRP | S_IXGRP)
&& !(attribute & S_ISVTX))
== (S_IFDIR | S_IWGRP | S_IXGRP) && !(attribute & S_ISVTX))
group_allow |= FILE_DELETE_CHILD;
/* Construct allow attribute for everyone. */
@@ -1658,30 +1743,30 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute,
/* Construct appropriate inherit attribute. */
DWORD inherit = (attribute & S_IFDIR) ? SUB_CONTAINERS_AND_OBJECTS_INHERIT
: NO_INHERITANCE;
: NO_INHERITANCE;
/* Set deny ACE for owner. */
if (owner_deny
&& !add_access_denied_ace (acl, ace_off++, owner_deny,
owner_sid, acl_len, inherit))
owner_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for owner. */
if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
owner_sid, acl_len, inherit))
owner_sid, acl_len, inherit))
return NULL;
/* Set deny ACE for group. */
if (group_deny
&& !add_access_denied_ace (acl, ace_off++, group_deny,
group_sid, acl_len, inherit))
group_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for group. */
if (!add_access_allowed_ace (acl, ace_off++, group_allow,
group_sid, acl_len, inherit))
group_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for everyone. */
if (!add_access_allowed_ace (acl, ace_off++, other_allow,
well_known_world_sid, acl_len, inherit))
well_known_world_sid, acl_len, inherit))
return NULL;
/* Set null ACE for special bits. */
if (null_allow
@@ -1764,15 +1849,15 @@ void
set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
void *sd_buf, DWORD sd_buf_size)
{
/* symlinks are anything for everyone!*/
/* symlinks are anything for everyone! */
if ((attribute & S_IFLNK) == S_IFLNK)
attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
psa->lpSecurityDescriptor = sd_buf;
InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR)sd_buf,
InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR) sd_buf,
SECURITY_DESCRIPTOR_REVISION);
psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (),
attribute, (PSECURITY_DESCRIPTOR)sd_buf,
psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (), attribute,
(PSECURITY_DESCRIPTOR) sd_buf,
&sd_buf_size);
}
@@ -1803,8 +1888,7 @@ set_nt_attribute (const char *file, __uid32_t uid, __gid32_t gid,
int
set_file_attribute (int use_ntsec, const char *file,
__uid32_t uid, __gid32_t gid,
int attribute)
__uid32_t uid, __gid32_t gid, int attribute)
{
int ret = 0;
@@ -1825,6 +1909,5 @@ int
set_file_attribute (int use_ntsec, const char *file, int attribute)
{
return set_file_attribute (use_ntsec, file,
myself->uid, myself->gid,
attribute);
myself->uid, myself->gid, attribute);
}