Workaround AzureAD shortcomings

No real domain, no DC, no infos via NetUserGetInfo... nothing.  Just nothing.

Use fixed uid 0x1000 (4096) for AzureAD user and gid 0x1001 (4097) for
AzureAD group.  Note that this group is part of the user token, but it's
not the primary group.  The primary group SID is, unfortunately, the
user's SID.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2016-08-08 09:45:34 +02:00
parent 4de8596b8e
commit eb61113daf
1 changed files with 90 additions and 10 deletions

View File

@ -1082,6 +1082,7 @@ cygheap_pwdgrp::get_home (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
case NSS_SCHEME_FREEATTR: case NSS_SCHEME_FREEATTR:
break; break;
case NSS_SCHEME_DESC: case NSS_SCHEME_DESC:
if (ui)
home = fetch_from_description (ui->usri3_comment, L"home=\"", 6); home = fetch_from_description (ui->usri3_comment, L"home=\"", 6);
break; break;
case NSS_SCHEME_PATH: case NSS_SCHEME_PATH:
@ -1173,6 +1174,7 @@ cygheap_pwdgrp::get_shell (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
case NSS_SCHEME_FREEATTR: case NSS_SCHEME_FREEATTR:
break; break;
case NSS_SCHEME_DESC: case NSS_SCHEME_DESC:
if (ui)
shell = fetch_from_description (ui->usri3_comment, L"shell=\"", 7); shell = fetch_from_description (ui->usri3_comment, L"shell=\"", 7);
break; break;
case NSS_SCHEME_PATH: case NSS_SCHEME_PATH:
@ -1271,7 +1273,7 @@ cygheap_pwdgrp::get_gecos (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
case NSS_SCHEME_FALLBACK: case NSS_SCHEME_FALLBACK:
return NULL; return NULL;
case NSS_SCHEME_WINDOWS: case NSS_SCHEME_WINDOWS:
if (ui->usri3_full_name && *ui->usri3_full_name) if (ui && ui->usri3_full_name && *ui->usri3_full_name)
sys_wcstombs_alloc (&gecos, HEAP_NOTHEAP, ui->usri3_full_name); sys_wcstombs_alloc (&gecos, HEAP_NOTHEAP, ui->usri3_full_name);
break; break;
case NSS_SCHEME_CYGWIN: case NSS_SCHEME_CYGWIN:
@ -1279,6 +1281,7 @@ cygheap_pwdgrp::get_gecos (PUSER_INFO_3 ui, cygpsid &sid, PCWSTR dom,
case NSS_SCHEME_FREEATTR: case NSS_SCHEME_FREEATTR:
break; break;
case NSS_SCHEME_DESC: case NSS_SCHEME_DESC:
if (ui)
gecos = fetch_from_description (ui->usri3_comment, L"gecos=\"", 7); gecos = fetch_from_description (ui->usri3_comment, L"gecos=\"", 7);
break; break;
case NSS_SCHEME_PATH: case NSS_SCHEME_PATH:
@ -1508,6 +1511,36 @@ 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 ("");
static void
get_azure_grp_sid ()
{
if (PSID (azure_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)
if (sid_id_auth (groups->Groups[pg].Sid) == 12)
{
azure_grp_sid = groups->Groups[pg].Sid;
break;
}
}
}
}
void * void *
pwdgrp::add_account_post_fetch (char *line, bool lock) pwdgrp::add_account_post_fetch (char *line, bool lock)
{ {
@ -1911,6 +1944,9 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
/* Last but not least, some validity checks on the name style. */ /* Last but not least, some validity checks on the name style. */
if (!fq_name) if (!fq_name)
{ {
/* AzureAD user must be prepended by "domain" name. */
if (sid_id_auth (sid) == 12)
return NULL;
/* name_only only if db_prefix is auto. */ /* name_only only if db_prefix is auto. */
if (!cygheap->pg.nss_prefix_auto ()) if (!cygheap->pg.nss_prefix_auto ())
{ {
@ -1945,6 +1981,9 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
/* All is well if db_prefix is always. */ /* All is well if db_prefix is always. */
if (cygheap->pg.nss_prefix_always ()) if (cygheap->pg.nss_prefix_always ())
break; break;
/* AzureAD accounts should be fully qualifed either. */
if (sid_id_auth (sid) == 12)
break;
/* Otherwise, no fully_qualified for builtin accounts, except for /* Otherwise, no fully_qualified for builtin accounts, except for
NT SERVICE, for which we require the prefix. Note that there's NT SERVICE, for which we require the prefix. Note that there's
no equivalent test in the `if (!fq_name)' branch above, because no equivalent test in the `if (!fq_name)' branch above, because
@ -2012,6 +2051,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
sid = logon_sid; sid = logon_sid;
break; break;
} }
else if (arg.id == 0x1000)
{
/* AzureAD S-1-12-1-W-X-Y-Z user */
csid = cygheap->user.saved_sid ();
}
else if (arg.id == 0x1001)
{
/* Special AzureAD group SID */
get_azure_grp_sid ();
/* LookupAccountSidW will fail. */
sid = csid = azure_grp_sid;
break;
}
else if (arg.id == 0xfffe) else if (arg.id == 0xfffe)
{ {
/* Special case "nobody" for reproducible construction of a /* Special case "nobody" for reproducible construction of a
@ -2130,13 +2182,15 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
/* Don't allow users as group. While this is technically /* Don't allow users as group. While this is technically
possible, it doesn't make sense in a POSIX scenario. possible, it doesn't make sense in a POSIX scenario.
And then there are the so-called Microsoft Accounts. The Microsoft Accounts as well as AzureAD accounts have the
special SID with security authority 11 is converted to a primary group SID in their user token set to their own
well known group above, but additionally, when logging in user SID.
with such an account, the user's primary group SID is the
user's SID. Those we let pass, but no others. */ Those we let pass, but no others. */
bool its_ok = false; bool its_ok = false;
if (wincap.has_microsoft_accounts ()) if (sid_id_auth (sid) == 12)
its_ok = true;
else if (wincap.has_microsoft_accounts ())
{ {
struct cyg_USER_INFO_24 *ui24; struct cyg_USER_INFO_24 *ui24;
if (NetUserGetInfo (NULL, name, 24, (PBYTE *) &ui24) if (NetUserGetInfo (NULL, name, 24, (PBYTE *) &ui24)
@ -2227,6 +2281,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
posix_offset = fetch_posix_offset (td, &loc_ldap); posix_offset = fetch_posix_offset (td, &loc_ldap);
} }
} }
/* AzureAD S-1-12-1-W-X-Y-Z user */
else if (sid_id_auth (sid) == 12)
{
uid = gid = 0x1000;
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 /* If the domain returned by LookupAccountSid is not our machine
name, and if our machine is no domain member, we lose. We have name, and if our machine is no domain member, we lose. We have
nobody to ask for the POSIX offset. */ nobody to ask for the POSIX offset. */
@ -2456,6 +2523,19 @@ pwdgrp::fetch_account_from_windows (fetch_user_arg_t &arg, cyg_ldap *pldap)
fully_qualified_name = true; fully_qualified_name = true;
acc_type = SidTypeUnknown; acc_type = SidTypeUnknown;
} }
else if (sid_id_auth (sid) == 12 && sid_sub_auth (sid, 0) == 1)
{
/* Special AzureAD 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 = 0x1001;
wcpcpy (dom, L"AzureAD");
wcpcpy (name = namebuf, L"Group");
fully_qualified_name = true;
acc_type = SidTypeUnknown;
}
else if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */ else if (sid_id_auth (sid) == 5 /* SECURITY_NT_AUTHORITY */
&& sid_sub_auth (sid, 0) == SECURITY_LOGON_IDS_RID) && sid_sub_auth (sid, 0) == SECURITY_LOGON_IDS_RID)
{ {