mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-21 04:54:48 +02:00
Merge
This commit is contained in:
commit
716befae69
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh", "ssh.vcxproj", "{74E69D5E-A1EF-46EA-9173-19A412774104}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
|
Binary file not shown.
@ -46,7 +46,6 @@
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
||||
#endif
|
||||
|
||||
HANDLE hInputConsole = NULL;
|
||||
HANDLE hOutputConsole = NULL;
|
||||
DWORD dwSavedAttributes = 0;
|
||||
WORD wStartingAttributes = 0;
|
||||
|
@ -88,6 +88,8 @@ int w32_getaddrinfo(const char *, const char *,
|
||||
const struct addrinfo *, struct addrinfo **);
|
||||
FILE* w32_fopen_utf8(const char *, const char *);
|
||||
int w32_ftruncate(int fd, off_t length);
|
||||
char* w32_programdir();
|
||||
|
||||
|
||||
/* Shutdown constants */
|
||||
#define SHUT_WR SD_SEND
|
||||
|
@ -141,3 +141,27 @@ utf16_to_utf8(const wchar_t* utf16) {
|
||||
return NULL;
|
||||
return utf8;
|
||||
}
|
||||
|
||||
static char* s_programdir = NULL;
|
||||
char* w32_programdir() {
|
||||
if (s_programdir != NULL)
|
||||
return s_programdir;
|
||||
|
||||
if ((s_programdir = utf16_to_utf8(_wpgmptr)) == NULL)
|
||||
return NULL;
|
||||
|
||||
/* null terminate after directory path */
|
||||
{
|
||||
char* tail = s_programdir + strlen(s_programdir);
|
||||
while (tail > s_programdir && *tail != '\\' && *tail != '/')
|
||||
tail--;
|
||||
|
||||
if (tail > s_programdir)
|
||||
*tail = '\0';
|
||||
else
|
||||
*tail = '.'; /* current directory */
|
||||
}
|
||||
|
||||
return s_programdir;
|
||||
|
||||
}
|
@ -202,48 +202,6 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* given a access token, find the domain name of user account of the access token */
|
||||
int GetDomainFromToken ( HANDLE *hAccessToken, UCHAR *domain, DWORD dwSize)
|
||||
{
|
||||
UCHAR InfoBuffer[1000],username[200];
|
||||
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
|
||||
DWORD dwInfoBufferSize,dwAccountSize = 200, dwDomainSize = dwSize;
|
||||
SID_NAME_USE snu;
|
||||
|
||||
domain[0] = '\0' ;
|
||||
GetTokenInformation(*hAccessToken,TokenUser,InfoBuffer,
|
||||
1000, &dwInfoBufferSize);
|
||||
|
||||
LookupAccountSid(NULL, pTokenUser->User.Sid, (LPSTR)username,
|
||||
&dwAccountSize,(LPSTR)domain, &dwDomainSize, &snu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve user homedir from token, save it in static string
|
||||
* and return pointer to this string.
|
||||
*
|
||||
* userName - user's name (IN)
|
||||
* token - logon user's token (IN)
|
||||
*
|
||||
* RETURNS: pointer to static string with homedir or NULL if fails.
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
||||
/*
|
||||
* Temporary getpwuid implementaion of Windows. This should be replaced with getpw_currentuser
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO - this is moved from realpath.c in openbsdcompat. Review and finalize its position*/
|
||||
|
||||
|
@ -50,32 +50,29 @@
|
||||
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
|
||||
#endif
|
||||
|
||||
HINSTANCE hUserLibrary;
|
||||
HINSTANCE hKernelLibrary;
|
||||
typedef BOOL (WINAPI *__t_SetCurrentConsoleFontEx)(
|
||||
_In_ HANDLE hConsoleOutput,
|
||||
_In_ BOOL bMaximumWindow,
|
||||
_In_ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx
|
||||
);
|
||||
__t_SetCurrentConsoleFontEx __SetCurrentConsoleFontEx;
|
||||
|
||||
// kernel32.dll
|
||||
typedef BOOL(WINAPI * fSetCurrentConsoleFontEx)(
|
||||
_In_ HANDLE hConsoleOutput,
|
||||
_In_ BOOL bMaximumWindow,
|
||||
_In_ PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
||||
fSetCurrentConsoleFontEx fnSetCurrentConsoleFontEx = NULL;
|
||||
typedef BOOL (WINAPI *__t_UnhookWinEvent)(
|
||||
_In_ HWINEVENTHOOK hWinEventHook
|
||||
);
|
||||
__t_UnhookWinEvent __UnhookWinEvent;
|
||||
|
||||
// user32.dll
|
||||
typedef HWINEVENTHOOK (WINAPI * fSetWinEventHook)(
|
||||
_In_ UINT eventMin,
|
||||
_In_ UINT eventMax,
|
||||
_In_ HMODULE hmodWinEventProc,
|
||||
_In_ WINEVENTPROC lpfnWinEventProc,
|
||||
_In_ DWORD idProcess,
|
||||
_In_ DWORD idThread,
|
||||
_In_ UINT dwflags
|
||||
);
|
||||
fSetWinEventHook fnSetWinEventHook = NULL;
|
||||
typedef HWINEVENTHOOK (WINAPI *__t_SetWinEventHook)(
|
||||
_In_ UINT eventMin,
|
||||
_In_ UINT eventMax,
|
||||
_In_ HMODULE hmodWinEventProc,
|
||||
_In_ WINEVENTPROC lpfnWinEventProc,
|
||||
_In_ DWORD idProcess,
|
||||
_In_ DWORD idThread,
|
||||
_In_ UINT dwflags
|
||||
);
|
||||
__t_SetWinEventHook __SetWinEventHook;
|
||||
|
||||
typedef BOOL (WINAPI * fUnhookWinEvent)(
|
||||
_In_ HWINEVENTHOOK hWinEventHook
|
||||
);
|
||||
fUnhookWinEvent fnUnhookWinEvent = NULL;
|
||||
|
||||
typedef struct consoleEvent {
|
||||
DWORD event;
|
||||
@ -417,8 +414,7 @@ void SizeWindow(HANDLE hInput) {
|
||||
matchingFont.FontWeight = FW_NORMAL;
|
||||
wcscpy(matchingFont.FaceName, L"Consolas");
|
||||
|
||||
if(fnSetCurrentConsoleFontEx != NULL)
|
||||
bSuccess = fnSetCurrentConsoleFontEx(child_out, FALSE, &matchingFont);
|
||||
bSuccess = SetCurrentConsoleFontEx(child_out, FALSE, &matchingFont);
|
||||
|
||||
// This information is the live screen
|
||||
ZeroMemory(&consoleInfo, sizeof(consoleInfo));
|
||||
@ -855,7 +851,7 @@ DWORD WINAPI ProcessPipes(LPVOID p) {
|
||||
INPUT_RECORD ir;
|
||||
|
||||
if (buf[i] == 3) {/*Ctrl+C - Raise Ctrl+C*/
|
||||
GenerateConsoleCtrlEvent(CTRL_C_EVENT, childProcessId);
|
||||
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1076,7 +1072,7 @@ cleanup:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmain(int ac, wchar_t **av) {
|
||||
int start_with_pty(int ac, wchar_t **av) {
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
wchar_t cmd[MAX_PATH];
|
||||
@ -1086,22 +1082,7 @@ int wmain(int ac, wchar_t **av) {
|
||||
DWORD dwMode;
|
||||
DWORD dwStatus;
|
||||
HANDLE hEventHook = NULL;
|
||||
|
||||
HINSTANCE hUserLibrary;
|
||||
HINSTANCE hKernelLibrary;
|
||||
|
||||
hKernelLibrary = LoadLibrary(L"kernel32.dll");
|
||||
if (hKernelLibrary != NULL)
|
||||
{
|
||||
fnSetCurrentConsoleFontEx = (fSetCurrentConsoleFontEx)GetProcAddress(hKernelLibrary, "SetCurrentConsoleFontEx");
|
||||
}
|
||||
|
||||
hUserLibrary = LoadLibrary(L"user32.dll");
|
||||
if (hUserLibrary != NULL)
|
||||
{
|
||||
fnSetWinEventHook = (fSetWinEventHook)GetProcAddress(hUserLibrary, "SetWinEventHook");
|
||||
fnUnhookWinEvent = (fUnhookWinEvent)GetProcAddress(hUserLibrary, "UnhookWinEvent");
|
||||
}
|
||||
HMODULE hm_kernel32 = NULL, hm_user32 = NULL;
|
||||
|
||||
pipe_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
@ -1121,27 +1102,14 @@ int wmain(int ac, wchar_t **av) {
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
/* create job to hold all child processes */
|
||||
{
|
||||
/* TODO - this does not work as expected*/
|
||||
HANDLE job = CreateJobObject(NULL, NULL);
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info;
|
||||
memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)))
|
||||
return -1;
|
||||
CloseHandle(job);
|
||||
}
|
||||
|
||||
/* WM_APPEXIT */
|
||||
hostThreadId = GetCurrentThreadId();
|
||||
hostProcessId = GetCurrentProcessId();
|
||||
|
||||
InitializeCriticalSection(&criticalSection);
|
||||
|
||||
if(fnSetWinEventHook != NULL)
|
||||
hEventHook = SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL,
|
||||
ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
hEventHook = SetWinEventHook(EVENT_CONSOLE_CARET, EVENT_CONSOLE_LAYOUT, NULL,
|
||||
ConsoleEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
|
||||
|
||||
memset(&si, 0, sizeof(STARTUPINFO));
|
||||
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
|
||||
@ -1149,12 +1117,6 @@ int wmain(int ac, wchar_t **av) {
|
||||
// Copy our parent buffer sizes
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = 0;
|
||||
if (fnSetWinEventHook == NULL) {
|
||||
si.hStdInput = INVALID_HANDLE_VALUE;
|
||||
si.hStdOutput = pipe_out;
|
||||
si.hStdError = pipe_err;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
}
|
||||
|
||||
/* disable inheritance on pipe_in*/
|
||||
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
|
||||
@ -1175,14 +1137,19 @@ int wmain(int ac, wchar_t **av) {
|
||||
av++;
|
||||
}
|
||||
|
||||
SetConsoleCtrlHandler(NULL, FALSE);
|
||||
GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
|
||||
NULL, NULL, &si, &pi));
|
||||
childProcessId = pi.dwProcessId;
|
||||
|
||||
FreeConsole();
|
||||
Sleep(20);
|
||||
while (!AttachConsole(pi.dwProcessId))
|
||||
{
|
||||
Sleep(1000);
|
||||
DWORD exit_code;
|
||||
if (GetExitCodeProcess(pi.hProcess, &exit_code) && exit_code != STILL_ACTIVE)
|
||||
break;
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
/* monitor child exist */
|
||||
@ -1215,15 +1182,184 @@ cleanup:
|
||||
WaitForSingleObject(monitor_thread, INFINITE);
|
||||
if (ux_thread != INVALID_HANDLE_VALUE)
|
||||
TerminateThread(ux_thread, S_OK);
|
||||
if (hEventHook && fnUnhookWinEvent != NULL)
|
||||
fnUnhookWinEvent(hEventHook);
|
||||
|
||||
if (hKernelLibrary != NULL)
|
||||
FreeLibrary(hKernelLibrary);
|
||||
if (hUserLibrary != NULL)
|
||||
FreeLibrary(hUserLibrary);
|
||||
if (hEventHook)
|
||||
UnhookWinEvent(hEventHook);
|
||||
|
||||
FreeConsole();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLE child_pipe_read;
|
||||
HANDLE child_pipe_write;
|
||||
DWORD WINAPI MonitorChild_nopty(
|
||||
_In_ LPVOID lpParameter
|
||||
) {
|
||||
WaitForSingleObject(child, INFINITE);
|
||||
CloseHandle(pipe_in);
|
||||
//printf("XXXX CHILD PROCESS DEAD XXXXX");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start_withno_pty(int ac, wchar_t **av) {
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
wchar_t cmd[MAX_PATH];
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
BOOL ret;
|
||||
|
||||
pipe_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
pipe_err = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
/* copy pipe handles passed through std io*/
|
||||
if ((pipe_in == INVALID_HANDLE_VALUE)
|
||||
|| (pipe_out == INVALID_HANDLE_VALUE)
|
||||
|| (pipe_err == INVALID_HANDLE_VALUE))
|
||||
return -1;
|
||||
|
||||
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = TRUE;
|
||||
if (!CreatePipe(&child_pipe_read, &child_pipe_write, &sa, 128))
|
||||
return -1;
|
||||
|
||||
memset(&si, 0, sizeof(STARTUPINFO));
|
||||
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = child_pipe_read;
|
||||
si.hStdOutput = pipe_out;
|
||||
si.hStdError = pipe_err;
|
||||
|
||||
/* disable inheritance on child_pipe_write and pipe_in*/
|
||||
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
|
||||
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(child_pipe_write, HANDLE_FLAG_INHERIT, 0));
|
||||
|
||||
/*TODO - pick this up from system32*/
|
||||
cmd[0] = L'\0';
|
||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L"cmd.exe"));
|
||||
ac -= 2;
|
||||
av += 2;
|
||||
if (ac)
|
||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" /c"));
|
||||
while (ac) {
|
||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" "));
|
||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, *av));
|
||||
ac--;
|
||||
av++;
|
||||
}
|
||||
|
||||
GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi));
|
||||
|
||||
/* close unwanted handles*/
|
||||
CloseHandle(child_pipe_read);
|
||||
child_pipe_read = INVALID_HANDLE_VALUE;
|
||||
|
||||
child = pi.hProcess;
|
||||
/* monitor child exist */
|
||||
monitor_thread = CreateThread(NULL, 0, MonitorChild_nopty, NULL, 0, NULL);
|
||||
if (monitor_thread == INVALID_HANDLE_VALUE)
|
||||
goto cleanup;
|
||||
|
||||
/* disable Ctrl+C hander in this process*/
|
||||
SetConsoleCtrlHandler(NULL, TRUE);
|
||||
|
||||
/* process data from pipe_in and route appropriately */
|
||||
while (1) {
|
||||
char buf[128];
|
||||
DWORD rd = 0, wr = 0, i = 0;
|
||||
GOTO_CLEANUP_ON_FALSE(ReadFile(pipe_in, buf, 128, &rd, NULL));
|
||||
|
||||
while (i < rd) {
|
||||
|
||||
/* skip arrow keys */
|
||||
if ((rd - i >= 3) && (buf[i] == '\033') && (buf[i + 1] == '[')
|
||||
&& (buf[i + 2] >= 'A') && (buf[i + 2] <= 'D')) {
|
||||
i += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip tab */
|
||||
if (buf[i] == '\t') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ctrl +C
|
||||
if (buf[i] == '\003') {
|
||||
GOTO_CLEANUP_ON_FALSE(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0));
|
||||
in_cmd_len = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// for backspace, we need to send space and another backspace for visual erase
|
||||
if (buf[i] == '\b') {
|
||||
if (in_cmd_len > 0) {
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, "\b \b", 3, &wr, NULL));
|
||||
in_cmd_len--;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//for CR and LF
|
||||
if ((buf[i] == '\r') || (buf[i] == '\n')) {
|
||||
|
||||
/* TODO - do a much accurate mapping */
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
|
||||
if ((buf[i] == '\r') && ((i == rd - 1) || (buf[i + 1] != '\n'))) {
|
||||
buf[i] = '\n';
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
|
||||
}
|
||||
in_cmd[in_cmd_len] = buf[i];
|
||||
in_cmd_len++;
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL));
|
||||
in_cmd_len = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(pipe_out, buf + i, 1, &wr, NULL));
|
||||
in_cmd[in_cmd_len] = buf[i];
|
||||
in_cmd_len++;
|
||||
if (in_cmd_len == MAX_CMD_LEN - 1) {
|
||||
GOTO_CLEANUP_ON_FALSE(WriteFile(child_pipe_write, in_cmd, in_cmd_len, &wr, NULL));
|
||||
in_cmd_len = 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
if (child != INVALID_HANDLE_VALUE)
|
||||
TerminateProcess(child, 0);
|
||||
if (monitor_thread != INVALID_HANDLE_VALUE)
|
||||
WaitForSingleObject(monitor_thread, INFINITE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmain(int ac, wchar_t **av) {
|
||||
|
||||
|
||||
/* create job to hold all child processes */
|
||||
{
|
||||
/* TODO - this does not work as expected*/
|
||||
HANDLE job = CreateJobObject(NULL, NULL);
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info;
|
||||
memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)))
|
||||
return -1;
|
||||
CloseHandle(job);
|
||||
}
|
||||
|
||||
if ((ac == 1) || wcscmp(av[1], L"-nopty"))
|
||||
return start_with_pty(ac, av);
|
||||
else
|
||||
return start_withno_pty(ac, av);
|
||||
}
|
@ -90,8 +90,8 @@ BOOL WINAPI ctrl_c_handler(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int wmain(int argc, wchar_t **argv) {
|
||||
|
||||
w32posix_initialize();
|
||||
load_config();
|
||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||
@ -108,7 +108,7 @@ int main(int argc, char **argv) {
|
||||
if (argc == 2) {
|
||||
/*agent process is likely a spawned child*/
|
||||
char* h = 0;
|
||||
h += atoi(*(argv + 1));
|
||||
h += _wtoi(*(argv + 1));
|
||||
if (h != 0) {
|
||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||
agent_start(FALSE, TRUE, h);
|
||||
@ -146,7 +146,7 @@ int scm_start_service(DWORD num, LPWSTR* args) {
|
||||
ZeroMemory(&service_status, sizeof(service_status));
|
||||
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300);
|
||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||
log_init("ssh-agent", config_log_level(), 1, 0);
|
||||
agent_start(FALSE, FALSE, 0);
|
||||
return 0;
|
||||
|
@ -126,8 +126,10 @@ w32posix_initialize() {
|
||||
|| (socketio_initialize() != 0))
|
||||
DebugBreak();
|
||||
main_thread = OpenThread(THREAD_SET_CONTEXT, FALSE, GetCurrentThreadId());
|
||||
if ((main_thread == NULL) || (sw_initialize() != 0))
|
||||
DebugBreak();
|
||||
if ((main_thread == NULL) || (sw_initialize() != 0) || w32_programdir() == NULL) {
|
||||
DebugBreak();
|
||||
fatal("failed to initialize w32posix wrapper");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
4
scp.c
4
scp.c
@ -2230,6 +2230,10 @@ int start_process_io(char *exename, char **argv, char **envv,
|
||||
|
||||
ctr = 0;
|
||||
cmdbuf[0] = '\0';
|
||||
if (argv[0][0] != '\0' && argv[0][1] != ':') {
|
||||
strcat(cmdbuf, w32_programdir());
|
||||
strcat(cmdbuf, "\\");
|
||||
}
|
||||
while (argv[ctr]) {
|
||||
strcat_s(cmdbuf, sizeof(cmdbuf), argv[ctr]);
|
||||
strcat_s(cmdbuf, sizeof(cmdbuf), " ");
|
||||
|
811
session.c
811
session.c
@ -99,6 +99,7 @@
|
||||
#include "sftp.h"
|
||||
#ifdef WIN32_FIXME
|
||||
#include "console.h"
|
||||
#include <Sddl.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32_FIXME
|
||||
@ -112,9 +113,6 @@ FIXME: GFPZR: Function stat() may be undeclared.
|
||||
#include <Userenv.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#ifdef WIN32_PRAGMA_REMCON
|
||||
#include <shlwapi.h>
|
||||
#endif
|
||||
extern char HomeDirLsaW[MAX_PATH];
|
||||
|
||||
#endif
|
||||
@ -491,14 +489,383 @@ do_authenticated1(Authctxt *authctxt)
|
||||
}
|
||||
}
|
||||
|
||||
// PRAGMA:TODO
|
||||
#ifndef WIN32_FIXME
|
||||
#define USE_PIPES 1
|
||||
#endif
|
||||
#ifdef WINDOWS
|
||||
|
||||
#ifdef WIN32_FIXME
|
||||
extern int debug_flag;
|
||||
#endif
|
||||
#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)
|
||||
|
||||
void setup_session_vars(Session* s)
|
||||
{
|
||||
wchar_t* pw_dir_w;
|
||||
wchar_t* tmp;
|
||||
char buf[128];
|
||||
char* laddr;
|
||||
|
||||
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");
|
||||
SetEnvironmentVariableW(L"USERNAME", tmp);
|
||||
free(tmp);
|
||||
|
||||
if (s->display)
|
||||
SetEnvironmentVariableA("DISPLAY", s->display);
|
||||
|
||||
|
||||
SetEnvironmentVariableW(L"HOMEPATH", pw_dir_w);
|
||||
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_w);
|
||||
|
||||
if (pw_dir_w[1] == L':') {
|
||||
wchar_t wc = pw_dir_w[2];
|
||||
pw_dir_w[2] = L'\0';
|
||||
SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_w);
|
||||
pw_dir_w[2] = wc;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %d",
|
||||
get_remote_ipaddr(), get_remote_port(), get_local_port());
|
||||
|
||||
SetEnvironmentVariableA("SSH_CLIENT", buf);
|
||||
|
||||
laddr = get_local_ipaddr(packet_get_connection_in());
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
|
||||
get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
|
||||
|
||||
free(laddr);
|
||||
|
||||
SetEnvironmentVariableA("SSH_CONNECTION", buf);
|
||||
|
||||
if (original_command)
|
||||
SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command);
|
||||
|
||||
|
||||
if ((s->term) && (s->term[0]))
|
||||
SetEnvironmentVariable("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, 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. */
|
||||
/* TODO - Get away with fixed limits and dynamically allocate required memory, cleanup this logic*/
|
||||
#define MAX_VALUE_LEN 1000
|
||||
#define MAX_DATA_LEN 2000
|
||||
#define MAX_EXPANDED_DATA_LEN 5000
|
||||
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, &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();
|
||||
}
|
||||
}
|
||||
|
||||
free(pw_dir_w);
|
||||
}
|
||||
|
||||
int do_exec_windows(Session *s, const char *command, int pty) {
|
||||
int pipein[2], pipeout[2], pipeerr[2], r;
|
||||
char *exec_command = NULL, *progdir = w32_programdir();
|
||||
wchar_t *exec_command_w = NULL, *pw_dir_w;
|
||||
|
||||
if (s->is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR)
|
||||
{
|
||||
error("sub system not supported, exiting\n");
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Create three pipes for stdin, stdout and stderr */
|
||||
if (pipe(pipein) == -1 || pipe(pipeout) == -1 || pipe(pipeerr) == -1)
|
||||
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");
|
||||
|
||||
|
||||
set_nonblock(pipein[0]);
|
||||
set_nonblock(pipein[1]);
|
||||
set_nonblock(pipeout[0]);
|
||||
set_nonblock(pipeout[1]);
|
||||
set_nonblock(pipeerr[0]);
|
||||
set_nonblock(pipeerr[1]);
|
||||
|
||||
fcntl(pipein[1], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pipeout[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(pipeerr[0], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
/* prepare exec - path used with CreateProcess() */
|
||||
if (s->is_subsystem || (command && memcmp(command, "scp", 3) == 0)) {
|
||||
/* relative or absolute */
|
||||
if (command == NULL || command[0] == '\0')
|
||||
fatal("expecting command for a subsystem");
|
||||
|
||||
if (command[1] == ':') /* absolute */
|
||||
exec_command = xstrdup(command);
|
||||
else {/*relative*/
|
||||
exec_command = malloc(strlen(progdir) + 1 + strlen(command));
|
||||
if (exec_command == NULL)
|
||||
fatal("%s, out of memory");
|
||||
memcpy(exec_command, progdir, strlen(progdir));
|
||||
exec_command[strlen(progdir)] = '\\';
|
||||
memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1);
|
||||
}
|
||||
} else {
|
||||
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");
|
||||
c = exec_command;
|
||||
memcpy(c, progdir, strlen(progdir));
|
||||
c += strlen(progdir);
|
||||
*c++ = '\\';
|
||||
memcpy(c, shell_host, strlen(shell_host));
|
||||
c += strlen(shell_host);
|
||||
if (command) {
|
||||
memcpy(c, command, strlen(command));
|
||||
c += strlen(command);
|
||||
}
|
||||
*c = '\0';
|
||||
}
|
||||
|
||||
/* setup Environment varibles */
|
||||
setup_session_vars(s);
|
||||
|
||||
extern int debug_flag;
|
||||
|
||||
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)sfd_to_handle(pipein[0]);
|
||||
si.hStdOutput = (HANDLE)sfd_to_handle(pipeout[1]);
|
||||
si.hStdError = (HANDLE)sfd_to_handle(pipeerr[1]);
|
||||
si.lpDesktop = NULL;
|
||||
|
||||
hToken = s->authctxt->methoddata;
|
||||
|
||||
debug("Executing command: %s", exec_command);
|
||||
|
||||
/* Create the child process */
|
||||
|
||||
exec_command_w = utf8_to_utf16(exec_command);
|
||||
|
||||
if (debug_flag)
|
||||
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
|
||||
DETACHED_PROCESS, NULL, pw_dir_w,
|
||||
&si, &pi);
|
||||
else
|
||||
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());
|
||||
|
||||
CloseHandle(hToken);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
s->pid = pi.dwProcessId;
|
||||
sw_add_child(pi.hProcess, pi.dwProcessId);
|
||||
|
||||
/*
|
||||
* Set interactive/non-interactive mode.
|
||||
*/
|
||||
|
||||
packet_set_interactive(s->display != NULL, options.ip_qos_interactive,
|
||||
options.ip_qos_bulk);
|
||||
|
||||
/*
|
||||
* We are the parent. Close the child sides of the socket pairs.
|
||||
*/
|
||||
|
||||
close(pipein[0]);
|
||||
close(pipeout[1]);
|
||||
close(pipeerr[1]);
|
||||
|
||||
|
||||
/*
|
||||
* Close child thread handles as we do not need it. Process handle we keep so that we can know if it has died o not
|
||||
*/
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
// CloseHandle(pi.hProcess);
|
||||
|
||||
/*
|
||||
* Clear loginmsg, since it's the child's responsibility to display
|
||||
* it to the user, otherwise multiple sessions may accumulate
|
||||
* multiple copies of the login messages.
|
||||
*/
|
||||
|
||||
buffer_clear(&loginmsg);
|
||||
|
||||
/*
|
||||
* Enter the interactive session. Note: server_loop must be able to
|
||||
* handle the case that fdin and fdout are the same.
|
||||
*/
|
||||
|
||||
if (compat20)
|
||||
{
|
||||
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
|
||||
}
|
||||
else
|
||||
{
|
||||
server_loop(pi.hProcess, pipein[1], pipeout[0], pipeerr[0]);
|
||||
|
||||
/*
|
||||
* server_loop has closed inout[0] and err[0].
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
do_exec_no_pty(Session *s, const char *command) {
|
||||
return do_exec_windows(s, command, 0);
|
||||
}
|
||||
|
||||
int
|
||||
do_exec_pty(Session *s, const char *command) {
|
||||
return do_exec_windows(s, command, 1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* This is called to fork and execute a command when we have no tty. This
|
||||
@ -508,408 +875,6 @@ extern int debug_flag;
|
||||
int
|
||||
do_exec_no_pty(Session *s, const char *command)
|
||||
{
|
||||
#ifdef WIN32_FIXME
|
||||
wchar_t* pw_dir_utf16 = utf8_to_utf16(s->pw->pw_dir);
|
||||
|
||||
/*
|
||||
* Win32 code.
|
||||
*/
|
||||
|
||||
if (s -> is_subsystem == SUBSYSTEM_INT_SFTP_ERROR)
|
||||
{
|
||||
printf("This service allows sftp connections only.\n");
|
||||
fflush(NULL);
|
||||
exit(1);
|
||||
}
|
||||
else if (s -> is_subsystem == SUBSYSTEM_INT_SFTP)
|
||||
{
|
||||
u_int i;
|
||||
for (i = 0; i < options.num_subsystems; i++)
|
||||
{
|
||||
if (strcmp("sftp", options.subsystem_name[i]) == 0)
|
||||
{
|
||||
command = options.subsystem_args[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOW si;
|
||||
|
||||
int pipein[2];
|
||||
int pipeout[2];
|
||||
int pipeerr[2];
|
||||
|
||||
BOOL b;
|
||||
|
||||
HANDLE hToken = INVALID_HANDLE_VALUE;
|
||||
|
||||
int do_xauth;
|
||||
|
||||
FILE *f = NULL;
|
||||
|
||||
char cmd[1024];
|
||||
char *exec_command;
|
||||
char *laddr;
|
||||
char buf[256];
|
||||
#ifdef WIN32_PRAGMA_REMCON
|
||||
char exec_command_str[512];
|
||||
#endif
|
||||
|
||||
if (!command)
|
||||
{
|
||||
#ifndef WIN32_PRAGMA_REMCON
|
||||
exec_command = s->pw->pw_shell;
|
||||
#else
|
||||
if ( PathFileExists("\\program files\\pragma\\shared files\\cmdserver.exe") )
|
||||
snprintf(exec_command_str, sizeof(exec_command_str),
|
||||
"\\program files\\pragma\\shared files\\cmdserver.exe SSHD %d %d", s->row, s->col );
|
||||
else {
|
||||
// find base path of our executable
|
||||
char basepath[MAX_PATH];
|
||||
strcpy_s(basepath, MAX_PATH, __progname);
|
||||
PathRemoveFileSpec(basepath); // get the full dir part of the name
|
||||
snprintf(exec_command_str, sizeof(exec_command_str),
|
||||
"%s\\cmdserver.exe SSHD %d %d", basepath,s->row, s->col);
|
||||
}
|
||||
exec_command = exec_command_str;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
exec_command = command;
|
||||
}
|
||||
|
||||
do_xauth = s -> display != NULL && s -> auth_proto != NULL && s -> auth_data != NULL;
|
||||
|
||||
/*
|
||||
* Create three socket pairs for stdin, stdout and stderr
|
||||
*/
|
||||
pipe(pipein);
|
||||
pipe(pipeout);
|
||||
pipe(pipeerr);
|
||||
|
||||
int retcode = -1;
|
||||
if ( (!s -> is_subsystem) && (s ->ttyfd != -1))
|
||||
{
|
||||
extern HANDLE hInputConsole;
|
||||
extern HANDLE hOutputConsole ;
|
||||
hInputConsole = GetConsoleInputHandle();
|
||||
hOutputConsole = GetConsoleOutputHandle();
|
||||
ConSetScreenSize( s->col, s->row );
|
||||
s->ptyfd = pipein[1]; // hConsole; // the pty is the Windows console output handle in our Win32 port
|
||||
}
|
||||
|
||||
debug3("sockin[0]: %d sockin[1]: %d", pipein[0], pipein[1]);
|
||||
debug3("sockout[0]: %d sockout[1]: %d", pipeout[0], pipeout[1]);
|
||||
debug3("sockerr[0]: %d sockerr[1]: %d", pipeerr[0], pipeerr[1]);
|
||||
|
||||
|
||||
SetHandleInformation(sfd_to_handle(pipein[1]), HANDLE_FLAG_INHERIT, 0);
|
||||
SetHandleInformation(sfd_to_handle(pipeout[0]), HANDLE_FLAG_INHERIT, 0);
|
||||
SetHandleInformation(sfd_to_handle(pipeerr[0]), HANDLE_FLAG_INHERIT, 0);
|
||||
|
||||
/*
|
||||
* 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) sfd_to_handle(pipein[0]);
|
||||
si.hStdOutput = (HANDLE) sfd_to_handle(pipeout[1]);
|
||||
si.hStdError = (HANDLE) sfd_to_handle(pipeerr[1]);
|
||||
si.lpDesktop = NULL;
|
||||
|
||||
SetEnvironmentVariable("USER", s->pw->pw_name);
|
||||
SetEnvironmentVariable("USERNAME", s->pw->pw_name);
|
||||
SetEnvironmentVariable("LOGNAME", s->pw->pw_name);
|
||||
|
||||
/*
|
||||
* Setup xauth if needed
|
||||
*/
|
||||
|
||||
if (do_xauth && options.xauth_location != NULL)
|
||||
{
|
||||
/*
|
||||
* Add authority data to .Xauthority if appropriate.
|
||||
*/
|
||||
|
||||
if (debug_flag)
|
||||
{
|
||||
fprintf(stderr, "Running %.500s remove %.100s\n",
|
||||
options.xauth_location, s->auth_display);
|
||||
|
||||
fprintf(stderr, "%.500s add %.100s %.100s %.100s\n", options.xauth_location,
|
||||
s -> auth_display, s -> auth_proto, s -> auth_data);
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof cmd, "%s -q -", options.xauth_location);
|
||||
|
||||
f = _popen(cmd, "w");
|
||||
|
||||
if (f)
|
||||
{
|
||||
fprintf(f, "remove %s\n", s -> auth_display);
|
||||
|
||||
fprintf(f, "add %s %s %s\n", s -> auth_display, s -> auth_proto, s -> auth_data);
|
||||
|
||||
_pclose(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Could not run %s\n", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
set_nonblock(pipein[0]);
|
||||
set_nonblock(pipein[1]);
|
||||
set_nonblock(pipeout[0]);
|
||||
set_nonblock(pipeout[1]);
|
||||
set_nonblock(pipeerr[0]);
|
||||
set_nonblock(pipeerr[1]);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we get this far, the user has already been authenticated
|
||||
* We should either have a user token in authctxt -> methoddata
|
||||
* (e.g. for password auth) or we need to create a more restrictive
|
||||
* token using CreateUserToken for non-password auth mechanisms.
|
||||
*/
|
||||
|
||||
hToken = s -> authctxt -> methoddata;
|
||||
|
||||
|
||||
if (s -> display)
|
||||
{
|
||||
SetEnvironmentVariable("DISPLAY", s -> display);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change to users home directory
|
||||
* TODO - pw_dir is utf-8, convert it to utf-16 and call _wchdir
|
||||
* also change subsequent calls to SetEnvironmentVariable
|
||||
*/
|
||||
|
||||
_wchdir(pw_dir_utf16);
|
||||
|
||||
SetEnvironmentVariableW(L"HOME", pw_dir_utf16);
|
||||
SetEnvironmentVariableW(L"USERPROFILE", pw_dir_utf16);
|
||||
|
||||
wchar_t *wstr, wchr;
|
||||
wstr = wcschr(pw_dir_utf16, L':');
|
||||
if (wstr) {
|
||||
wchr = *(wstr + 1);
|
||||
*(wstr + 1) = '\0';
|
||||
SetEnvironmentVariableW(L"HOMEDRIVE", pw_dir_utf16);
|
||||
*(wstr + 1) = wchr;
|
||||
SetEnvironmentVariableW(L"HOMEPATH", (wstr+1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// find the server name of the domain controller which created this token
|
||||
GetDomainFromToken ( &hToken, buf, sizeof(buf));
|
||||
if (buf[0])
|
||||
SetEnvironmentVariable("USERDOMAIN", buf );
|
||||
|
||||
/*
|
||||
* Set SSH_CLIENT variable.
|
||||
*/
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %d",
|
||||
get_remote_ipaddr(), get_remote_port(), get_local_port());
|
||||
|
||||
SetEnvironmentVariableA("SSH_CLIENT", buf);
|
||||
|
||||
/*
|
||||
* Set SSH_CONNECTION variable.
|
||||
*/
|
||||
|
||||
laddr = get_local_ipaddr(packet_get_connection_in());
|
||||
|
||||
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
|
||||
get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
|
||||
|
||||
free(laddr);
|
||||
|
||||
SetEnvironmentVariableA("SSH_CONNECTION", buf);
|
||||
|
||||
if (original_command)
|
||||
SetEnvironmentVariableA("SSH_ORIGINAL_COMMAND", original_command);
|
||||
|
||||
|
||||
// set better prompt for Windows cmd shell
|
||||
if (!s -> is_subsystem) {
|
||||
snprintf(buf,sizeof buf, "%s@%s $P$G", s->pw->pw_name, getenv("COMPUTERNAME"));
|
||||
SetEnvironmentVariableA("PROMPT", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current user's name (associated with sshd thread).
|
||||
*/
|
||||
|
||||
debug3("Home path before CreateProcessAsUser [%ls]", s -> pw -> pw_dir);
|
||||
|
||||
DWORD size = 256;
|
||||
|
||||
char name[256];
|
||||
|
||||
GetUserName(name, &size);
|
||||
|
||||
if ( (s->term) && (s->term[0]) )
|
||||
SetEnvironmentVariable("TERM", s->term);
|
||||
/*
|
||||
* Create new process as other user using access token object.
|
||||
*/
|
||||
|
||||
debug("Executing command: %s", exec_command);
|
||||
|
||||
/*
|
||||
* Create the child process
|
||||
*/
|
||||
|
||||
wchar_t exec_command_w[MAX_PATH];
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, exec_command, -1, exec_command_w, MAX_PATH);
|
||||
DWORD dwStartupFlags = DETACHED_PROCESS;// CREATE_SUSPENDED; // 0
|
||||
|
||||
SetConsoleCtrlHandler(NULL, FALSE);
|
||||
|
||||
wchar_t* p_dir = utf8_to_utf16(s->pw->pw_dir);
|
||||
if (debug_flag)
|
||||
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
|
||||
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, pw_dir_utf16,
|
||||
&si, &pi);
|
||||
else
|
||||
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
|
||||
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, pw_dir_utf16,
|
||||
&si, &pi);
|
||||
|
||||
if (!b)
|
||||
{
|
||||
debug("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||
|
||||
CloseHandle(hToken);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
else if (s->ttyfd != -1) { /*attach to shell console */
|
||||
FreeConsole();
|
||||
if (!debug_flag)
|
||||
ImpersonateLoggedOnUser(hToken);
|
||||
while (AttachConsole(pi.dwProcessId) == FALSE) {
|
||||
Sleep(200);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save token used for create child process. We'll need it on cleanup
|
||||
* to clean up DACL of Winsta0.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Log the process handle (fake it as the pid) for termination lookups
|
||||
*/
|
||||
|
||||
s -> pid = pi.dwProcessId;
|
||||
sw_add_child(pi.hProcess, pi.dwProcessId);
|
||||
|
||||
// Add the child process created to select mux so that during our select data call we know if the process has exited
|
||||
/* TODO - fix thi s*/
|
||||
//int WSHELPAddChildToWatch ( HANDLE processtowatch);
|
||||
//WSHELPAddChildToWatch ( pi.hProcess);
|
||||
|
||||
/*
|
||||
* Set interactive/non-interactive mode.
|
||||
*/
|
||||
|
||||
packet_set_interactive(s -> display != NULL, options.ip_qos_interactive,
|
||||
options.ip_qos_bulk);
|
||||
|
||||
/*
|
||||
* We are the parent. Close the child sides of the socket pairs.
|
||||
*/
|
||||
|
||||
close(pipein[0]);
|
||||
close(pipeout[1]);
|
||||
close(pipeerr[1]);
|
||||
|
||||
ResumeThread ( pi.hThread ); /* now let cmd shell main thread be active s we have closed all i/o file handle that cmd will use */
|
||||
SetConsoleCtrlHandler(NULL, TRUE);
|
||||
|
||||
/*
|
||||
* Close child thread handles as we do not need it. Process handle we keep so that we can know if it has died o not
|
||||
*/
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
// CloseHandle(pi.hProcess);
|
||||
|
||||
/*
|
||||
* Clear loginmsg, since it's the child's responsibility to display
|
||||
* it to the user, otherwise multiple sessions may accumulate
|
||||
* multiple copies of the login messages.
|
||||
*/
|
||||
|
||||
buffer_clear(&loginmsg);
|
||||
|
||||
/*
|
||||
* Enter the interactive session. Note: server_loop must be able to
|
||||
* handle the case that fdin and fdout are the same.
|
||||
*/
|
||||
|
||||
if (compat20)
|
||||
{
|
||||
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
|
||||
}
|
||||
else
|
||||
{
|
||||
server_loop(pi.hProcess, pipein[1], pipeout[0], pipeerr[0]);
|
||||
|
||||
/*
|
||||
* server_loop has closed inout[0] and err[0].
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Original OpenSSH code.
|
||||
*/
|
||||
pid_t pid;
|
||||
|
||||
#ifdef USE_PIPES
|
||||
@ -1094,7 +1059,7 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
#endif /* else WIN32_FIXME */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1106,11 +1071,6 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
int
|
||||
do_exec_pty(Session *s, const char *command)
|
||||
{
|
||||
#ifndef WIN32_FIXME
|
||||
|
||||
/*
|
||||
* Original OpenSSH code.
|
||||
*/
|
||||
int fdout, ptyfd, ttyfd, ptymaster;
|
||||
pid_t pid;
|
||||
|
||||
@ -1222,17 +1182,8 @@ do_exec_pty(Session *s, const char *command)
|
||||
/* server_loop _has_ closed ptyfd and fdout. */
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
|
||||
/*
|
||||
* Win32 code.
|
||||
*/
|
||||
|
||||
//return 0;
|
||||
return do_exec_no_pty(s, command);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LOGIN_NEEDS_UTMPX
|
||||
static void
|
||||
@ -2616,9 +2567,7 @@ session_pty_req(Session *s)
|
||||
/* for SSH1 the tty modes length is not given */
|
||||
if (!compat20)
|
||||
n_bytes = packet_remaining();
|
||||
#ifndef WIN32_PRAGMA_REMCON
|
||||
tty_parse_modes(s->ttyfd, &n_bytes);
|
||||
#endif
|
||||
|
||||
if (!use_privsep)
|
||||
pty_setowner(s->pw, s->tty);
|
||||
@ -2626,9 +2575,7 @@ session_pty_req(Session *s)
|
||||
/* Set window size from the packet. */
|
||||
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
|
||||
|
||||
#ifndef WIN32_PRAGMA_REMCON
|
||||
packet_check_eom();
|
||||
#endif
|
||||
session_proctitle(s);
|
||||
return 1;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#ifdef WIN32_VS
|
||||
#include "win32_dirent.h"
|
||||
#include <Shlwapi.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
5
sftp.c
5
sftp.c
@ -2396,6 +2396,11 @@ connect_to_server(char *path, char **args, int *in, int *out)
|
||||
STARTUPINFO si = { 0 };
|
||||
|
||||
debug3("Generating ssh-client command...");
|
||||
fullCmd[0] = '\0';
|
||||
if (path[0] != '\0' && path[1] != ':') {
|
||||
strncat(fullCmd, w32_programdir(), MAX_PATH);
|
||||
strncat(fullCmd, "\\", MAX_PATH);
|
||||
}
|
||||
strncat(fullCmd, path, MAX_PATH);
|
||||
for (i = 1; args[i]; i++) {
|
||||
strncat(fullCmd, " ", MAX_PATH);
|
||||
|
2
ssh.c
2
ssh.c
@ -118,7 +118,6 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
char dotsshdir[MAX_PATH];
|
||||
extern HANDLE hInputConsole;
|
||||
|
||||
#endif /* WIN32_FIXME */
|
||||
|
||||
@ -1393,7 +1392,6 @@ main(int ac, char **av)
|
||||
if (tty_flag) {
|
||||
//AllocConsole();
|
||||
ConInputInitParams(); // init the Console input side with global parameters
|
||||
hInputConsole = GetStdHandle(STD_INPUT_HANDLE);
|
||||
ConInit(STD_OUTPUT_HANDLE, TRUE); //init the output console surface for us to write
|
||||
ConClearScreen();
|
||||
}
|
||||
|
33
sshd.c
33
sshd.c
@ -281,25 +281,16 @@ static void do_ssh2_kex(void);
|
||||
{
|
||||
int exitCode = -1;
|
||||
|
||||
//
|
||||
// Windows.
|
||||
//
|
||||
|
||||
#ifdef WIN32_FIXME
|
||||
|
||||
if (GetModuleFileName(NULL, path, pathSize)){
|
||||
int i;
|
||||
int lastSlashPos = 0;
|
||||
|
||||
for (i = 0; path[i]; i++) {
|
||||
if (path[i] == '/' || path[i] == '\\') {
|
||||
lastSlashPos = i;
|
||||
}
|
||||
}
|
||||
|
||||
path[lastSlashPos] = 0;
|
||||
/* Windows */
|
||||
#ifdef WINDOWS
|
||||
|
||||
char* dir = w32_programdir();
|
||||
if (strnlen(dir, pathSize) == pathSize)
|
||||
error("program directory path size exceeded provided pathSize %d", pathSize);
|
||||
else {
|
||||
memcpy(path, dir, strnlen(dir, pathSize) + 1);
|
||||
exitCode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1972,11 +1963,7 @@ main(int ac, char **av)
|
||||
|
||||
struct stat s;
|
||||
|
||||
#ifdef WIN32_FIXME
|
||||
#define PATH_SIZE MAX_PATH
|
||||
#else
|
||||
#define PATH_SIZE PATH_MAX
|
||||
#endif
|
||||
#define PATH_SIZE PATH_MAX
|
||||
|
||||
char basePath[PATH_SIZE] = {0};
|
||||
char path[PATH_SIZE] = {0};
|
||||
|
Loading…
x
Reference in New Issue
Block a user