Skip to content

Commit

Permalink
uinfo: special-case IIS APPPOOL accounts
Browse files Browse the repository at this point in the history
The account under which Azure Web Apps run is an IIS APPOOL account that
is generated on the fly.

These are special because the virtual machines on which thes Apps run
are not domain-joined, yet the accounts are domain accounts.

To support the use case where such a Web App needs to call `ssh` (e.g.
to deploy from a Git repository that is accessible only via SSH), we do
need OpenSSH's `getpwuid (getuid ())` invocation to work.

But currently it does not. Concretely, `getuid ()` returns -1 for these
accounts, and OpenSSH fails to find the correct home directory
(_especially_ when that home directory was overridden via a `db_home:
env` line in `/etc/nsswitch.conf`).

This can be verified e.g. in a Kudu console (for details about Kudu
consoles, see https://github.com/projectkudu/kudu/wiki/Kudu-console):
the domain is `IIS APPPOOL`, the account name is the name of the Azure
Web App, the SID starts with 'S-1-5-82-`, and
`pwdgrp::fetch_account_from_windows()` runs into the code path where
"[...] the domain returned by LookupAccountSid is not our machine name,
and if our machine is no domain member, we lose.  We have nobody to ask
for the POSIX offset."

Since these IIS APPPOOL accounts are relatively similar to AzureAD
accounts in this scenario, let's imitate the latter to support also the
former.

Reported-by: David Ebbo <david.ebbo@gmail.com>
Helped-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Nov 29, 2023
1 parent 0558d73 commit ab5d85c
Showing 1 changed file with 98 additions and 9 deletions.
107 changes: 98 additions & 9 deletions winsup/cygwin/uinfo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1490,9 +1490,9 @@ get_logon_sid ()
}
}

/* Fetch special AzureAD group, which is part of the token group list but
*not* recognized by LookupAccountSid (ERROR_NONE_MAPPED). */
static cygsid azure_grp_sid ("");
/* Fetch special AzureAD and IIS APPPOOL groups, which are part of the token
group list but *not* recognized by LookupAccountSid (ERROR_NONE_MAPPED). */
static cygsid azure_grp_sid (""), iis_apppool_grp_sid ("");

static void
get_azure_grp_sid ()
Expand Down Expand Up @@ -1520,6 +1520,36 @@ get_azure_grp_sid ()
}
}

static void
get_iis_apppool_grp_sid ()
{
if (PSID (iis_apppool_grp_sid) == NO_SID)
{
NTSTATUS status;
ULONG size;
tmp_pathbuf tp;
PTOKEN_GROUPS groups = (PTOKEN_GROUPS) tp.w_get ();

status = NtQueryInformationToken (hProcToken, TokenGroups, groups,
2 * NT_MAX_PATH, &size);
if (!NT_SUCCESS (status))
debug_printf ("NtQueryInformationToken (TokenGroups) %y", status);
else
{
for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
{
PSID sid = groups->Groups[pg].Sid;
if (sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID)
{
iis_apppool_grp_sid = sid;
break;
}
}
}
}
}

void *
pwdgrp::add_account_post_fetch (char *line, bool lock)
{
Expand Down Expand Up @@ -1801,6 +1831,16 @@ pwdgrp::construct_sid_from_name (cygsid &sid, wchar_t *name, wchar_t *sep)
}
return false;
}
if (sep && wcscmp (name, L"IIS APPPOOL\\Group") == 0)
{
get_iis_apppool_grp_sid ();
if (PSID (logon_sid) != NO_SID)
{
sid = iis_apppool_grp_sid;
return true;
}
return false;
}
if (!sep && wcscmp (name, L"CurrentSession") == 0)
{
get_logon_sid ();
Expand Down Expand Up @@ -2024,8 +2064,11 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
/* Last but not least, some validity checks on the name style. */
if (!fq_name)
{
/* AzureAD user must be prepended by "domain" name. */
if (sid_id_auth (sid) == 12)
/* AzureAD and IIS APPPOOL users must be prepended by "domain"
name. */
if (sid_id_auth (sid) == 12 ||
(sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID))
return NULL;
/* name_only account is either builtin or primary domain, or
account domain on non-domain machines. */
Expand All @@ -2051,8 +2094,10 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
}
else
{
/* AzureAD accounts should be fully qualifed either. */
if (sid_id_auth (sid) == 12)
/* AzureAD and IIS APPPOOL accounts should be fully qualifed either. */
if (sid_id_auth (sid) == 12 ||
(sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID))
break;
/* Otherwise, no fully_qualified for builtin accounts, except for
NT SERVICE, for which we require the prefix. Note that there's
Expand Down Expand Up @@ -2131,6 +2176,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
sid = csid = azure_grp_sid;
break;
}
else if (arg.id == 0x1002)
{
/* IIS APPPOOL S-1-5-82-* user */
csid = cygheap->user.saved_sid ();
}
else if (arg.id == 0x1003)
{
/* Special IIS APPPOOL group SID */
get_iis_apppool_grp_sid ();
/* LookupAccountSidW will fail. */
sid = csid = iis_apppool_grp_sid;
break;
}
else if (arg.id == 0xfffe)
{
/* Special case "nobody" for reproducible construction of a
Expand Down Expand Up @@ -2259,7 +2317,9 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
Those we let pass, but no others. */
bool its_ok = false;
if (sid_id_auth (sid) == 12)
if (sid_id_auth (sid) == 12 ||
(sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID))
its_ok = true;
else if (wincap.has_microsoft_accounts ())
{
Expand Down Expand Up @@ -2348,7 +2408,7 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
posix_offset = fetch_posix_offset (td, &loc_ldap);
}
}
/* AzureAD S-1-12-1-W-X-Y-Z user */
/* AzureAD S-1-12-1-W-X-Y-Z and IIS APPOOL S-1-5-82-* user */
else if (sid_id_auth (sid) == 12)
{
uid = gid = 0x1000;
Expand All @@ -2361,6 +2421,21 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
name, fully_qualified_name);
break;
}
/* IIS APPOOL S-1-5-82-* user */
else if (sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID)
{
uid = 0x1002;
gid = 0x1003;
fully_qualified_name = true;
home = cygheap->pg.get_home ((PUSER_INFO_3) NULL, sid, dom, name,
fully_qualified_name);
shell = cygheap->pg.get_shell ((PUSER_INFO_3) NULL, sid, dom,
name, fully_qualified_name);
gecos = cygheap->pg.get_gecos ((PUSER_INFO_3) NULL, sid, dom,
name, fully_qualified_name);
break;
}
/* If the domain returned by LookupAccountSid is not our machine
name, and if our machine is no domain member, we lose. We have
nobody to ask for the POSIX offset. */
Expand Down Expand Up @@ -2632,6 +2707,20 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
fully_qualified_name = true;
acc_type = SidTypeUnknown;
}
else if (sid_id_auth (sid) == 5 &&
sid_sub_auth (sid, 0) == SECURITY_APPPOOL_ID_BASE_RID)
{
/* Special IIS APPPOOL group SID which can't be resolved by
LookupAccountSid (ERROR_NONE_MAPPED). This is only allowed
as group entry, not as passwd entry. */
if (is_passwd ())
return NULL;
uid = gid = 0x1003;
wcpcpy (dom, L"IIS APPPOOL");
wcpcpy (name = namebuf, L"Group");
fully_qualified_name = true;
acc_type = SidTypeUnknown;
}
else if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
&& sid_sub_auth (sid, 0) == SECURITY_LOGON_IDS_RID)
{
Expand Down

0 comments on commit ab5d85c

Please sign in to comment.