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'\\');
|
||||
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 */
|
||||
if (TranslateNameW(user_utf16, NameSamCompatible,
|
||||
NameUserPrincipal, domain_upn, &domain_upn_len) != 0) {
|
||||
if (library != NULL && (LocalTranslateNameW = (TranslateNameWFunc) GetProcAddress(library, "TranslateNameW")) != NULL &&
|
||||
LocalTranslateNameW(user_utf16, NameSamCompatible, NameUserPrincipal, domain_upn, &domain_upn_len) != 0) {
|
||||
unam_utf16 = domain_upn;
|
||||
udom_utf16 = NULL;
|
||||
}
|
||||
|
|
|
@ -1224,10 +1224,6 @@ getusergroups(const char *user, int *ngroups)
|
|||
/* early declarations and initializations to support cleanup */
|
||||
HANDLE logon_token = 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 */
|
||||
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
|
||||
* 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) {
|
||||
debug3("%s: GetTokenInformation() failed for user '%s'.", __FUNCTION__, user);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate and copy the sids to a a structure we can pass to lookup */
|
||||
if ((group_sids = (PSID *)malloc(sizeof(PSID) * group_buf->GroupCount)) == NULL) {
|
||||
/* 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_buf->GroupCount * 2)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
DWORD group_sids_count = 0;
|
||||
for (DWORD i = 0; i < group_buf->GroupCount; i++) {
|
||||
|
||||
/* only bother with group thats are 'enabled' from a security perspective */
|
||||
|
@ -1288,84 +1284,53 @@ getusergroups(const char *user, int *ngroups)
|
|||
if (memcmp(&nt_authority, GetSidIdentifierAuthority(sid), sizeof(SID_IDENTIFIER_AUTHORITY)) == 0 && (
|
||||
sub == SECURITY_NT_NON_UNIQUE || sub == SECURITY_BUILTIN_DOMAIN_RID) &&
|
||||
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 */
|
||||
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
||||
if (LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_LOOKUP_NAMES, &lsa_policy) != 0) {
|
||||
debug3("%s: LsaOpenPolicy() failed for user '%s'.", __FUNCTION__, user);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* translate all the sids to real group names */
|
||||
NTSTATUS lsa_ret = LsaLookupSids(lsa_policy, group_sids_count, group_sids, &domain_list, &name_list);
|
||||
if (lsa_ret != STATUS_SUCCESS) {
|
||||
debug3("%s: LsaLookupSids() failed for user '%s' with return %d.", __FUNCTION__, user, lsa_ret);
|
||||
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));
|
||||
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;
|
||||
/* lookup the account name for this sid */
|
||||
wchar_t name[GNLEN + 1];
|
||||
DWORD name_len = ARRAYSIZE(name);
|
||||
wchar_t domain[DNLEN + 1];
|
||||
DWORD domain_len = ARRAYSIZE(domain);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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"%s\\%s", 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 (_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:
|
||||
|
||||
if (domain_list)
|
||||
LsaFreeMemory(domain_list);
|
||||
if (name_list)
|
||||
LsaFreeMemory(name_list);
|
||||
if (group_buf)
|
||||
free(group_buf);
|
||||
if (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 */
|
||||
if (user_groups && errno == ENOMEM || *ngroups == 0) {
|
||||
|
|
|
@ -133,10 +133,26 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
|
|||
|
||||
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 */
|
||||
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
||||
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) {
|
||||
|
||||
/* upn lookup failed so resort to attempting samcompatiblename */
|
||||
|
|
Loading…
Reference in New Issue