Updates To Address OneCore Linking (#311)
* Updates To Address OneCore Linking - Modified generate_s4u_user_token() and sys_auth_passwd() to dynamically load TranslateNameW() to avoid OneCore static library linking. - Modified getusergroups() to avoid Lsa* calls that are not present in OneCore libraries. * Updates To Address OneCore Linking - Revisions - Corrected failure detection logic when TranslateNameW() cannot be located.
This commit is contained in:
parent
ec102dce28
commit
471b76dbd5
|
@ -298,9 +298,24 @@ sys_auth_passwd(struct ssh *ssh, const char *password)
|
||||||
wchar_t * backslash = wcschr(user_utf16, L'\\');
|
wchar_t * backslash = wcschr(user_utf16, L'\\');
|
||||||
if (backslash != NULL) {
|
if (backslash != NULL) {
|
||||||
|
|
||||||
|
/* assemble the path to the name translation library */
|
||||||
|
wchar_t library_path[MAX_PATH + 1];
|
||||||
|
if (GetSystemDirectoryW(library_path, ARRAYSIZE(library_path)) == 0) {
|
||||||
|
debug3("%s: GetSystemDirectoryW() failed name translation: %d", __FUNCTION__, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
wcscat_s(library_path, ARRAYSIZE(library_path), L"\\secur32.dll");
|
||||||
|
|
||||||
|
/* dynamically load name translation function to support static linking to onecore */
|
||||||
|
typedef (*TranslateNameWFunc)(_In_ LPCWSTR lpAccountName,
|
||||||
|
_In_ EXTENDED_NAME_FORMAT AccountNameFormat, _In_ EXTENDED_NAME_FORMAT DesiredNameFormat,
|
||||||
|
_Out_writes_to_opt_(*nSize, *nSize) LPWSTR lpTranslatedName, _Inout_ PULONG nSize);
|
||||||
|
HMODULE library = LoadLibraryW(library_path);
|
||||||
|
TranslateNameWFunc LocalTranslateNameW = NULL;
|
||||||
|
|
||||||
/* attempt to format into upn format as this is preferred for login */
|
/* attempt to format into upn format as this is preferred for login */
|
||||||
if (TranslateNameW(user_utf16, NameSamCompatible,
|
if (library != NULL && (LocalTranslateNameW = (TranslateNameWFunc) GetProcAddress(library, "TranslateNameW")) != NULL &&
|
||||||
NameUserPrincipal, domain_upn, &domain_upn_len) != 0) {
|
LocalTranslateNameW(user_utf16, NameSamCompatible, NameUserPrincipal, domain_upn, &domain_upn_len) != 0) {
|
||||||
unam_utf16 = domain_upn;
|
unam_utf16 = domain_upn;
|
||||||
udom_utf16 = NULL;
|
udom_utf16 = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1224,10 +1224,6 @@ getusergroups(const char *user, int *ngroups)
|
||||||
/* early declarations and initializations to support cleanup */
|
/* early declarations and initializations to support cleanup */
|
||||||
HANDLE logon_token = NULL;
|
HANDLE logon_token = NULL;
|
||||||
PTOKEN_GROUPS group_buf = NULL;
|
PTOKEN_GROUPS group_buf = NULL;
|
||||||
PLSA_REFERENCED_DOMAIN_LIST domain_list = NULL;
|
|
||||||
PLSA_TRANSLATED_NAME name_list = NULL;
|
|
||||||
PSID * group_sids = NULL;
|
|
||||||
LSA_HANDLE lsa_policy = NULL;
|
|
||||||
|
|
||||||
/* initialize return values */
|
/* initialize return values */
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -1257,19 +1253,19 @@ getusergroups(const char *user, int *ngroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read group sids from logon token -- this will return a list of groups
|
/* read group sids from logon token -- this will return a list of groups
|
||||||
* similiar to the data returned when you do a whoami /groups command */
|
* similar to the data returned when you do a whoami /groups command */
|
||||||
if (GetTokenInformation(logon_token, TokenGroups, group_buf, group_size, &group_size) == 0) {
|
if (GetTokenInformation(logon_token, TokenGroups, group_buf, group_size, &group_size) == 0) {
|
||||||
debug3("%s: GetTokenInformation() failed for user '%s'.", __FUNCTION__, user);
|
debug3("%s: GetTokenInformation() failed for user '%s'.", __FUNCTION__, user);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate and copy the sids to a a structure we can pass to lookup */
|
/* allocate memory to hold points to all group names; we double the value
|
||||||
if ((group_sids = (PSID *)malloc(sizeof(PSID) * group_buf->GroupCount)) == NULL) {
|
* in order to account for local groups that we trim the domain qualifier */
|
||||||
|
if ((user_groups = (char**)malloc(sizeof(char*) * group_buf->GroupCount * 2)) == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD group_sids_count = 0;
|
|
||||||
for (DWORD i = 0; i < group_buf->GroupCount; i++) {
|
for (DWORD i = 0; i < group_buf->GroupCount; i++) {
|
||||||
|
|
||||||
/* only bother with group thats are 'enabled' from a security perspective */
|
/* only bother with group thats are 'enabled' from a security perspective */
|
||||||
|
@ -1288,60 +1284,23 @@ getusergroups(const char *user, int *ngroups)
|
||||||
if (memcmp(&nt_authority, GetSidIdentifierAuthority(sid), sizeof(SID_IDENTIFIER_AUTHORITY)) == 0 && (
|
if (memcmp(&nt_authority, GetSidIdentifierAuthority(sid), sizeof(SID_IDENTIFIER_AUTHORITY)) == 0 && (
|
||||||
sub == SECURITY_NT_NON_UNIQUE || sub == SECURITY_BUILTIN_DOMAIN_RID) &&
|
sub == SECURITY_NT_NON_UNIQUE || sub == SECURITY_BUILTIN_DOMAIN_RID) &&
|
||||||
rid != DOMAIN_GROUP_RID_USERS && rid != DOMAIN_ALIAS_RID_USERS) {
|
rid != DOMAIN_GROUP_RID_USERS && rid != DOMAIN_ALIAS_RID_USERS) {
|
||||||
group_sids[group_sids_count++] = sid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open a new connection to the lsa policy provider for group lookup */
|
/* lookup the account name for this sid */
|
||||||
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
wchar_t name[GNLEN + 1];
|
||||||
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
DWORD name_len = ARRAYSIZE(name);
|
||||||
if (LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_LOOKUP_NAMES, &lsa_policy) != 0) {
|
wchar_t domain[DNLEN + 1];
|
||||||
debug3("%s: LsaOpenPolicy() failed for user '%s'.", __FUNCTION__, user);
|
DWORD domain_len = ARRAYSIZE(domain);
|
||||||
goto cleanup;
|
SID_NAME_USE name_use = 0;
|
||||||
}
|
if (LookupAccountSidW(NULL, sid, name, &name_len, domain, &domain_len, &name_use) == 0) {
|
||||||
|
errno = ENOENT;
|
||||||
|
debug("%s: LookupAccountSid() failed: %d.", __FUNCTION__, GetLastError());
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* translate all the sids to real group names */
|
/* add group name in netbios\\name format */
|
||||||
NTSTATUS lsa_ret = LsaLookupSids(lsa_policy, group_sids_count, group_sids, &domain_list, &name_list);
|
int current_group = (*ngroups)++;
|
||||||
if (lsa_ret != STATUS_SUCCESS) {
|
wchar_t formatted_group[DNLEN + 1 + GNLEN + 1];
|
||||||
debug3("%s: LsaLookupSids() failed for user '%s' with return %d.", __FUNCTION__, user, lsa_ret);
|
swprintf_s(formatted_group, ARRAYSIZE(formatted_group), L"%s\\%s", domain, name);
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate memory to hold points to all group names; we double the value
|
|
||||||
* in order to account for local groups that we trim the domain qualifier */
|
|
||||||
if ((user_groups = (char**)malloc(sizeof(char*) * group_sids_count * 2)) == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* enumerate all groups and add to group list */
|
|
||||||
for (DWORD group_index = 0; group_index < group_sids_count; group_index++) {
|
|
||||||
|
|
||||||
/* ignore unresolvable or invalid domains */
|
|
||||||
if (name_list[group_index].DomainIndex == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
PLSA_UNICODE_STRING domain = &(domain_list->Domains[name_list[group_index].DomainIndex].Name);
|
|
||||||
PLSA_UNICODE_STRING name = &(name_list[group_index].Name);
|
|
||||||
|
|
||||||
/* add group name in netbios\\name format */
|
|
||||||
int current_group = (*ngroups)++;
|
|
||||||
wchar_t formatted_group[DNLEN + 1 + GNLEN + 1];
|
|
||||||
swprintf_s(formatted_group, ARRAYSIZE(formatted_group), L"%wZ\\%wZ", domain, name);
|
|
||||||
_wcslwr_s(formatted_group, ARRAYSIZE(formatted_group));
|
|
||||||
debug3("Added group '%ls' for user '%s'.", formatted_group, user);
|
|
||||||
user_groups[current_group] = utf16_to_utf8(formatted_group);
|
|
||||||
if (user_groups[current_group] == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for local accounts trim the domain qualifier */
|
|
||||||
if (wcslen(computer_name) == domain->Length / sizeof(wchar_t) &&
|
|
||||||
_wcsnicmp(computer_name, domain->Buffer, domain->Length / sizeof(wchar_t)) == 0)
|
|
||||||
{
|
|
||||||
current_group = (*ngroups)++;
|
|
||||||
swprintf_s(formatted_group, ARRAYSIZE(formatted_group), L"%wZ", name);
|
|
||||||
_wcslwr_s(formatted_group, ARRAYSIZE(formatted_group));
|
_wcslwr_s(formatted_group, ARRAYSIZE(formatted_group));
|
||||||
debug3("Added group '%ls' for user '%s'.", formatted_group, user);
|
debug3("Added group '%ls' for user '%s'.", formatted_group, user);
|
||||||
user_groups[current_group] = utf16_to_utf8(formatted_group);
|
user_groups[current_group] = utf16_to_utf8(formatted_group);
|
||||||
|
@ -1349,23 +1308,29 @@ getusergroups(const char *user, int *ngroups)
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for local accounts trim the domain qualifier */
|
||||||
|
if (_wcsicmp(computer_name, domain) == 0)
|
||||||
|
{
|
||||||
|
current_group = (*ngroups)++;
|
||||||
|
swprintf_s(formatted_group, ARRAYSIZE(formatted_group), L"%s", name);
|
||||||
|
_wcslwr_s(formatted_group, ARRAYSIZE(formatted_group));
|
||||||
|
debug3("Added group '%ls' for user '%s'.", formatted_group, user);
|
||||||
|
user_groups[current_group] = utf16_to_utf8(formatted_group);
|
||||||
|
if (user_groups[current_group] == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
||||||
if (domain_list)
|
|
||||||
LsaFreeMemory(domain_list);
|
|
||||||
if (name_list)
|
|
||||||
LsaFreeMemory(name_list);
|
|
||||||
if (group_buf)
|
if (group_buf)
|
||||||
free(group_buf);
|
free(group_buf);
|
||||||
if (logon_token)
|
if (logon_token)
|
||||||
CloseHandle(logon_token);
|
CloseHandle(logon_token);
|
||||||
if (group_sids)
|
|
||||||
free(group_sids);
|
|
||||||
if (lsa_policy)
|
|
||||||
LsaClose(lsa_policy);
|
|
||||||
|
|
||||||
/* special cleanup - if ran out of memory while allocating groups */
|
/* special cleanup - if ran out of memory while allocating groups */
|
||||||
if (user_groups && errno == ENOMEM || *ngroups == 0) {
|
if (user_groups && errno == ENOMEM || *ngroups == 0) {
|
||||||
|
|
|
@ -133,10 +133,26 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
|
||||||
|
|
||||||
if (domain_user) {
|
if (domain_user) {
|
||||||
|
|
||||||
|
/* assemble the path to the name translation library */
|
||||||
|
wchar_t library_path[MAX_PATH + 1];
|
||||||
|
if (GetSystemDirectoryW(library_path, ARRAYSIZE(library_path)) == 0) {
|
||||||
|
debug3("%s: GetSystemDirectoryW() failed name translation: %d", __FUNCTION__, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
wcscat_s(library_path, ARRAYSIZE(library_path), L"\\secur32.dll");
|
||||||
|
|
||||||
|
/* dynamically load name translation function to support static linking to onecore */
|
||||||
|
typedef (*TranslateNameWFunc)(_In_ LPCWSTR lpAccountName,
|
||||||
|
_In_ EXTENDED_NAME_FORMAT AccountNameFormat, _In_ EXTENDED_NAME_FORMAT DesiredNameFormat,
|
||||||
|
_Out_writes_to_opt_(*nSize, *nSize) LPWSTR lpTranslatedName, _Inout_ PULONG nSize);
|
||||||
|
HMODULE library = LoadLibraryW(library_path);
|
||||||
|
TranslateNameWFunc LocalTranslateNameW = NULL;
|
||||||
|
|
||||||
/* lookup the upn for the user */
|
/* lookup the upn for the user */
|
||||||
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
||||||
ULONG domain_upn_len = ARRAYSIZE(domain_upn);
|
ULONG domain_upn_len = ARRAYSIZE(domain_upn);
|
||||||
if (TranslateNameW(user_cpn, NameSamCompatible,
|
if (library == NULL || (LocalTranslateNameW = (TranslateNameWFunc) GetProcAddress(library, "TranslateNameW")) == NULL ||
|
||||||
|
LocalTranslateNameW(user_cpn, NameSamCompatible,
|
||||||
NameUserPrincipal, domain_upn, &domain_upn_len) == 0) {
|
NameUserPrincipal, domain_upn, &domain_upn_len) == 0) {
|
||||||
|
|
||||||
/* upn lookup failed so resort to attempting samcompatiblename */
|
/* upn lookup failed so resort to attempting samcompatiblename */
|
||||||
|
|
Loading…
Reference in New Issue