Changes to remove Impersonation Privilege requirement in sshd (#142)

https://github.com/PowerShell/Win32-OpenSSH/issues/726
This commit is contained in:
Manoj Ampalam 2017-05-18 22:57:42 -07:00 committed by GitHub
parent afc6ca91f7
commit 894f6dd79c
5 changed files with 108 additions and 133 deletions

View File

@ -96,9 +96,9 @@ cmd.exe /c 'sc.exe sdset ssh-agent D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPW
New-Service -Name sshd -BinaryPathName $sshdpath -Description "SSH Daemon" -StartupType Manual -DependsOn ssh-agent | Out-Null
sc.exe config sshd obj= $sshdAccount
sc.exe privs sshd SeAssignPrimaryTokenPrivilege
Add-Privilege -Account $sshdAccount -Privilege SeAssignPrimaryTokenPrivilege
Add-Privilege -Account $sshdAccount -Privilege SeServiceLogonRight
if(-not (test-path $logsdir -PathType Container))
{

View File

@ -122,7 +122,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level1</WarningLevel>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WIN32_WINNT=0x600;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>false</SDLCheck>
@ -164,7 +164,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level1</WarningLevel>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>

View File

@ -223,7 +223,7 @@ SendKeyStroke(HANDLE hInput, int keyStroke, char character)
void
ProcessIncomingKeys(char * ansikey)
{
int keylen = strlen(ansikey);
int keylen = (int)strlen(ansikey);
if (!keylen)
return;
@ -407,7 +407,7 @@ SendCharacter(HANDLE hInput, WORD attributes, wchar_t character)
StringCbPrintfExA(Next, SizeLeft, &Next, &SizeLeft, 0, "m", Color);
if (bUseAnsiEmulation && attributes != pattributes)
WriteFile(hInput, formatted_output, (Next - formatted_output), &wr, NULL);
WriteFile(hInput, formatted_output, (DWORD)(Next - formatted_output), &wr, NULL);
/* East asian languages have 2 bytes for each character, only use the first */
if (!(attributes & COMMON_LVB_TRAILING_BYTE)) {
@ -481,8 +481,8 @@ SizeWindow(HANDLE hInput)
inputSi.dwYCountChars = 25;
}
srWindowRect.Right = (SHORT)(min(inputSi.dwXCountChars, coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT)(min(inputSi.dwYCountChars, coordScreen.Y) - 1);
srWindowRect.Right = (SHORT)(min(inputSi.dwXCountChars, (DWORD)coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT)(min(inputSi.dwYCountChars, (DWORD)coordScreen.Y) - 1);
srWindowRect.Left = srWindowRect.Top = (SHORT)0;
/* Define the new console buffer size to be the maximum possible */
@ -511,14 +511,12 @@ MonitorChild(_In_ LPVOID lpParameter)
DWORD
ProcessEvent(void *p)
{
char f[255];
wchar_t chUpdate;
WORD wAttributes;
WORD wX;
WORD wY;
DWORD dwProcessId;
DWORD wr = 0;
DWORD dwMode;
DWORD event;
HWND hwnd;
LONG idObject;
@ -640,8 +638,8 @@ ProcessEvent(void *p)
return dwError;
}
if (readRect.Top > currentLine)
for (SHORT n = currentLine; n < readRect.Top; n++)
if ((DWORD)readRect.Top > currentLine)
for (DWORD n = currentLine; n < (DWORD)readRect.Top; n++)
SendLF(pipe_out);
/* Set cursor location based on the reported location from the message */
@ -779,8 +777,6 @@ ProcessEventQueue(LPVOID p)
if (child_in != INVALID_HANDLE_VALUE && child_in != NULL &&
child_out != INVALID_HANDLE_VALUE && child_out != NULL) {
DWORD dwInputMode;
DWORD dwOutputMode;
ZeroMemory(&consoleInfo, sizeof(consoleInfo));
consoleInfo.cbSize = sizeof(consoleInfo);
@ -908,8 +904,6 @@ ConsoleEventProc(HWINEVENTHOOK hWinEventHook,
DWORD
ProcessMessages(void* p)
{
BOOL ret;
DWORD dwMode;
DWORD dwStatus;
SECURITY_ATTRIBUTES sa;
MSG msg;
@ -966,8 +960,6 @@ start_with_pty(wchar_t *command)
wchar_t cmd[MAX_CMD_LEN];
SECURITY_ATTRIBUTES sa;
BOOL ret;
DWORD dwThreadId;
DWORD dwMode;
DWORD dwStatus;
HANDLE hEventHook = NULL;
HMODULE hm_kernel32 = NULL, hm_user32 = NULL;
@ -1226,6 +1218,102 @@ cleanup:
return child_exit_code;
}
#include <Shlobj.h>
#include <Sddl.h>
static void* xmalloc(size_t size) {
void* ptr;
if ((ptr = malloc(size)) == NULL) {
printf("out of memory");
exit(EXIT_FAILURE);
}
return ptr;
}
#define SET_USER_ENV(folder_id, evn_variable) do { \
if (SHGetKnownFolderPath(&folder_id,0,NULL,&path) == S_OK) \
{ \
SetEnvironmentVariableW(evn_variable, path); \
CoTaskMemFree(path); \
} \
} while (0)
/* set user environment variables from user profile */
static void setup_session_user_vars()
{
/* retrieve and set env variables. */
HKEY reg_key = 0;
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;
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, &reg_key);
if (ret != ERROR_SUCCESS)
//error("Error retrieving user environment variables. RegOpenKeyExW returned %d", ret);
return;
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_MORE_DATA || required > data_chars * 2) {
if (data != NULL)
free(data);
data = xmalloc(required);
data_chars = required / 2;
i--;
continue;
}
else if (ret != ERROR_SUCCESS)
break;
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();
}
int b64_pton(char const *src, u_char *target, size_t targsize);
int
@ -1254,6 +1342,8 @@ wmain(int ac, wchar_t **av)
return -1;
}
setup_session_user_vars();
/* decode cmd_b64*/
if (cmd_b64) {
char *cmd_b64_utf8, *cmd_utf8;

View File

@ -39,10 +39,7 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) {
void
pty_change_window_size(int ptyfd, u_int row, u_int col,
u_int xpixel, u_int ypixel) {
COORD coord;
coord.X = col;
coord.Y = 9999;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
/* TODO - Need to implement*/
}

112
session.c
View File

@ -299,16 +299,7 @@ xauth_valid_string(const char *s)
* - Interactive shell/commands are executed using ssh-shellhost.exe
* - ssh-shellhost.exe implements server-side PTY for Windows
*/
#include <Shlobj.h>
#include <Sddl.h>
#define SET_USER_ENV(folder_id, evn_variable) do { \
if (SHGetKnownFolderPath(&folder_id,0,token,&path) == S_OK) \
{ \
SetEnvironmentVariableW(evn_variable, path); \
CoTaskMemFree(path); \
} \
} while (0)
#define UTF8_TO_UTF16_FATAL(o, i) do { \
if (o != NULL) free(o); \
@ -316,85 +307,6 @@ xauth_valid_string(const char *s)
fatal("%s, out of memory", __func__); \
} while (0)
static void setup_session_user_vars(Session* s) /* set user environment variables from user profile */
{
/* 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, &reg_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_MORE_DATA || required > data_chars * 2) {
if (data != NULL)
free(data);
data = xmalloc(required);
data_chars = required/2;
i--;
continue;
}
else if (ret != ERROR_SUCCESS) {
error("Error retrieving user environment variables. RegEnumValueW returned %d", ret);
break;
}
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];
@ -444,7 +356,6 @@ static void setup_session_vars(Session* s) {
SetEnvironmentVariableW(L"PROMPT", wbuf);
}
setup_session_user_vars(s);
free(pw_dir_w);
free(tmp);
}
@ -579,29 +490,6 @@ int do_exec_windows(Session *s, const char *command, int pty) {
if (!b)
fatal("ERROR. Cannot create process (%u).\n", GetLastError());
else if (pty) { /*attach to shell console */
FreeConsole();
if (!debug_flag)
ImpersonateLoggedOnUser(hToken);
Sleep(20);
while (AttachConsole(pi.dwProcessId) == FALSE) {
DWORD exit_code;
if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE)
break;
Sleep(100);
}
if (!debug_flag)
RevertToSelf();
{
/* TODO - check this - Create Process above is not respecting x# and y# chars, so we are doing this explicity on the
* attached console agein */
COORD coord;
coord.X = s->col;
coord.Y = 9999;;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
}
CloseHandle(pi.hThread);
s->pid = pi.dwProcessId;