mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
Tidied do_exex_windows in session.c (https://github.com/PowerShell/Win32-OpenSSH/issues/510)
This commit is contained in:
parent
47c4ec917b
commit
9906e0515d
@ -20,6 +20,7 @@ struct passwd {
|
||||
gid_t pw_gid; /* numerical group ID */
|
||||
char *pw_dir; /* initial working directory */
|
||||
char *pw_shell; /* path to shell */
|
||||
char *pw_sid; /* sid of user */
|
||||
};
|
||||
|
||||
/*start - declarations not applicable in Windows */
|
||||
|
@ -83,7 +83,7 @@ static struct passwd*
|
||||
get_passwd(const char *user_utf8, LPWSTR user_sid) {
|
||||
struct passwd *ret = NULL;
|
||||
wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
|
||||
char *uname_utf8 = NULL, *pw_home_utf8 = NULL;
|
||||
char *uname_utf8 = NULL, *pw_home_utf8 = NULL, *user_sid_utf8;
|
||||
LPBYTE user_info = NULL;
|
||||
LPWSTR user_sid_local = NULL;
|
||||
wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX];
|
||||
@ -156,7 +156,8 @@ get_passwd(const char *user_utf8, LPWSTR user_sid) {
|
||||
GetWindowsDirectoryW(profile_home, PATH_MAX);
|
||||
|
||||
if ((uname_utf8 = _strdup(user_utf8)) == NULL ||
|
||||
(pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) {
|
||||
(pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL ||
|
||||
(user_sid_utf8 = utf16_to_utf8(user_sid)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
@ -165,7 +166,10 @@ get_passwd(const char *user_utf8, LPWSTR user_sid) {
|
||||
uname_utf8 = NULL;
|
||||
pw.pw_dir = pw_home_utf8;
|
||||
pw_home_utf8 = NULL;
|
||||
pw.pw_sid = user_sid_utf8;
|
||||
user_sid_utf8 = NULL;
|
||||
ret = &pw;
|
||||
|
||||
done:
|
||||
if (user_utf16)
|
||||
free(user_utf16);
|
||||
@ -181,6 +185,8 @@ done:
|
||||
RegCloseKey(reg_key);
|
||||
if (pdc)
|
||||
NetApiBufferFree(pdc);
|
||||
if (user_sid_utf8)
|
||||
free(user_sid_utf8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
261
session.c
261
session.c
@ -310,27 +310,106 @@ xauth_valid_string(const char *s)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void setup_session_vars(Session* s)
|
||||
#define UTF8_TO_UTF16_FATAL(o, i) do { \
|
||||
if (o != NULL) free(o); \
|
||||
if ((o = utf8_to_utf16(i)) == NULL) \
|
||||
fatal("%s, out of memory", __func__); \
|
||||
} while (0)
|
||||
|
||||
static void setup_session_user_vars(Session* s) /* set user environment variables from user profile */
|
||||
{
|
||||
wchar_t* pw_dir_w;
|
||||
wchar_t* tmp;
|
||||
char buf[128];
|
||||
/* retrieve and set env variables. */
|
||||
HKEY reg_key = 0;
|
||||
HANDLE token = s->authctxt->methoddata;
|
||||
wchar_t *path;
|
||||
wchar_t name[256];
|
||||
wchar_t *data = NULL, *data_expanded = NULL, *path_value = NULL, *to_apply;
|
||||
DWORD type, name_chars = 256, data_chars = 0, data_expanded_chars = 0, required, i = 0;
|
||||
LONG ret;
|
||||
|
||||
if (ImpersonateLoggedOnUser(token) == FALSE)
|
||||
debug("Failed to impersonate user token, %d", GetLastError());
|
||||
SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA");
|
||||
SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE");
|
||||
SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA");
|
||||
|
||||
ret = RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, ®_key);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
error("Error retrieving user environment variables. RegOpenKeyExW returned %d", ret);
|
||||
else while (1) {
|
||||
to_apply = NULL;
|
||||
required = data_chars * 2;
|
||||
name_chars = 256;
|
||||
ret = RegEnumValueW(reg_key, i++, name, &name_chars, 0, &type, (LPBYTE)data, &required);
|
||||
if (ret == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
else if (ret != ERROR_SUCCESS) {
|
||||
error("Error retrieving user environment variables. RegEnumValueW returned %d", ret);
|
||||
break;
|
||||
}
|
||||
else if (required > data_chars * 2) {
|
||||
if (data != NULL)
|
||||
free(data);
|
||||
data = xmalloc(required);
|
||||
data_chars = required/2;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == REG_SZ)
|
||||
to_apply = data;
|
||||
else if (type == REG_EXPAND_SZ) {
|
||||
required = ExpandEnvironmentStringsW(data, data_expanded, data_expanded_chars);
|
||||
if (required > data_expanded_chars) {
|
||||
if (data_expanded)
|
||||
free(data_expanded);
|
||||
data_expanded = xmalloc(required * 2);
|
||||
data_expanded_chars = required;
|
||||
ExpandEnvironmentStringsW(data, data_expanded, data_expanded_chars);
|
||||
}
|
||||
to_apply = data_expanded;
|
||||
}
|
||||
|
||||
if (wcsicmp(name, L"PATH") == 0) {
|
||||
if ((required = GetEnvironmentVariableW(L"PATH", NULL, 0)) != 0) {
|
||||
/* "required" includes null term */
|
||||
path_value = xmalloc((wcslen(to_apply) + 1 + required)*2);
|
||||
GetEnvironmentVariableW(L"PATH", path_value, required);
|
||||
path_value[required - 1] = L';';
|
||||
memcpy(path_value + required, to_apply, (wcslen(to_apply) + 1) * 2);
|
||||
to_apply = path_value;
|
||||
}
|
||||
|
||||
}
|
||||
if (to_apply)
|
||||
SetEnvironmentVariableW(name, to_apply);
|
||||
}
|
||||
if (reg_key)
|
||||
RegCloseKey(reg_key);
|
||||
if (data)
|
||||
free(data);
|
||||
if (data_expanded)
|
||||
free(data_expanded);
|
||||
if (path_value)
|
||||
free(path_value);
|
||||
RevertToSelf();
|
||||
}
|
||||
|
||||
static void setup_session_vars(Session* s) {
|
||||
wchar_t *pw_dir_w = NULL, *tmp = NULL;
|
||||
char buf[256];
|
||||
wchar_t wbuf[256];
|
||||
char* laddr;
|
||||
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
|
||||
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
|
||||
fatal("%s: out of memory");
|
||||
|
||||
if ((tmp = utf8_to_utf16(s->pw->pw_name)) == NULL)
|
||||
fatal("%s, out of memory");
|
||||
UTF8_TO_UTF16_FATAL(pw_dir_w, s->pw->pw_dir);
|
||||
UTF8_TO_UTF16_FATAL(tmp, s->pw->pw_name);
|
||||
SetEnvironmentVariableW(L"USERNAME", tmp);
|
||||
free(tmp);
|
||||
|
||||
if (s->display)
|
||||
SetEnvironmentVariableA("DISPLAY", s->display);
|
||||
|
||||
|
||||
if (s->display) {
|
||||
UTF8_TO_UTF16_FATAL(tmp, s->display);
|
||||
SetEnvironmentVariableW(L"DISPLAY", tmp);
|
||||
}
|
||||
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w);
|
||||
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w);
|
||||
|
||||
@ -343,111 +422,31 @@ void setup_session_vars(Session* s)
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %d",
|
||||
ssh->remote_ipaddr, ssh->remote_port, ssh->local_port);
|
||||
|
||||
SetEnvironmentVariableA("SSH_CLIENT", buf);
|
||||
|
||||
laddr = get_local_ipaddr(packet_get_connection_in());
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
|
||||
ssh->remote_ipaddr, ssh->remote_port, laddr, ssh->local_port);
|
||||
|
||||
free(laddr);
|
||||
|
||||
SetEnvironmentVariableA("SSH_CONNECTION", buf);
|
||||
|
||||
if (original_command)
|
||||
SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command);
|
||||
|
||||
if (original_command) {
|
||||
UTF8_TO_UTF16_FATAL(tmp, original_command);
|
||||
SetEnvironmentVariableW(L"SSH_ORIGINAL_COMMAND", tmp);
|
||||
}
|
||||
|
||||
if ((s->term) && (s->term[0]))
|
||||
SetEnvironmentVariable("TERM", s->term);
|
||||
SetEnvironmentVariableA("TERM", s->term);
|
||||
|
||||
if (!s->is_subsystem) {
|
||||
snprintf(buf, sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME"));
|
||||
SetEnvironmentVariableA("PROMPT", buf);
|
||||
}
|
||||
|
||||
/*set user environment variables*/
|
||||
{
|
||||
UCHAR InfoBuffer[1000];
|
||||
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
|
||||
DWORD dwInfoBufferSize, tmp_len;
|
||||
LPWSTR sid_str = NULL;
|
||||
wchar_t reg_path[MAX_PATH];
|
||||
HKEY reg_key = 0;
|
||||
HANDLE token = s->authctxt->methoddata;
|
||||
|
||||
tmp_len = MAX_PATH;
|
||||
if (GetTokenInformation(token, TokenUser, InfoBuffer,
|
||||
1000, &dwInfoBufferSize) == FALSE ||
|
||||
ConvertSidToStringSidW(pTokenUser->User.Sid, &sid_str) == FALSE ||
|
||||
swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", sid_str) == MAX_PATH ||
|
||||
RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, ®_key) != 0 ||
|
||||
RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)pw_dir_w, &tmp_len) != 0) {
|
||||
/* one of the above failed */
|
||||
debug("cannot retirve profile path - perhaps user profile is not created yet");
|
||||
}
|
||||
|
||||
if (sid_str)
|
||||
LocalFree(sid_str);
|
||||
|
||||
if (reg_key)
|
||||
RegCloseKey(reg_key);
|
||||
|
||||
/* retrieve and set env variables. */
|
||||
{
|
||||
#define MAX_VALUE_LEN 1000
|
||||
#define MAX_DATA_LEN 2000
|
||||
#define MAX_EXPANDED_DATA_LEN 5000
|
||||
/* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/
|
||||
wchar_t *path;
|
||||
wchar_t value_name[MAX_VALUE_LEN];
|
||||
wchar_t value_data[MAX_DATA_LEN], value_data_expanded[MAX_EXPANDED_DATA_LEN], *to_apply;
|
||||
DWORD value_type, name_len, data_len;
|
||||
int i;
|
||||
LONG ret;
|
||||
|
||||
if (ImpersonateLoggedOnUser(token) == FALSE)
|
||||
debug("Failed to impersonate user token, %d", GetLastError());
|
||||
SET_USER_ENV(FOLDERID_LocalAppData, L"LOCALAPPDATA");
|
||||
SET_USER_ENV(FOLDERID_Profile, L"USERPROFILE");
|
||||
SET_USER_ENV(FOLDERID_RoamingAppData, L"APPDATA");
|
||||
reg_key = 0;
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Environment", 0, KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS) {
|
||||
i = 0;
|
||||
while (1) {
|
||||
name_len = MAX_VALUE_LEN * 2;
|
||||
data_len = MAX_DATA_LEN * 2;
|
||||
to_apply = NULL;
|
||||
if (RegEnumValueW(reg_key, i++, value_name, &name_len, 0, &value_type, (LPBYTE)&value_data, &data_len) != ERROR_SUCCESS)
|
||||
break;
|
||||
if (value_type == REG_SZ)
|
||||
to_apply = value_data;
|
||||
else if (value_type == REG_EXPAND_SZ) {
|
||||
ExpandEnvironmentStringsW(value_data, value_data_expanded, MAX_EXPANDED_DATA_LEN);
|
||||
to_apply = value_data_expanded;
|
||||
}
|
||||
|
||||
if (wcsicmp(value_name, L"PATH") == 0) {
|
||||
DWORD size;
|
||||
if ((size = GetEnvironmentVariableW(L"PATH", NULL, 0)) != ERROR_ENVVAR_NOT_FOUND) {
|
||||
memcpy(value_data_expanded + size, to_apply, (wcslen(to_apply) + 1) * 2);
|
||||
GetEnvironmentVariableW(L"PATH", value_data_expanded, MAX_EXPANDED_DATA_LEN);
|
||||
value_data_expanded[size - 1] = L';';
|
||||
to_apply = value_data_expanded;
|
||||
}
|
||||
|
||||
}
|
||||
if (to_apply)
|
||||
SetEnvironmentVariableW(value_name, to_apply);
|
||||
}
|
||||
RegCloseKey(reg_key);
|
||||
}
|
||||
RevertToSelf();
|
||||
}
|
||||
UTF8_TO_UTF16_FATAL(tmp, s->pw->pw_name);
|
||||
_snwprintf(wbuf, sizeof(wbuf)/2, L"%ls@%ls $P$G", tmp, _wgetenv(L"COMPUTERNAME"));
|
||||
SetEnvironmentVariableW(L"PROMPT", wbuf);
|
||||
}
|
||||
|
||||
setup_session_user_vars(s);
|
||||
free(pw_dir_w);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
char* w32_programdir();
|
||||
@ -459,7 +458,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
wchar_t *exec_command_w = NULL, *pw_dir_w;
|
||||
|
||||
if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR) {
|
||||
error("sub system not supported, exiting\n");
|
||||
error("sub system not supported, exiting");
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
}
|
||||
@ -469,7 +468,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
fatal("%s: cannot create pipe: %.100s", __func__, strerror(errno));
|
||||
|
||||
if ((pw_dir_w = utf8_to_utf16(s->pw->pw_dir)) == NULL)
|
||||
fatal("%s: out of memory");
|
||||
fatal("%s: out of memory", __func__);
|
||||
|
||||
|
||||
set_nonblock(pipein[0]);
|
||||
@ -494,7 +493,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
else {/*relative*/
|
||||
exec_command = malloc(strlen(progdir) + 1 + strlen(command));
|
||||
if (exec_command == NULL)
|
||||
fatal("%s, out of memory");
|
||||
fatal("%s, out of memory", __func__);
|
||||
memcpy(exec_command, progdir, strlen(progdir));
|
||||
exec_command[strlen(progdir)] = '\\';
|
||||
memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1);
|
||||
@ -503,7 +502,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
char *shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty ", *c;
|
||||
exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command ? strlen(command) : 0) + 1);
|
||||
if (exec_command == NULL)
|
||||
fatal("%s, out of memory");
|
||||
fatal("%s, out of memory", __func__);
|
||||
c = exec_command;
|
||||
memcpy(c, progdir, strlen(progdir));
|
||||
c += strlen(progdir);
|
||||
@ -519,37 +518,23 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
|
||||
/* setup Environment varibles */
|
||||
setup_session_vars(s);
|
||||
|
||||
extern int debug_flag;
|
||||
|
||||
/* start the process */
|
||||
{
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOW si;
|
||||
|
||||
BOOL b;
|
||||
|
||||
HANDLE hToken = INVALID_HANDLE_VALUE;
|
||||
|
||||
|
||||
/*
|
||||
* Assign sockets to StartupInfo
|
||||
*/
|
||||
|
||||
memset(&si, 0, sizeof(STARTUPINFO));
|
||||
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.lpReserved = 0;
|
||||
si.lpTitle = NULL; /* NULL means use exe name as title */
|
||||
si.dwX = 0;
|
||||
si.dwY = 0;
|
||||
si.dwXSize = 5;
|
||||
si.dwYSize = 5;
|
||||
si.dwXCountChars = s->col;
|
||||
si.dwYCountChars = s->row;
|
||||
si.dwFillAttribute = 0;
|
||||
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
|
||||
si.wShowWindow = 0; // FALSE ;
|
||||
si.cbReserved2 = 0;
|
||||
si.lpReserved2 = 0;
|
||||
|
||||
si.hStdInput = (HANDLE)w32_fd_to_handle(pipein[0]);
|
||||
si.hStdOutput = (HANDLE)w32_fd_to_handle(pipeout[1]);
|
||||
@ -559,29 +544,20 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
hToken = s->authctxt->methoddata;
|
||||
|
||||
debug("Executing command: %s", exec_command);
|
||||
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
|
||||
|
||||
/* Create the child process */
|
||||
|
||||
exec_command_w = utf8_to_utf16(exec_command);
|
||||
|
||||
/* in debug mode launch using sshd.exe user context */
|
||||
if (debug_flag)
|
||||
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
|
||||
DETACHED_PROCESS, NULL, pw_dir_w,
|
||||
&si, &pi);
|
||||
else
|
||||
else /* launch as client user context */
|
||||
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
|
||||
DETACHED_PROCESS , NULL, pw_dir_w,
|
||||
&si, &pi);
|
||||
|
||||
if (!b)
|
||||
{
|
||||
debug("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||
free(pw_dir_w);
|
||||
free(exec_command_w);
|
||||
CloseHandle(hToken);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
fatal("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||
else if (pty) { /*attach to shell console */
|
||||
FreeConsole();
|
||||
if (!debug_flag)
|
||||
@ -610,6 +586,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
s->pid = pi.dwProcessId;
|
||||
register_child(pi.hProcess, pi.dwProcessId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set interactive/non-interactive mode.
|
||||
*/
|
||||
@ -625,16 +602,14 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
* Enter the interactive session. Note: server_loop must be able to
|
||||
* handle the case that fdin and fdout are the same.
|
||||
*/
|
||||
|
||||
if (s->ttyfd == -1)
|
||||
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
|
||||
else
|
||||
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); // tty interactive session
|
||||
session_set_fds(s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); /* tty interactive session */
|
||||
|
||||
free(pw_dir_w);
|
||||
free(exec_command_w);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -2389,9 +2364,9 @@ static int
|
||||
session_env_req(Session *s)
|
||||
{
|
||||
char *name, *val;
|
||||
u_int name_len, val_len, i;
|
||||
u_int name_chars, val_len, i;
|
||||
|
||||
name = packet_get_cstring(&name_len);
|
||||
name = packet_get_cstring(&name_chars);
|
||||
val = packet_get_cstring(&val_len);
|
||||
packet_check_eom();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user