Rework username same as hostname (#469)

This commit is contained in:
Oldřich Jedlička 2021-05-07 00:20:35 +02:00 committed by GitHub
parent 59a96cfee4
commit 62ea86fdbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 557 additions and 489 deletions

View File

@ -1587,6 +1587,104 @@ am_system()
return running_as_system; return running_as_system;
} }
/*
* Returns SID of user/group. If psid argument is NULL, allocates a new one,
* otherwise saves SID into the supplied memory area.
* Sets psid_len (if non-NULL) to the actual SID size.
* Caller should free() return value if psid argument was NULL.
*/
PSID
lookup_sid(const wchar_t* name_utf16, PSID psid, DWORD * psid_len)
{
PSID ret = NULL, alloc_psid = NULL, target_psid;
DWORD sid_len = 0;
SID_NAME_USE n_use;
WCHAR dom[DNLEN + 1] = L"";
DWORD dom_len = DNLEN + 1;
wchar_t* name_utf16_modified = NULL;
BOOL resolveAsAdminsSid = 0, r;
debug3_f("name_utf16:%S", name_utf16);
LookupAccountNameW(NULL, name_utf16, NULL, &sid_len, dom, &dom_len, &n_use);
if (sid_len == 0 && _wcsicmp(name_utf16, L"administrators") == 0) {
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, NULL, &sid_len);
resolveAsAdminsSid = 1;
debug3_f("resolveAsAdminsSid:%d", resolveAsAdminsSid);
}
if (sid_len == 0) {
error_f("LookupAccountNameW() failed with error:%d", GetLastError());
errno = errno_from_Win32LastError();
goto cleanup;
}
target_psid = psid;
if (target_psid == NULL) {
if ((alloc_psid = malloc(sid_len)) == NULL) {
errno = ENOMEM;
error_f("Failed to allocate memory");
goto cleanup;
}
target_psid = alloc_psid;
}
if (resolveAsAdminsSid)
r = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, target_psid, &sid_len);
else
r = LookupAccountNameW(NULL, name_utf16, target_psid, &sid_len, dom, &dom_len, &n_use);
if (!r) {
error_f("Failed to retrieve SID for user:%S error:%d", name_utf16, GetLastError());
errno = errno_from_Win32LastError();
goto cleanup;
}
if (n_use == SidTypeDomain) {
// Additionally check the case when name is the same as computer name and
// thus same as local domain. Try to resolve <name>\<name>.
/* fetch the computer name so we can determine if the specified user is local or not */
wchar_t computer_name[CNLEN + 1];
DWORD computer_name_size = ARRAYSIZE(computer_name);
if (GetComputerNameW(computer_name, &computer_name_size) == 0) {
error_f("GetComputerNameW() failed with error:%d", GetLastError());
goto cleanup;
}
if (_wcsicmp(name_utf16, computer_name) != 0) {
error_f("For SidTypeDomain, name:%ls must be same as machine name:%ls", name_utf16, computer_name);
goto cleanup;
}
debug3_f("local user name is same as machine name");
size_t name_size = wcslen(name_utf16) * 2U + 2U;
name_utf16_modified = malloc(name_size * sizeof(wchar_t));
name_utf16_modified[0] = L'\0';
wcscat_s(name_utf16_modified, name_size, name_utf16);
wcscat_s(name_utf16_modified, name_size, L"\\");
wcscat_s(name_utf16_modified, name_size, name_utf16);
ret = lookup_sid(name_utf16_modified, psid, psid_len);
}
else {
if (psid_len != NULL)
*psid_len = sid_len;
alloc_psid = NULL;
ret = target_psid;
}
cleanup:
if (name_utf16_modified)
free(name_utf16_modified);
if (alloc_psid)
free(alloc_psid);
return ret;
}
/* /*
* returns SID of user/group or current user if (user = NULL) * returns SID of user/group or current user if (user = NULL)
* caller should free() return value * caller should free() return value
@ -1601,41 +1699,10 @@ get_sid(const char* name)
wchar_t* name_utf16 = NULL; wchar_t* name_utf16 = NULL;
if (name) { if (name) {
DWORD sid_len = 0;
SID_NAME_USE n_use;
WCHAR dom[DNLEN + 1] = L"";
DWORD dom_len = DNLEN + 1;
BOOL resolveAsAdminsSid = 0, r;
if ((name_utf16 = utf8_to_utf16(name)) == NULL) if ((name_utf16 = utf8_to_utf16(name)) == NULL)
goto cleanup; goto cleanup;
LookupAccountNameW(NULL, name_utf16, NULL, &sid_len, dom, &dom_len, &n_use); psid = lookup_sid(name_utf16, NULL, NULL);
if (sid_len == 0 && _stricmp(name, "administrators") == 0) {
CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, NULL, &sid_len);
resolveAsAdminsSid = 1;
}
if (sid_len == 0) {
errno = errno_from_Win32LastError();
goto cleanup;
}
if ((psid = malloc(sid_len)) == NULL) {
errno = ENOMEM;
goto cleanup;
}
if (resolveAsAdminsSid)
r = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, psid, &sid_len);
else
r = LookupAccountNameW(NULL, name_utf16, psid, &sid_len, dom, &dom_len, &n_use);
if (!r) {
errno = errno_from_Win32LastError();
goto cleanup;
}
} }
else { else {
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE || if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE ||

View File

@ -70,6 +70,7 @@ int load_user_profile(HANDLE user_token, char* user);
int create_directory_withsddl(wchar_t *path, wchar_t *sddl); int create_directory_withsddl(wchar_t *path, wchar_t *sddl);
int is_absolute_path(const char *); int is_absolute_path(const char *);
int file_in_chroot_jail(HANDLE); int file_in_chroot_jail(HANDLE);
PSID lookup_sid(const wchar_t* name_utf16, PSID psid, DWORD * psid_len);
PSID get_sid(const char*); PSID get_sid(const char*);
int am_system(); int am_system();
int is_conpty_supported(); int is_conpty_supported();

View File

@ -1,458 +1,458 @@
/* /*
* Author: NoMachine <developers@nomachine.com> * Author: NoMachine <developers@nomachine.com>
* *
* Author: Bryan Berns <berns@uwalumni.com> * Author: Bryan Berns <berns@uwalumni.com>
* Normalized and optimized login routines and added support for * Normalized and optimized login routines and added support for
* internet-linked accounts. * internet-linked accounts.
* *
* Copyright (c) 2009, 2011 NoMachine * Copyright (c) 2009, 2011 NoMachine
* All rights reserved * All rights reserved
* *
* Support functions and system calls' replacements needed to let the * Support functions and system calls' replacements needed to let the
* software run on Win32 based operating systems. * software run on Win32 based operating systems.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <Windows.h> #include <Windows.h>
#include <stdio.h> #include <stdio.h>
#include <LM.h> #include <LM.h>
#include <sddl.h> #include <sddl.h>
#include <DsGetDC.h> #include <DsGetDC.h>
#define SECURITY_WIN32 #define SECURITY_WIN32
#include <security.h> #include <security.h>
#include "inc\pwd.h" #include "inc\pwd.h"
#include "inc\grp.h" #include "inc\grp.h"
#include "inc\utf.h" #include "inc\utf.h"
#include "misc_internal.h" #include "misc_internal.h"
#include "debug.h" #include "debug.h"
static struct passwd pw; static struct passwd pw;
static char* pw_shellpath = NULL; static char* pw_shellpath = NULL;
char* shell_command_option = NULL; char* shell_command_option = NULL;
char* shell_arguments = NULL; char* shell_arguments = NULL;
BOOLEAN arg_escape = TRUE; BOOLEAN arg_escape = TRUE;
/* returns 0 on success, and -1 with errno set on failure */ /* returns 0 on success, and -1 with errno set on failure */
static int static int
set_defaultshell() set_defaultshell()
{ {
HKEY reg_key = 0; HKEY reg_key = 0;
int tmp_len, ret = -1; int tmp_len, ret = -1;
REGSAM mask = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY; REGSAM mask = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY;
wchar_t path_buf[PATH_MAX], option_buf[32], arg_buf[PATH_MAX]; wchar_t path_buf[PATH_MAX], option_buf[32], arg_buf[PATH_MAX];
char *pw_shellpath_local = NULL, *command_option_local = NULL, *shell_arguments_local = NULL; char *pw_shellpath_local = NULL, *command_option_local = NULL, *shell_arguments_local = NULL;
errno = 0; errno = 0;
/* if already set, return success */ /* if already set, return success */
if (pw_shellpath != NULL) if (pw_shellpath != NULL)
return 0; return 0;
path_buf[0] = L'\0'; path_buf[0] = L'\0';
option_buf[0] = L'\0'; option_buf[0] = L'\0';
arg_buf[0] = L'\0'; arg_buf[0] = L'\0';
tmp_len = _countof(path_buf); tmp_len = _countof(path_buf);
if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, SSH_REGISTRY_ROOT, 0, mask, &reg_key) == ERROR_SUCCESS) && if ((RegOpenKeyExW(HKEY_LOCAL_MACHINE, SSH_REGISTRY_ROOT, 0, mask, &reg_key) == ERROR_SUCCESS) &&
(RegQueryValueExW(reg_key, L"DefaultShell", 0, NULL, (LPBYTE)path_buf, &tmp_len) == ERROR_SUCCESS) && (RegQueryValueExW(reg_key, L"DefaultShell", 0, NULL, (LPBYTE)path_buf, &tmp_len) == ERROR_SUCCESS) &&
(path_buf[0] != L'\0')) { (path_buf[0] != L'\0')) {
/* fetched default shell path from registry */ /* fetched default shell path from registry */
tmp_len = _countof(option_buf); tmp_len = _countof(option_buf);
DWORD size = sizeof(DWORD); DWORD size = sizeof(DWORD);
DWORD escape_option = 1; DWORD escape_option = 1;
if (RegQueryValueExW(reg_key, L"DefaultShellCommandOption", 0, NULL, (LPBYTE)option_buf, &tmp_len) != ERROR_SUCCESS) if (RegQueryValueExW(reg_key, L"DefaultShellCommandOption", 0, NULL, (LPBYTE)option_buf, &tmp_len) != ERROR_SUCCESS)
option_buf[0] = L'\0'; option_buf[0] = L'\0';
tmp_len = _countof(arg_buf); tmp_len = _countof(arg_buf);
if (RegQueryValueExW(reg_key, L"DefaultShellArguments", 0, NULL, (LPBYTE)arg_buf, &tmp_len) != ERROR_SUCCESS) if (RegQueryValueExW(reg_key, L"DefaultShellArguments", 0, NULL, (LPBYTE)arg_buf, &tmp_len) != ERROR_SUCCESS)
arg_buf[0] = L'\0'; arg_buf[0] = L'\0';
if (RegQueryValueExW(reg_key, L"DefaultShellEscapeArguments", 0, NULL, (LPBYTE)&escape_option, &size) == ERROR_SUCCESS) if (RegQueryValueExW(reg_key, L"DefaultShellEscapeArguments", 0, NULL, (LPBYTE)&escape_option, &size) == ERROR_SUCCESS)
arg_escape = (escape_option != 0) ? TRUE : FALSE; arg_escape = (escape_option != 0) ? TRUE : FALSE;
} else { } else {
if (!GetSystemDirectoryW(path_buf, _countof(path_buf))) { if (!GetSystemDirectoryW(path_buf, _countof(path_buf))) {
errno = GetLastError(); errno = GetLastError();
goto cleanup; goto cleanup;
} }
if (wcscat_s(path_buf, _countof(path_buf), L"\\cmd.exe") != 0) if (wcscat_s(path_buf, _countof(path_buf), L"\\cmd.exe") != 0)
goto cleanup; goto cleanup;
} }
if ((pw_shellpath_local = utf16_to_utf8(path_buf)) == NULL) if ((pw_shellpath_local = utf16_to_utf8(path_buf)) == NULL)
goto cleanup; goto cleanup;
if (option_buf[0] != L'\0') if (option_buf[0] != L'\0')
if ((command_option_local = utf16_to_utf8(option_buf)) == NULL) if ((command_option_local = utf16_to_utf8(option_buf)) == NULL)
goto cleanup; goto cleanup;
if (arg_buf[0] != L'\0') if (arg_buf[0] != L'\0')
if ((shell_arguments_local = utf16_to_utf8(arg_buf)) == NULL) if ((shell_arguments_local = utf16_to_utf8(arg_buf)) == NULL)
goto cleanup; goto cleanup;
convertToBackslash(pw_shellpath_local); convertToBackslash(pw_shellpath_local);
to_lower_case(pw_shellpath_local); to_lower_case(pw_shellpath_local);
pw_shellpath = pw_shellpath_local; pw_shellpath = pw_shellpath_local;
pw_shellpath_local = NULL; pw_shellpath_local = NULL;
shell_command_option = command_option_local; shell_command_option = command_option_local;
shell_arguments = shell_arguments_local; shell_arguments = shell_arguments_local;
command_option_local = NULL; command_option_local = NULL;
shell_arguments_local = NULL; shell_arguments_local = NULL;
ret = 0; ret = 0;
cleanup: cleanup:
if (pw_shellpath_local) if (pw_shellpath_local)
free(pw_shellpath_local); free(pw_shellpath_local);
if (command_option_local) if (command_option_local)
free(command_option_local); free(command_option_local);
if (shell_arguments_local) if (shell_arguments_local)
free(shell_arguments_local); free(shell_arguments_local);
return ret; return ret;
} }
int int
initialize_pw() initialize_pw()
{ {
if (set_defaultshell() != 0) if (set_defaultshell() != 0)
return -1; return -1;
if (pw.pw_shell != pw_shellpath) { if (pw.pw_shell != pw_shellpath) {
memset(&pw, 0, sizeof(pw)); memset(&pw, 0, sizeof(pw));
pw.pw_shell = pw_shellpath; pw.pw_shell = pw_shellpath;
pw.pw_passwd = "\0"; pw.pw_passwd = "\0";
/* pw_uid = 0 for root on Unix and SSH code has specific restrictions for root /* pw_uid = 0 for root on Unix and SSH code has specific restrictions for root
* that are not applicable in Windows */ * that are not applicable in Windows */
pw.pw_uid = 1; pw.pw_uid = 1;
} }
return 0; return 0;
} }
static void static void
clean_pw() clean_pw()
{ {
if (pw.pw_name) if (pw.pw_name)
free(pw.pw_name); free(pw.pw_name);
if (pw.pw_dir) if (pw.pw_dir)
free(pw.pw_dir); free(pw.pw_dir);
pw.pw_name = NULL; pw.pw_name = NULL;
pw.pw_dir = NULL; pw.pw_dir = NULL;
} }
static int static int
reset_pw() reset_pw()
{ {
if (initialize_pw() != 0) if (initialize_pw() != 0)
return -1; return -1;
clean_pw(); clean_pw();
return 0; return 0;
} }
static struct passwd* static struct passwd*
get_passwd(const wchar_t * user_utf16, PSID sid) get_passwd(const wchar_t * user_utf16, PSID sid)
{ {
wchar_t user_resolved[DNLEN + 1 + UNLEN + 1]; wchar_t user_resolved[DNLEN + 1 + UNLEN + 1];
struct passwd *ret = NULL; struct passwd *ret = NULL;
wchar_t *sid_string = NULL, *tmp = NULL, *user_utf16_modified = NULL; wchar_t *sid_string = NULL, *tmp = NULL, *user_utf16_modified = NULL;
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX], profile_home_exp[PATH_MAX]; wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX], profile_home_exp[PATH_MAX];
DWORD reg_path_len = PATH_MAX; DWORD reg_path_len = PATH_MAX;
HKEY reg_key = 0; HKEY reg_key = 0;
BYTE binary_sid[SECURITY_MAX_SID_SIZE]; BYTE binary_sid[SECURITY_MAX_SID_SIZE];
DWORD sid_size = ARRAYSIZE(binary_sid); DWORD sid_size = ARRAYSIZE(binary_sid);
WCHAR domain_name[DNLEN + 1] = L""; WCHAR domain_name[DNLEN + 1] = L"";
DWORD domain_name_size = DNLEN + 1; DWORD domain_name_size = DNLEN + 1;
SID_NAME_USE account_type = 0; SID_NAME_USE account_type = 0;
errno = 0; errno = 0;
if (reset_pw() != 0) if (reset_pw() != 0)
return NULL; return NULL;
/* /*
* We support both "domain\user" and "domain/user" formats. * We support both "domain\user" and "domain/user" formats.
* But win32 APIs only accept domain\user format so convert it. * But win32 APIs only accept domain\user format so convert it.
*/ */
if (user_utf16) { if (user_utf16) {
user_utf16_modified = _wcsdup(user_utf16); user_utf16_modified = _wcsdup(user_utf16);
if (!user_utf16_modified) { if (!user_utf16_modified) {
errno = ENOMEM; errno = ENOMEM;
error("%s failed to duplicate %s", __func__, user_utf16); error("%s failed to duplicate %s", __func__, user_utf16);
goto cleanup; goto cleanup;
} }
if (tmp = wcsstr(user_utf16_modified, L"/")) if (tmp = wcsstr(user_utf16_modified, L"/"))
*tmp = L'\\'; *tmp = L'\\';
} }
/* skip forward lookup on name if sid was passed in */ /* skip forward lookup on name if sid was passed in */
if (sid != NULL) if (sid != NULL)
CopySid(sizeof(binary_sid), binary_sid, sid); CopySid(sizeof(binary_sid), binary_sid, sid);
/* else attempt to lookup the account; this will verify the account is valid and /* else attempt to lookup the account; this will verify the account is valid and
* is will return its sid and the realm that owns it */ * is will return its sid and the realm that owns it */
else if(LookupAccountNameW(NULL, user_utf16_modified, binary_sid, &sid_size, else if (lookup_sid(user_utf16_modified, binary_sid, &sid_size) == NULL) {
domain_name, &domain_name_size, &account_type) == 0) { errno = ENOENT;
errno = ENOENT; debug("%s: lookup_sid() failed: %d.", __FUNCTION__, GetLastError());
debug("%s: LookupAccountName() failed: %d.", __FUNCTION__, GetLastError()); goto cleanup;
goto cleanup; }
}
/* convert the binary string to a string */
/* convert the binary string to a string */ if (ConvertSidToStringSidW((PSID) binary_sid, &sid_string) == FALSE) {
if (ConvertSidToStringSidW((PSID) binary_sid, &sid_string) == FALSE) { errno = errno_from_Win32LastError();
errno = errno_from_Win32LastError(); goto cleanup;
goto cleanup; }
}
/* lookup the account name from the sid */
/* lookup the account name from the sid */ WCHAR user_name[UNLEN + 1];
WCHAR user_name[UNLEN + 1]; DWORD user_name_length = ARRAYSIZE(user_name);
DWORD user_name_length = ARRAYSIZE(user_name); domain_name_size = DNLEN + 1;
domain_name_size = DNLEN + 1; if (LookupAccountSidW(NULL, binary_sid, user_name, &user_name_length,
if (LookupAccountSidW(NULL, binary_sid, user_name, &user_name_length, domain_name, &domain_name_size, &account_type) == 0) {
domain_name, &domain_name_size, &account_type) == 0) { errno = errno_from_Win32LastError();
errno = errno_from_Win32LastError(); debug("%s: LookupAccountSid() failed: %d.", __FUNCTION__, GetLastError());
debug("%s: LookupAccountSid() failed: %d.", __FUNCTION__, GetLastError()); goto cleanup;
goto cleanup; }
}
/* verify passed account is actually a user account */
/* verify passed account is actually a user account */ if (account_type != SidTypeUser) {
if (account_type != SidTypeUser) { errno = ENOENT;
errno = ENOENT; debug3("%s: Invalid account type: %d.", __FUNCTION__, account_type);
debug3("%s: Invalid account type: %d.", __FUNCTION__, account_type); goto cleanup;
goto cleanup; }
}
/* fetch the computer name so we can determine if the specified user is local or not */
/* fetch the computer name so we can determine if the specified user is local or not */ wchar_t computer_name[CNLEN + 1];
wchar_t computer_name[CNLEN + 1]; DWORD computer_name_size = ARRAYSIZE(computer_name);
DWORD computer_name_size = ARRAYSIZE(computer_name); if (GetComputerNameW(computer_name, &computer_name_size) == 0) {
if (GetComputerNameW(computer_name, &computer_name_size) == 0) { error_f("GetComputerNameW() failed with error:%d", GetLastError());
goto cleanup; goto cleanup;
} }
/* if standard local user name or system account, just use name without decoration */ /* if standard local user name or system account, just use name without decoration */
const SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY; const SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
if (((_wcsicmp(domain_name, computer_name) == 0) && (_wcsicmp(computer_name, user_name) != 0)) || if ((_wcsicmp(domain_name, computer_name) == 0) ||
((memcmp(&nt_authority, GetSidIdentifierAuthority((PSID)binary_sid), sizeof(SID_IDENTIFIER_AUTHORITY)) == 0) && ((memcmp(&nt_authority, GetSidIdentifierAuthority((PSID)binary_sid), sizeof(SID_IDENTIFIER_AUTHORITY)) == 0) &&
(((SID*)binary_sid)->SubAuthority[0] == SECURITY_LOCAL_SYSTEM_RID))) { (((SID*)binary_sid)->SubAuthority[0] == SECURITY_LOCAL_SYSTEM_RID))) {
wcscpy_s(user_resolved, ARRAYSIZE(user_resolved), user_name); wcscpy_s(user_resolved, ARRAYSIZE(user_resolved), user_name);
} }
/* put any other format in sam compatible format */ /* put any other format in sam compatible format */
else else
swprintf_s(user_resolved, ARRAYSIZE(user_resolved), L"%s\\%s", domain_name, user_name); swprintf_s(user_resolved, ARRAYSIZE(user_resolved), L"%s\\%s", domain_name, user_name);
/* if one of below fails, set profile path to Windows directory */ /* if one of below fails, set profile path to Windows directory */
if (swprintf_s(reg_path, PATH_MAX, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_string) == -1 || if (swprintf_s(reg_path, PATH_MAX, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_string) == -1 ||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 || RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, &reg_key) != 0 ||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &reg_path_len) != 0 || RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &reg_path_len) != 0 ||
ExpandEnvironmentStringsW(profile_home, NULL, 0) > PATH_MAX || ExpandEnvironmentStringsW(profile_home, NULL, 0) > PATH_MAX ||
ExpandEnvironmentStringsW(profile_home, profile_home_exp, PATH_MAX) == 0) ExpandEnvironmentStringsW(profile_home, profile_home_exp, PATH_MAX) == 0)
if (GetWindowsDirectoryW(profile_home_exp, PATH_MAX) == 0) { if (GetWindowsDirectoryW(profile_home_exp, PATH_MAX) == 0) {
debug3("GetWindowsDirectoryW failed with %d", GetLastError()); debug3("GetWindowsDirectoryW failed with %d", GetLastError());
errno = EOTHER; errno = EOTHER;
goto cleanup; goto cleanup;
} }
/* convert to utf8, make name lowercase, and assign to output structure*/ /* convert to utf8, make name lowercase, and assign to output structure*/
_wcslwr_s(user_resolved, wcslen(user_resolved) + 1); _wcslwr_s(user_resolved, wcslen(user_resolved) + 1);
if ((pw.pw_name = utf16_to_utf8(user_resolved)) == NULL || if ((pw.pw_name = utf16_to_utf8(user_resolved)) == NULL ||
(pw.pw_dir = utf16_to_utf8(profile_home_exp)) == NULL) { (pw.pw_dir = utf16_to_utf8(profile_home_exp)) == NULL) {
clean_pw(); clean_pw();
errno = ENOMEM; errno = ENOMEM;
goto cleanup; goto cleanup;
} }
ret = &pw; ret = &pw;
cleanup: cleanup:
if (sid_string) if (sid_string)
LocalFree(sid_string); LocalFree(sid_string);
if (reg_key) if (reg_key)
RegCloseKey(reg_key); RegCloseKey(reg_key);
return ret; return ret;
} }
static struct passwd* static struct passwd*
getpwnam_placeholder(const char* user) { getpwnam_placeholder(const char* user) {
wchar_t tmp_home[PATH_MAX]; wchar_t tmp_home[PATH_MAX];
char *pw_name = NULL, *pw_dir = NULL; char *pw_name = NULL, *pw_dir = NULL;
struct passwd* ret = NULL; struct passwd* ret = NULL;
if (GetWindowsDirectoryW(tmp_home, PATH_MAX) == 0) { if (GetWindowsDirectoryW(tmp_home, PATH_MAX) == 0) {
debug3("GetWindowsDirectoryW failed with %d", GetLastError()); debug3("GetWindowsDirectoryW failed with %d", GetLastError());
errno = EOTHER; errno = EOTHER;
goto cleanup; goto cleanup;
} }
pw_name = _strdup(user); pw_name = _strdup(user);
pw_dir = utf16_to_utf8(tmp_home); pw_dir = utf16_to_utf8(tmp_home);
if (!pw_name || !pw_dir) { if (!pw_name || !pw_dir) {
errno = ENOMEM; errno = ENOMEM;
goto cleanup; goto cleanup;
} }
pw.pw_name = pw_name; pw.pw_name = pw_name;
pw_name = NULL; pw_name = NULL;
pw.pw_dir = pw_dir; pw.pw_dir = pw_dir;
pw_dir = NULL; pw_dir = NULL;
ret = &pw; ret = &pw;
cleanup: cleanup:
if (pw_name) if (pw_name)
free(pw_name); free(pw_name);
if (pw_dir) if (pw_dir)
free(pw_dir); free(pw_dir);
return ret; return ret;
} }
struct passwd* struct passwd*
w32_getpwnam(const char *user_utf8) w32_getpwnam(const char *user_utf8)
{ {
struct passwd* ret = NULL; struct passwd* ret = NULL;
wchar_t * user_utf16 = NULL; wchar_t * user_utf16 = NULL;
user_utf16 = utf8_to_utf16(user_utf8); user_utf16 = utf8_to_utf16(user_utf8);
if (user_utf16 == NULL) { if (user_utf16 == NULL) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
ret = get_passwd(user_utf16, NULL); ret = get_passwd(user_utf16, NULL);
if (ret != NULL) if (ret != NULL)
goto done; goto done;
/* for unpriviliged user account, create placeholder and return*/ /* for unpriviliged user account, create placeholder and return*/
if (_stricmp(user_utf8, "sshd") == 0) { if (_stricmp(user_utf8, "sshd") == 0) {
ret = getpwnam_placeholder(user_utf8); ret = getpwnam_placeholder(user_utf8);
goto done; goto done;
} }
/* check if custom passwd auth is enabled */ /* check if custom passwd auth is enabled */
if (get_custom_lsa_package()) if (get_custom_lsa_package())
ret = getpwnam_placeholder(user_utf8); ret = getpwnam_placeholder(user_utf8);
done: done:
if (user_utf16) if (user_utf16)
free(user_utf16); free(user_utf16);
return ret; return ret;
} }
struct passwd* struct passwd*
w32_getpwuid(uid_t uid) w32_getpwuid(uid_t uid)
{ {
struct passwd* ret = NULL; struct passwd* ret = NULL;
PSID cur_user_sid = NULL; PSID cur_user_sid = NULL;
if ((cur_user_sid = get_sid(NULL)) == NULL) if ((cur_user_sid = get_sid(NULL)) == NULL)
goto cleanup; goto cleanup;
ret = get_passwd(NULL, cur_user_sid); ret = get_passwd(NULL, cur_user_sid);
cleanup: cleanup:
if (cur_user_sid) if (cur_user_sid)
free(cur_user_sid); free(cur_user_sid);
return ret; return ret;
} }
char * char *
group_from_gid(gid_t gid, int nogroup) group_from_gid(gid_t gid, int nogroup)
{ {
return "-"; return "-";
} }
char * char *
user_from_uid(uid_t uid, int nouser) user_from_uid(uid_t uid, int nouser)
{ {
return "-"; return "-";
} }
uid_t uid_t
w32_getuid(void) w32_getuid(void)
{ {
return 1; return 1;
} }
gid_t gid_t
getgid(void) getgid(void)
{ {
return 0; return 0;
} }
uid_t uid_t
geteuid(void) geteuid(void)
{ {
return 1; return 1;
} }
gid_t gid_t
getegid(void) getegid(void)
{ {
return 0; return 0;
} }
int int
setuid(uid_t uid) setuid(uid_t uid)
{ {
return 0; return 0;
} }
int int
setgid(gid_t gid) setgid(gid_t gid)
{ {
return 0; return 0;
} }
int int
seteuid(uid_t uid) seteuid(uid_t uid)
{ {
return 0; return 0;
} }
int int
setegid(gid_t gid) setegid(gid_t gid)
{ {
return 0; return 0;
} }
struct passwd *getpwent(void) struct passwd *getpwent(void)
{ {
return NULL; return NULL;
} }
void setpwent(void) void setpwent(void)
{ {
return; return;
} }
void void
endpwent(void) endpwent(void)
{ {
return; return;
} }