mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
ConPTY changes and support for auto-updating known_hosts;
- Logic to support conpty (currently disabled until validation is complete) - fdopen() and fchmod() support for file handles - support for auto updating known_hosts via ssh and ssh-keygen - Support for dynamic Windows-size changes with PTY - Changes to support OneCore SDK - Test cases
This commit is contained in:
parent
366964344f
commit
84e87be8ae
@ -18,7 +18,7 @@ if (-not $gitBinFullPath)
|
|||||||
function Get-RepoFork
|
function Get-RepoFork
|
||||||
{
|
{
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param([string]$AccountURL, [string]$RepoFork, [string]$repoLocalPath, [string]$BranchName)
|
param([string]$AccountURL="https://github.com/powershell", [string]$RepoFork, [string]$repoLocalPath, [string]$BranchName)
|
||||||
if (Test-Path -Path $repoLocalPath -PathType Container)
|
if (Test-Path -Path $repoLocalPath -PathType Container)
|
||||||
{
|
{
|
||||||
Remove-Item -Path $repoLocalPath -Recurse -Force
|
Remove-Item -Path $repoLocalPath -Recurse -Force
|
||||||
|
@ -304,6 +304,7 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\spawn.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\spawn.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_wait.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_wait.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32_pty.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
||||||
|
@ -40,11 +40,14 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "ansiprsr.h"
|
#include "ansiprsr.h"
|
||||||
|
#include "misc_internal.h"
|
||||||
|
|
||||||
HANDLE hOutputConsole = NULL;
|
HANDLE hOutputConsole = NULL;
|
||||||
DWORD stdin_dwSavedAttributes = 0;
|
DWORD stdin_dwSavedAttributes = 0;
|
||||||
DWORD stdout_dwSavedAttributes = 0;
|
DWORD stdout_dwSavedAttributes = 0;
|
||||||
WORD wStartingAttributes = 0;
|
WORD wStartingAttributes = 0;
|
||||||
|
unsigned int console_out_cp_saved = 0;
|
||||||
|
unsigned int console_in_cp_saved = 0;
|
||||||
|
|
||||||
int ScreenX;
|
int ScreenX;
|
||||||
int ScreenY;
|
int ScreenY;
|
||||||
@ -142,8 +145,22 @@ ConEnterRawMode()
|
|||||||
SavedViewRect = csbi.srWindow;
|
SavedViewRect = csbi.srWindow;
|
||||||
debug("console doesn't support the ansi parsing");
|
debug("console doesn't support the ansi parsing");
|
||||||
} else {
|
} else {
|
||||||
ConSaveViewRect();
|
|
||||||
debug("console supports the ansi parsing");
|
debug("console supports the ansi parsing");
|
||||||
|
if (is_conpty_supported()) {
|
||||||
|
console_out_cp_saved = GetConsoleOutputCP();
|
||||||
|
console_in_cp_saved = GetConsoleCP();
|
||||||
|
if (SetConsoleOutputCP(CP_UTF8))
|
||||||
|
debug3("Successfully set console output code page from:%d to %d", console_out_cp_saved, CP_UTF8);
|
||||||
|
else
|
||||||
|
error("Failed to set console output code page from:%d to %d error:%d", console_out_cp_saved, CP_UTF8, GetLastError());
|
||||||
|
|
||||||
|
if (SetConsoleCP(CP_UTF8))
|
||||||
|
debug3("Successfully set console input code page from:%d to %d", console_in_cp_saved, CP_UTF8);
|
||||||
|
else
|
||||||
|
error("Failed to set console input code page from:%d to %d error:%d", console_in_cp_saved, CP_UTF8, GetLastError());
|
||||||
|
} else {
|
||||||
|
ConSaveViewRect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConSetScreenX();
|
ConSetScreenX();
|
||||||
@ -160,6 +177,22 @@ ConExitRawMode()
|
|||||||
{
|
{
|
||||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), stdin_dwSavedAttributes);
|
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), stdin_dwSavedAttributes);
|
||||||
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), stdout_dwSavedAttributes);
|
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), stdout_dwSavedAttributes);
|
||||||
|
|
||||||
|
if (FALSE == isAnsiParsingRequired && is_conpty_supported()) {
|
||||||
|
if (console_out_cp_saved) {
|
||||||
|
if(SetConsoleOutputCP(console_out_cp_saved))
|
||||||
|
debug3("Successfully set console output code page from %d to %d", CP_UTF8, console_out_cp_saved);
|
||||||
|
else
|
||||||
|
error("Failed to set console output code page from %d to %d error:%d", CP_UTF8, console_out_cp_saved, GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console_in_cp_saved) {
|
||||||
|
if (SetConsoleCP(console_in_cp_saved))
|
||||||
|
debug3("Successfully set console input code page from %d to %d", CP_UTF8, console_in_cp_saved);
|
||||||
|
else
|
||||||
|
error("Failed to set console input code page from %d to %d error:%d", CP_UTF8, console_in_cp_saved, GetLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to exit the raw mode */
|
/* Used to exit the raw mode */
|
||||||
@ -223,7 +256,7 @@ ConSetScreenRect(int xSize, int ySize)
|
|||||||
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
|
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bSuccess)
|
if (bSuccess && !is_conpty_supported())
|
||||||
ConSaveViewRect();
|
ConSaveViewRect();
|
||||||
|
|
||||||
/* if the current buffer *is* the size we want, don't do anything! */
|
/* if the current buffer *is* the size we want, don't do anything! */
|
||||||
@ -270,7 +303,7 @@ ConSetScreenSize(int xSize, int ySize)
|
|||||||
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
|
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bSuccess)
|
if (bSuccess && !is_conpty_supported())
|
||||||
ConSaveViewRect();
|
ConSaveViewRect();
|
||||||
|
|
||||||
/* if the current buffer *is* the size we want, don't do anything! */
|
/* if the current buffer *is* the size we want, don't do anything! */
|
||||||
@ -1490,7 +1523,6 @@ void
|
|||||||
ConSaveViewRect()
|
ConSaveViewRect()
|
||||||
{
|
{
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
|
||||||
if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
|
if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
|
||||||
SavedViewRect = csbi.srWindow;
|
SavedViewRect = csbi.srWindow;
|
||||||
}
|
}
|
||||||
@ -1590,7 +1622,8 @@ ConMoveCursorTopOfVisibleWindow()
|
|||||||
offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top;
|
offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top;
|
||||||
ConMoveVisibleWindow(offset);
|
ConMoveVisibleWindow(offset);
|
||||||
|
|
||||||
ConSaveViewRect();
|
if(!is_conpty_supported())
|
||||||
|
ConSaveViewRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ fileio_pipe(struct w32_io* pio[2], int duplex)
|
|||||||
|
|
||||||
sec_attributes.bInheritHandle = TRUE;
|
sec_attributes.bInheritHandle = TRUE;
|
||||||
sec_attributes.lpSecurityDescriptor = NULL;
|
sec_attributes.lpSecurityDescriptor = NULL;
|
||||||
sec_attributes.nLength = 0;
|
sec_attributes.nLength = sizeof(sec_attributes);
|
||||||
|
|
||||||
/* create named pipe */
|
/* create named pipe */
|
||||||
write_handle = CreateNamedPipeA(pipe_name,
|
write_handle = CreateNamedPipeA(pipe_name,
|
||||||
@ -415,18 +415,18 @@ cleanup:
|
|||||||
|
|
||||||
/* returns 1 if true, 0 otherwise */
|
/* returns 1 if true, 0 otherwise */
|
||||||
int
|
int
|
||||||
file_in_chroot_jail(HANDLE handle, const char* path_utf8) {
|
file_in_chroot_jail(HANDLE handle) {
|
||||||
/* ensure final path is within chroot */
|
/* ensure final path is within chroot */
|
||||||
wchar_t path_buf[MAX_PATH], *final_path;
|
wchar_t *final_path;
|
||||||
if (GetFinalPathNameByHandleW(handle, path_buf, MAX_PATH, 0) == 0) {
|
|
||||||
debug3("failed to get final path of file:%s error:%d", path_utf8, GetLastError());
|
final_path = get_final_path_by_handle(handle);
|
||||||
|
if (!final_path)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
final_path = path_buf + 4;
|
|
||||||
to_wlower_case(final_path);
|
to_wlower_case(final_path);
|
||||||
if ((wcslen(final_path) < wcslen(chroot_pathw)) ||
|
if ((wcslen(final_path) < wcslen(chroot_pathw)) ||
|
||||||
memcmp(final_path, chroot_pathw, 2 * wcslen(chroot_pathw)) != 0 ||
|
memcmp(final_path, chroot_pathw, 2 * wcslen(chroot_pathw)) != 0 ||
|
||||||
final_path[wcslen(chroot_pathw)] != '\\') {
|
final_path[wcslen(chroot_pathw)] != '\\') {
|
||||||
debug3("access denied due to attempt to escape chroot jail");
|
debug3("access denied due to attempt to escape chroot jail");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -478,7 +478,8 @@ fileio_open(const char *path_utf8, int flags, mode_t mode)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chroot_pathw && !nonfs_dev && !file_in_chroot_jail(handle, path_utf8)) {
|
if (chroot_pathw && !nonfs_dev && !file_in_chroot_jail(handle)) {
|
||||||
|
debug3("%s is not in chroot jail", path_utf8);
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -776,7 +777,7 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = _open_osfhandle(dup_handle, 0);
|
int fd = _open_osfhandle((intptr_t)dup_handle, 0);
|
||||||
debug4("fstat - pio:%p", pio);
|
debug4("fstat - pio:%p", pio);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
CloseHandle(dup_handle);
|
CloseHandle(dup_handle);
|
||||||
@ -902,44 +903,41 @@ fileio_lseek(struct w32_io* pio, unsigned __int64 offset, int origin)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fdopen implementation */
|
/*
|
||||||
|
* fdopen implementation - use with caution
|
||||||
|
* this implementation deviates from POSIX spec the following way
|
||||||
|
* - the underlying file descriptor is closed automatically
|
||||||
|
* hence no further POSIX io operations (read, write, close, etc) on the
|
||||||
|
* underlying file descriptor are supported
|
||||||
|
*/
|
||||||
FILE*
|
FILE*
|
||||||
fileio_fdopen(struct w32_io* pio, const char *mode)
|
fileio_fdopen(struct w32_io* pio, const char *mode)
|
||||||
{
|
{
|
||||||
int fd_flags = 0;
|
wchar_t *file_path, *wmode = NULL;
|
||||||
|
FILE* ret = NULL;
|
||||||
|
|
||||||
debug4("fdopen - io:%p", pio);
|
debug4("fdopen - io:%p", pio);
|
||||||
|
|
||||||
/* logic below doesn't work with overlapped file HANDLES */
|
if ((wmode = utf8_to_utf16(mode)) == NULL)
|
||||||
if (mode[1] == '\0') {
|
goto cleanup;
|
||||||
switch (*mode) {
|
|
||||||
case 'r':
|
|
||||||
fd_flags = _O_RDONLY;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
fd_flags = _O_APPEND;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errno = ENOTSUP;
|
|
||||||
debug3("fdopen - ERROR unsupported mode %s", mode);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errno = ENOTSUP;
|
|
||||||
debug3("fdopen - ERROR unsupported mode %s", mode);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd = _open_osfhandle((intptr_t)pio->handle, fd_flags);
|
file_path = get_final_path_by_handle(pio->handle);
|
||||||
|
if (!file_path)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (fd == -1) {
|
/*
|
||||||
errno = EOTHER;
|
* close the win32 handle right away and remove entry from table
|
||||||
debug3("fdopen - ERROR:%d _open_osfhandle()", errno);
|
* otherwise, wfopen will get an access denied due to sharing violation
|
||||||
return NULL;
|
*/
|
||||||
}
|
int w32_close(int);
|
||||||
|
w32_close(pio->table_index);
|
||||||
|
errno = _wfopen_s(&ret, file_path, wmode);
|
||||||
|
|
||||||
return _fdopen(fd, mode);
|
cleanup:
|
||||||
|
if (wmode)
|
||||||
|
free(wmode);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -38,6 +38,10 @@ int w32_mkdir(const char *pathname, unsigned short mode);
|
|||||||
int w32_chmod(const char *, mode_t);
|
int w32_chmod(const char *, mode_t);
|
||||||
#define chmod w32_chmod
|
#define chmod w32_chmod
|
||||||
|
|
||||||
|
int w32_fchmod(int fd, mode_t mode);
|
||||||
|
#define fchmod w32_fchmod
|
||||||
|
|
||||||
|
|
||||||
struct w32_stat {
|
struct w32_stat {
|
||||||
dev_t st_dev; /* ID of device containing file */
|
dev_t st_dev; /* ID of device containing file */
|
||||||
unsigned short st_ino; /* inode number */
|
unsigned short st_ino; /* inode number */
|
||||||
|
@ -286,7 +286,8 @@ w32_fopen_utf8(const char *input_path, const char *mode)
|
|||||||
if (chroot_pathw && !nonfs_dev) {
|
if (chroot_pathw && !nonfs_dev) {
|
||||||
/* ensure final path is within chroot */
|
/* ensure final path is within chroot */
|
||||||
HANDLE h = (HANDLE)_get_osfhandle(_fileno(f));
|
HANDLE h = (HANDLE)_get_osfhandle(_fileno(f));
|
||||||
if (!file_in_chroot_jail(h, input_path)) {
|
if (!file_in_chroot_jail(h)) {
|
||||||
|
debug3("%s is not in chroot jail", input_path);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
@ -419,34 +420,6 @@ w32_setvbuf(FILE *stream, char *buffer, int mode, size_t size) {
|
|||||||
return setvbuf(stream, buffer, mode, size);
|
return setvbuf(stream, buffer, mode, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO - deprecate this. This is not a POSIX API, used internally only */
|
|
||||||
char *
|
|
||||||
w32_programdir()
|
|
||||||
{
|
|
||||||
wchar_t* wpgmptr;
|
|
||||||
|
|
||||||
if (s_programdir != NULL)
|
|
||||||
return s_programdir;
|
|
||||||
|
|
||||||
if (_get_wpgmptr(&wpgmptr) != 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
daemon(int nochdir, int noclose)
|
daemon(int nochdir, int noclose)
|
||||||
{
|
{
|
||||||
@ -1592,11 +1565,11 @@ cleanup:
|
|||||||
|
|
||||||
/* builds session commandline. returns NULL with errno set on failure, caller should free returned string */
|
/* builds session commandline. returns NULL with errno set on failure, caller should free returned string */
|
||||||
char*
|
char*
|
||||||
build_session_commandline(const char *shell, const char* shell_arg, const char *command, int pty)
|
build_session_commandline(const char *shell, const char* shell_arg, const char *command)
|
||||||
{
|
{
|
||||||
enum sh_type { SH_OTHER, SH_CMD, SH_PS, SH_BASH } shell_type = SH_OTHER;
|
enum sh_type { SH_OTHER, SH_CMD, SH_PS, SH_BASH } shell_type = SH_OTHER;
|
||||||
enum cmd_type { CMD_OTHER, CMD_SFTP, CMD_SCP } command_type = CMD_OTHER;
|
enum cmd_type { CMD_OTHER, CMD_SFTP, CMD_SCP } command_type = CMD_OTHER;
|
||||||
char *progdir = w32_programdir(), *cmd_sp = NULL, *cmdline = NULL, *ret = NULL, *p;
|
char *progdir = __progdir, *cmd_sp = NULL, *cmdline = NULL, *ret = NULL, *p;
|
||||||
int len, progdir_len = (int)strlen(progdir);
|
int len, progdir_len = (int)strlen(progdir);
|
||||||
|
|
||||||
#define CMDLINE_APPEND(P, S) \
|
#define CMDLINE_APPEND(P, S) \
|
||||||
@ -1650,7 +1623,7 @@ do { \
|
|||||||
if (!command)
|
if (!command)
|
||||||
break;
|
break;
|
||||||
command_len = (int)strlen(command);
|
command_len = (int)strlen(command);
|
||||||
|
/*TODO - replace numbers below with readable compile time operators*/
|
||||||
if (command_len >= 13 && _memicmp(command, "internal-sftp", 13) == 0) {
|
if (command_len >= 13 && _memicmp(command, "internal-sftp", 13) == 0) {
|
||||||
command_type = CMD_SFTP;
|
command_type = CMD_SFTP;
|
||||||
command_args = command + 13;
|
command_args = command + 13;
|
||||||
@ -1687,7 +1660,6 @@ do { \
|
|||||||
p = cmd_sp;
|
p = cmd_sp;
|
||||||
|
|
||||||
if (shell_type == SH_CMD) {
|
if (shell_type == SH_CMD) {
|
||||||
|
|
||||||
CMDLINE_APPEND(p, "\"");
|
CMDLINE_APPEND(p, "\"");
|
||||||
CMDLINE_APPEND(p, progdir);
|
CMDLINE_APPEND(p, progdir);
|
||||||
|
|
||||||
@ -1709,8 +1681,6 @@ do { \
|
|||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
if (pty)
|
|
||||||
len += progdir_len + (int)strlen("ssh-shellhost.exe") + 5;
|
|
||||||
len +=(int) strlen(shell) + 3;/* 3 for " around shell path and trailing space */
|
len +=(int) strlen(shell) + 3;/* 3 for " around shell path and trailing space */
|
||||||
if (command) {
|
if (command) {
|
||||||
len += 15; /* for shell command argument, typically -c or /c */
|
len += 15; /* for shell command argument, typically -c or /c */
|
||||||
@ -1723,11 +1693,6 @@ do { \
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = cmdline;
|
p = cmdline;
|
||||||
if (pty) {
|
|
||||||
CMDLINE_APPEND(p, "\"");
|
|
||||||
CMDLINE_APPEND(p, progdir);
|
|
||||||
CMDLINE_APPEND(p, "\\ssh-shellhost.exe\" ");
|
|
||||||
}
|
|
||||||
CMDLINE_APPEND(p, "\"");
|
CMDLINE_APPEND(p, "\"");
|
||||||
CMDLINE_APPEND(p, shell);
|
CMDLINE_APPEND(p, shell);
|
||||||
CMDLINE_APPEND(p, "\"");
|
CMDLINE_APPEND(p, "\"");
|
||||||
@ -1742,14 +1707,10 @@ do { \
|
|||||||
else
|
else
|
||||||
CMDLINE_APPEND(p, " -c ");
|
CMDLINE_APPEND(p, " -c ");
|
||||||
|
|
||||||
/* bash type shells require " decoration around command*/
|
/* Add double quotes around command */
|
||||||
if (shell_type == SH_BASH)
|
CMDLINE_APPEND(p, "\"");
|
||||||
CMDLINE_APPEND(p, "\"");
|
|
||||||
|
|
||||||
CMDLINE_APPEND(p, command);
|
CMDLINE_APPEND(p, command);
|
||||||
|
CMDLINE_APPEND(p, "\"");
|
||||||
if (shell_type == SH_BASH)
|
|
||||||
CMDLINE_APPEND(p, "\"");
|
|
||||||
}
|
}
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
ret = cmdline;
|
ret = cmdline;
|
||||||
|
@ -25,6 +25,17 @@
|
|||||||
/* maximum size for user principal name as defined in ad schema */
|
/* maximum size for user principal name as defined in ad schema */
|
||||||
#define MAX_UPN_LEN 1024
|
#define MAX_UPN_LEN 1024
|
||||||
|
|
||||||
|
/* PTY windows size event type (for conhost and ssh-shellhost) */
|
||||||
|
#define PTY_SIGNAL_RESIZE_WINDOW 8u
|
||||||
|
|
||||||
|
/* maximum command line length */
|
||||||
|
#define MAX_CMD_LEN 8191
|
||||||
|
|
||||||
|
/* prog paths */
|
||||||
|
extern char* __progname;
|
||||||
|
extern char* __progdir;
|
||||||
|
extern wchar_t* __wprogdir;
|
||||||
|
|
||||||
static char *machine_domain_name;
|
static char *machine_domain_name;
|
||||||
|
|
||||||
extern char* chroot_path;
|
extern char* chroot_path;
|
||||||
@ -35,7 +46,7 @@ extern wchar_t* chroot_pathw;
|
|||||||
wchar_t * resolved_path_utf16(const char *);
|
wchar_t * resolved_path_utf16(const char *);
|
||||||
void w32posix_initialize();
|
void w32posix_initialize();
|
||||||
void w32posix_done();
|
void w32posix_done();
|
||||||
char* w32_programdir();
|
void init_prog_paths();
|
||||||
void convertToBackslash(char *str);
|
void convertToBackslash(char *str);
|
||||||
void convertToBackslashW(wchar_t *str);
|
void convertToBackslashW(wchar_t *str);
|
||||||
void convertToForwardslash(char *str);
|
void convertToForwardslash(char *str);
|
||||||
@ -51,9 +62,12 @@ HANDLE get_user_token(const char* user, int impersonation);
|
|||||||
int load_user_profile(HANDLE user_token, char* user);
|
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, const char*);
|
int file_in_chroot_jail(HANDLE);
|
||||||
PSID get_sid(const char*);
|
PSID get_sid(const char*);
|
||||||
int am_system();
|
int am_system();
|
||||||
char* build_session_commandline(const char *, const char *, const char *, int );
|
char* build_session_commandline(const char *, const char *, const char *);
|
||||||
|
int is_conpty_supported();
|
||||||
|
int exec_command_with_pty(wchar_t*, STARTUPINFOW*, PROCESS_INFORMATION*, int);
|
||||||
char* get_custom_lsa_package();
|
char* get_custom_lsa_package();
|
||||||
|
wchar_t* get_final_path_by_handle(HANDLE h);
|
||||||
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name);
|
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name);
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
#define MAX_CONSOLE_COLUMNS 9999
|
#define MAX_CONSOLE_COLUMNS 9999
|
||||||
#define MAX_CONSOLE_ROWS 9999
|
#define MAX_CONSOLE_ROWS 9999
|
||||||
#define MAX_CMD_LEN 8191 // msdn
|
|
||||||
#define WM_APPEXIT WM_USER+1
|
#define WM_APPEXIT WM_USER+1
|
||||||
#define MAX_EXPECTED_BUFFER_SIZE 1024
|
#define MAX_EXPECTED_BUFFER_SIZE 1024
|
||||||
/* 4KB is the largest size for which writes are guaranteed to be atomic */
|
/* 4KB is the largest size for which writes are guaranteed to be atomic */
|
||||||
@ -274,13 +273,14 @@ HANDLE child_in = INVALID_HANDLE_VALUE;
|
|||||||
HANDLE child_err = INVALID_HANDLE_VALUE;
|
HANDLE child_err = INVALID_HANDLE_VALUE;
|
||||||
HANDLE pipe_in = INVALID_HANDLE_VALUE;
|
HANDLE pipe_in = INVALID_HANDLE_VALUE;
|
||||||
HANDLE pipe_out = INVALID_HANDLE_VALUE;
|
HANDLE pipe_out = INVALID_HANDLE_VALUE;
|
||||||
HANDLE pipe_err = INVALID_HANDLE_VALUE;
|
HANDLE pipe_ctrl = INVALID_HANDLE_VALUE;
|
||||||
HANDLE child = INVALID_HANDLE_VALUE;
|
HANDLE child = INVALID_HANDLE_VALUE;
|
||||||
HANDLE job = NULL;
|
HANDLE job = NULL;
|
||||||
HANDLE hConsoleBuffer = INVALID_HANDLE_VALUE;
|
HANDLE hConsoleBuffer = INVALID_HANDLE_VALUE;
|
||||||
HANDLE monitor_thread = INVALID_HANDLE_VALUE;
|
HANDLE monitor_thread = INVALID_HANDLE_VALUE;
|
||||||
HANDLE io_thread = INVALID_HANDLE_VALUE;
|
HANDLE io_thread = INVALID_HANDLE_VALUE;
|
||||||
HANDLE ux_thread = INVALID_HANDLE_VALUE;
|
HANDLE ux_thread = INVALID_HANDLE_VALUE;
|
||||||
|
HANDLE ctrl_thread = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
DWORD child_exit_code = 0;
|
DWORD child_exit_code = 0;
|
||||||
DWORD hostProcessId = 0;
|
DWORD hostProcessId = 0;
|
||||||
@ -800,6 +800,48 @@ MonitorChild(_In_ LPVOID lpParameter)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned __stdcall
|
||||||
|
ControlThread(LPVOID p)
|
||||||
|
{
|
||||||
|
short type, row, col;
|
||||||
|
DWORD len;
|
||||||
|
COORD coord;
|
||||||
|
SMALL_RECT rect;
|
||||||
|
while (1) {
|
||||||
|
if (!ReadFile(pipe_ctrl, &type, 2, &len, NULL))
|
||||||
|
break;
|
||||||
|
if (type != PTY_SIGNAL_RESIZE_WINDOW)
|
||||||
|
break;
|
||||||
|
if (!ReadFile(pipe_ctrl, &col, 2, &len, NULL))
|
||||||
|
break;
|
||||||
|
if (!ReadFile(pipe_ctrl, &row, 2, &len, NULL))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* when reducing width, console seemed to retain prior width
|
||||||
|
* while increasing width, however, it behaves right
|
||||||
|
*
|
||||||
|
* hence setting it less by 1 and setting it again to the right
|
||||||
|
* count
|
||||||
|
*/
|
||||||
|
|
||||||
|
coord.X = col - 1;
|
||||||
|
coord.Y = row;
|
||||||
|
rect.Top = 0;
|
||||||
|
rect.Left = 0;
|
||||||
|
rect.Bottom = row - 1;
|
||||||
|
rect.Right = col - 2;
|
||||||
|
SetConsoleScreenBufferSize(child_out, coord);
|
||||||
|
SetConsoleWindowInfo(child_out, TRUE, &rect);
|
||||||
|
|
||||||
|
coord.X = col;
|
||||||
|
rect.Right = col - 1;
|
||||||
|
SetConsoleScreenBufferSize(child_out, coord);
|
||||||
|
SetConsoleWindowInfo(child_out, TRUE, &rect);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
ProcessEvent(void *p)
|
ProcessEvent(void *p)
|
||||||
{
|
{
|
||||||
@ -1231,10 +1273,10 @@ start_with_pty(wchar_t *command)
|
|||||||
|
|
||||||
pipe_in = GetStdHandle(STD_INPUT_HANDLE);
|
pipe_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
pipe_out = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
pipe_err = GetStdHandle(STD_ERROR_HANDLE);
|
pipe_ctrl = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
/* copy pipe handles passed through std io*/
|
/* copy pipe handles passed through std io*/
|
||||||
if ((pipe_in == INVALID_HANDLE_VALUE) || (pipe_out == INVALID_HANDLE_VALUE) || (pipe_err == INVALID_HANDLE_VALUE))
|
if ((pipe_in == INVALID_HANDLE_VALUE) || (pipe_out == INVALID_HANDLE_VALUE) || (pipe_ctrl == INVALID_HANDLE_VALUE))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
cp = GetConsoleCP();
|
cp = GetConsoleCP();
|
||||||
@ -1272,10 +1314,7 @@ start_with_pty(wchar_t *command)
|
|||||||
/*
|
/*
|
||||||
* Launch via cmd.exe /c, otherwise known issues exist with color rendering in powershell
|
* Launch via cmd.exe /c, otherwise known issues exist with color rendering in powershell
|
||||||
*/
|
*/
|
||||||
cmd[0] = L'\0';
|
_snwprintf_s(cmd, MAX_CMD_LEN, MAX_CMD_LEN, L"\"%ls\\cmd.exe\" /c \"%ls\"", system32_path, command);
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, system32_path));
|
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"\\cmd.exe /c "));
|
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, command));
|
|
||||||
|
|
||||||
SetConsoleCtrlHandler(NULL, FALSE);
|
SetConsoleCtrlHandler(NULL, FALSE);
|
||||||
GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
|
GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
|
||||||
@ -1311,6 +1350,10 @@ start_with_pty(wchar_t *command)
|
|||||||
if (IS_INVALID_HANDLE(ux_thread))
|
if (IS_INVALID_HANDLE(ux_thread))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
ctrl_thread = (HANDLE)_beginthreadex(NULL, 0, ControlThread, NULL, 0, NULL);
|
||||||
|
if (IS_INVALID_HANDLE(ctrl_thread))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
ProcessMessages(NULL);
|
ProcessMessages(NULL);
|
||||||
cleanup:
|
cleanup:
|
||||||
dwStatus = GetLastError();
|
dwStatus = GetLastError();
|
||||||
@ -1330,6 +1373,11 @@ cleanup:
|
|||||||
CloseHandle(io_thread);
|
CloseHandle(io_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IS_INVALID_HANDLE(ctrl_thread)) {
|
||||||
|
TerminateThread(ctrl_thread, 0);
|
||||||
|
CloseHandle(ctrl_thread);
|
||||||
|
}
|
||||||
|
|
||||||
if (hEventHook)
|
if (hEventHook)
|
||||||
__UnhookWinEvent(hEventHook);
|
__UnhookWinEvent(hEventHook);
|
||||||
|
|
||||||
@ -1349,20 +1397,99 @@ cleanup:
|
|||||||
return child_exit_code;
|
return child_exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* implements a basic shell - launches given cmd using CreateProcess */
|
||||||
wmain(int ac, wchar_t **av)
|
int start_as_shell(wchar_t* cmd)
|
||||||
{
|
{
|
||||||
wchar_t *exec_command;
|
STARTUPINFOW si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
_set_invalid_parameter_handler(my_invalid_parameter_handler);
|
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||||
|
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
|
||||||
|
si.cb = sizeof(STARTUPINFOW);
|
||||||
|
|
||||||
if (ac == 1) {
|
if (CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == FALSE) {
|
||||||
printf("usage: shellhost.exe <cmdline to be executed with PTY support>\n");
|
printf("ssh-shellhost cannot run '%ls', error: %d", cmd, GetLastError());
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get past shellhost.exe in commandline */
|
CloseHandle(pi.hThread);
|
||||||
exec_command = wcsstr(GetCommandLineW(), L"shellhost.exe") + wcslen(L"shellhost.exe") + 1;
|
/* close std io handles */
|
||||||
|
CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
|
||||||
|
CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
|
CloseHandle(GetStdHandle(STD_ERROR_HANDLE));
|
||||||
|
child_exit_code = 255;
|
||||||
|
|
||||||
return start_with_pty(exec_command);
|
/* wait for child to exit */
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
if (!GetExitCodeProcess(pi.hProcess, &child_exit_code))
|
||||||
|
printf("ssh-shellhost unable to track child process, error: %d", GetLastError());
|
||||||
|
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
return child_exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Usage:
|
||||||
|
* Execute commandline with PTY
|
||||||
|
* ssh-shellhost.exe ---pty commandline
|
||||||
|
* Note that in PTY mode, stderr is taken as the control channel
|
||||||
|
* to receive Windows size change events
|
||||||
|
*
|
||||||
|
* Execute commandline like shell (plain IO redirection)
|
||||||
|
* Syntax mimics cmd.exe -c usage. Note the explicit double quotes
|
||||||
|
* around actual commandline to execute.
|
||||||
|
* ssh-shellhost.exe -c "commandline"
|
||||||
|
* Ex. ssh-shellhost.exe -c "notepad.exe file.txt"
|
||||||
|
* ssh-shellhost.exe -c ""my program.exe" "arg 1" "arg 2""
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
wmain(int ac, wchar_t **av)
|
||||||
|
{
|
||||||
|
wchar_t *exec_command, *option, *cmdline;
|
||||||
|
int with_pty, len;
|
||||||
|
|
||||||
|
_set_invalid_parameter_handler(my_invalid_parameter_handler);
|
||||||
|
|
||||||
|
if (ac == 1)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
if ((cmdline = _wcsdup(GetCommandLineW())) == NULL) {
|
||||||
|
printf("ssh-shellhost.exe ran out of memory");
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option = wcsstr(cmdline, L" ---pty "))
|
||||||
|
with_pty = 1;
|
||||||
|
else if (option = wcsstr(cmdline, L" -c "))
|
||||||
|
with_pty = 0;
|
||||||
|
else
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
if (with_pty)
|
||||||
|
exec_command = option + wcslen(L" ---pty ");
|
||||||
|
else
|
||||||
|
exec_command = option + wcslen(L" -c ");
|
||||||
|
|
||||||
|
/* strip preceding white spaces */
|
||||||
|
while (*exec_command != L'\0' && *exec_command == L' ')
|
||||||
|
exec_command++;
|
||||||
|
|
||||||
|
if (exec_command == L'\0')
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
if (with_pty)
|
||||||
|
return start_with_pty(exec_command);
|
||||||
|
else {
|
||||||
|
/* if commandline is enclosed in double quotes, remove them */
|
||||||
|
len = (int)wcslen(exec_command);
|
||||||
|
if (len > 2 && *exec_command == L'\"' && *(exec_command + len - 1) == L'\"') {
|
||||||
|
*(exec_command + len - 1) = L'\0';
|
||||||
|
exec_command++;
|
||||||
|
}
|
||||||
|
return start_as_shell(exec_command);
|
||||||
|
}
|
||||||
|
usage:
|
||||||
|
printf("ssh-shellhost does not support command line: %ls", cmdline);
|
||||||
|
exit(255);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ static VOID CALLBACK
|
|||||||
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
|
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
|
||||||
{
|
{
|
||||||
debug5("SIGTERM APCProc()");
|
debug5("SIGTERM APCProc()");
|
||||||
sigaddset(&pending_signals, W32_SIGWINCH);
|
sigaddset(&pending_signals, SIGWINCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
#define SHIFT_TAB_KEY "\x1b[~"
|
#define SHIFT_TAB_KEY "\x1b[~"
|
||||||
#define SHIFT_ALT_Q "\x1b?"
|
#define SHIFT_ALT_Q "\x1b?"
|
||||||
#define ESCAPE_KEY "\x1b"
|
#define ESCAPE_KEY "\x1b"
|
||||||
#define BACKSPACE_KEY "\b"
|
#define BACKSPACE_KEY "\x7f"
|
||||||
|
|
||||||
// VT100 Function Key's
|
// VT100 Function Key's
|
||||||
#define VT100_PF1_KEY "\x1bO2"
|
#define VT100_PF1_KEY "\x1bO2"
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "ansiprsr.h"
|
#include "ansiprsr.h"
|
||||||
#include "inc\utf.h"
|
#include "inc\utf.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
#include "misc_internal.h"
|
||||||
|
|
||||||
#define dwBuffer 4096
|
#define dwBuffer 4096
|
||||||
|
|
||||||
@ -51,16 +52,17 @@ BOOL isFirstPacket = TRUE;
|
|||||||
* are hardcoded in the server and will be transformed to Windows Console commands.
|
* are hardcoded in the server and will be transformed to Windows Console commands.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, size_t *resplen)
|
processBuffer(HANDLE handle, char *buf, DWORD len, unsigned char **respbuf, size_t *resplen)
|
||||||
{
|
{
|
||||||
unsigned char *pszNewHead = NULL;
|
unsigned char *pszNewHead = NULL;
|
||||||
unsigned char *pszHead = NULL;
|
unsigned char *pszHead = NULL;
|
||||||
unsigned char *pszTail = NULL;
|
unsigned char *pszTail = NULL;
|
||||||
const char *applicationModeSeq = "\x1b[?1h";
|
const char *applicationModeSeq = "\x1b[?1h";
|
||||||
const int applicationModeSeqLen = (int)strlen(applicationModeSeq);
|
const DWORD applicationModeSeqLen = (DWORD)strlen(applicationModeSeq);
|
||||||
const char *normalModeSeq = "\x1b[?1l";
|
const char *normalModeSeq = "\x1b[?1l";
|
||||||
const int normalModeSeqLen = (int)strlen(normalModeSeq);
|
const DWORD normalModeSeqLen = (DWORD)strlen(normalModeSeq);
|
||||||
const char *clsSeq = "\x1b[2J";
|
const char *clsSeq = "\x1b[2J";
|
||||||
|
static int track_view_port = 1;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return;
|
return;
|
||||||
@ -68,6 +70,10 @@ processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, siz
|
|||||||
if (false == isAnsiParsingRequired) {
|
if (false == isAnsiParsingRequired) {
|
||||||
if(isFirstPacket) {
|
if(isFirstPacket) {
|
||||||
isFirstPacket = FALSE;
|
isFirstPacket = FALSE;
|
||||||
|
|
||||||
|
if (is_conpty_supported())
|
||||||
|
track_view_port = 0;
|
||||||
|
|
||||||
/* Windows server at first sends the "cls" after the connection is established.
|
/* Windows server at first sends the "cls" after the connection is established.
|
||||||
* There is a bug in the conhost which causes the visible window data to loose so to
|
* There is a bug in the conhost which causes the visible window data to loose so to
|
||||||
* mitigate that issue we need to first move the visible window so that the cursor is at the top of the visible window.
|
* mitigate that issue we need to first move the visible window so that the cursor is at the top of the visible window.
|
||||||
@ -81,15 +87,18 @@ processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, siz
|
|||||||
else if(len >= normalModeSeqLen && strstr(buf, normalModeSeq))
|
else if(len >= normalModeSeqLen && strstr(buf, normalModeSeq))
|
||||||
gbVTAppMode = false;
|
gbVTAppMode = false;
|
||||||
|
|
||||||
/* Console has the capability to parse so pass the raw buffer to console directly */
|
/* WriteFile() gets messy when user does scroll up/down so we need to restore the visible window.
|
||||||
ConRestoreViewRect(); /* Restore the visible window, otherwise WriteConsoleW() gets messy */
|
* It's a conhost bug but we need to live with it as they are not going to back port the fix.
|
||||||
wchar_t* t = utf8_to_utf16(buf);
|
*/
|
||||||
if (t) {
|
if(track_view_port)
|
||||||
WriteConsoleW(handle, t, (DWORD)wcslen(t), 0, 0);
|
ConRestoreViewRect();
|
||||||
free(t);
|
|
||||||
}
|
/* Console has the capability to parse so pass the raw buffer to console directly */
|
||||||
|
WriteFile(handle, buf, len, 0, 0);
|
||||||
|
|
||||||
|
if (track_view_port)
|
||||||
|
ConSaveViewRect();
|
||||||
|
|
||||||
ConSaveViewRect();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,6 @@
|
|||||||
|
|
||||||
#ifndef __TNNET_H
|
#ifndef __TNNET_H
|
||||||
#define __TNNET_H
|
#define __TNNET_H
|
||||||
void processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, size_t *resplen);
|
void processBuffer(HANDLE handle, char *buf, DWORD len, unsigned char **respbuf, size_t *resplen);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -51,7 +51,7 @@ system32_dir()
|
|||||||
static HMODULE
|
static HMODULE
|
||||||
load_module(wchar_t* name)
|
load_module(wchar_t* name)
|
||||||
{
|
{
|
||||||
HMODULE hm;
|
HMODULE hm = NULL;
|
||||||
|
|
||||||
/*system uses a standard search strategy to find the module */
|
/*system uses a standard search strategy to find the module */
|
||||||
if ((hm = LoadLibraryW(name)) == NULL)
|
if ((hm = LoadLibraryW(name)) == NULL)
|
||||||
@ -82,6 +82,17 @@ load_advapi32()
|
|||||||
return s_hm_advapi32;
|
return s_hm_advapi32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HMODULE
|
||||||
|
load_api_security_lsapolicy()
|
||||||
|
{
|
||||||
|
static HMODULE s_hm_api_security_lsapolicy = NULL;
|
||||||
|
|
||||||
|
if (!s_hm_api_security_lsapolicy)
|
||||||
|
s_hm_api_security_lsapolicy = load_module(L"api-ms-win-security-lsapolicy-l1-1-0.dll");
|
||||||
|
|
||||||
|
return s_hm_api_security_lsapolicy;
|
||||||
|
}
|
||||||
|
|
||||||
static HMODULE
|
static HMODULE
|
||||||
load_secur32()
|
load_secur32()
|
||||||
{
|
{
|
||||||
@ -106,6 +117,9 @@ load_ntdll()
|
|||||||
|
|
||||||
FARPROC get_proc_address(HMODULE hm, char* fn)
|
FARPROC get_proc_address(HMODULE hm, char* fn)
|
||||||
{
|
{
|
||||||
|
if (hm == NULL) {
|
||||||
|
debug3("GetProcAddress of %s failed with error %d.", fn, GetLastError());
|
||||||
|
}
|
||||||
FARPROC ret = GetProcAddress(hm, fn);
|
FARPROC ret = GetProcAddress(hm, fn);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
debug3("GetProcAddress of %s failed with error %d.", fn, GetLastError());
|
debug3("GetProcAddress of %s failed with error %d.", fn, GetLastError());
|
||||||
@ -119,6 +133,7 @@ pLogonUserExExW(wchar_t *user_name, wchar_t *domain, wchar_t *password, DWORD lo
|
|||||||
PVOID *profile_buffer, LPDWORD profile_length, PQUOTA_LIMITS quota_limits)
|
PVOID *profile_buffer, LPDWORD profile_length, PQUOTA_LIMITS quota_limits)
|
||||||
{
|
{
|
||||||
HMODULE hm = NULL;
|
HMODULE hm = NULL;
|
||||||
|
|
||||||
typedef BOOL(WINAPI *LogonUserExExWType)(wchar_t*, wchar_t*, wchar_t*, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID, PVOID, LPDWORD, PQUOTA_LIMITS);
|
typedef BOOL(WINAPI *LogonUserExExWType)(wchar_t*, wchar_t*, wchar_t*, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID, PVOID, LPDWORD, PQUOTA_LIMITS);
|
||||||
static LogonUserExExWType s_pLogonUserExExW = NULL;
|
static LogonUserExExWType s_pLogonUserExExW = NULL;
|
||||||
|
|
||||||
@ -154,10 +169,79 @@ BOOLEAN pTranslateNameW(LPCWSTR name,
|
|||||||
if ((s_pTranslateNameW = (TranslateNameWType)get_proc_address(hm, "TranslateNameW")) == NULL)
|
if ((s_pTranslateNameW = (TranslateNameWType)get_proc_address(hm, "TranslateNameW")) == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_pTranslateNameW(name, account_format, desired_name_format, translated_name, psize);
|
return s_pTranslateNameW(name, account_format, desired_name_format, translated_name, psize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING system_name,
|
||||||
|
PLSA_OBJECT_ATTRIBUTES attrib,
|
||||||
|
ACCESS_MASK access,
|
||||||
|
PLSA_HANDLE handle)
|
||||||
|
{
|
||||||
|
HMODULE hm = NULL;
|
||||||
|
typedef NTSTATUS(NTAPI *LsaOpenPolicyType)(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE);
|
||||||
|
static LsaOpenPolicyType s_pLsaOpenPolicy = NULL;
|
||||||
|
if (!s_pLsaOpenPolicy) {
|
||||||
|
if ((hm = load_api_security_lsapolicy()) == NULL &&
|
||||||
|
((hm = load_advapi32()) == NULL))
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
if ((s_pLsaOpenPolicy = (LsaOpenPolicyType)get_proc_address(hm, "LsaOpenPolicy")) == NULL)
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
}
|
||||||
|
return s_pLsaOpenPolicy(system_name, attrib, access, handle);
|
||||||
|
}
|
||||||
|
NTSTATUS pLsaFreeMemory(PVOID buffer)
|
||||||
|
{
|
||||||
|
HMODULE hm = NULL;
|
||||||
|
typedef NTSTATUS(NTAPI *LsaFreeMemoryType)(PVOID);
|
||||||
|
static LsaFreeMemoryType s_pLsaFreeMemory = NULL;
|
||||||
|
if (!s_pLsaFreeMemory) {
|
||||||
|
if ((hm = load_api_security_lsapolicy()) == NULL &&
|
||||||
|
((hm = load_advapi32()) == NULL))
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
if ((s_pLsaFreeMemory = (LsaFreeMemoryType)get_proc_address(hm, "LsaFreeMemory")) == NULL)
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
}
|
||||||
|
return s_pLsaFreeMemory(buffer);
|
||||||
|
}
|
||||||
|
NTSTATUS pLsaAddAccountRights(LSA_HANDLE lsa_h,
|
||||||
|
PSID psid,
|
||||||
|
PLSA_UNICODE_STRING rights,
|
||||||
|
ULONG num_rights)
|
||||||
|
{
|
||||||
|
HMODULE hm = NULL;
|
||||||
|
typedef NTSTATUS(NTAPI *LsaAddAccountRightsType)(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG);
|
||||||
|
static LsaAddAccountRightsType s_pLsaAddAccountRights = NULL;
|
||||||
|
if (!s_pLsaAddAccountRights) {
|
||||||
|
if ((hm = load_api_security_lsapolicy()) == NULL &&
|
||||||
|
((hm = load_advapi32()) == NULL))
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
if ((s_pLsaAddAccountRights = (LsaAddAccountRightsType)get_proc_address(hm, "LsaAddAccountRights")) == NULL)
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_pLsaAddAccountRights(lsa_h, psid, rights, num_rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS pLsaRemoveAccountRights(LSA_HANDLE lsa_h,
|
||||||
|
PSID psid,
|
||||||
|
BOOLEAN all_rights,
|
||||||
|
PLSA_UNICODE_STRING rights,
|
||||||
|
ULONG num_rights)
|
||||||
|
{
|
||||||
|
HMODULE hm = NULL;
|
||||||
|
typedef NTSTATUS(NTAPI *LsaRemoveAccountRightsType)(LSA_HANDLE, PSID, BOOLEAN, PLSA_UNICODE_STRING, ULONG);
|
||||||
|
static LsaRemoveAccountRightsType s_pLsaRemoveAccountRights = NULL;
|
||||||
|
if (!s_pLsaRemoveAccountRights) {
|
||||||
|
if ((hm = load_api_security_lsapolicy()) == NULL &&
|
||||||
|
((hm = load_advapi32()) == NULL))
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
if ((s_pLsaRemoveAccountRights = (LsaRemoveAccountRightsType)get_proc_address(hm, "LsaRemoveAccountRights")) == NULL)
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_pLsaRemoveAccountRights(lsa_h, psid, all_rights, rights, num_rights);
|
||||||
|
}
|
||||||
|
|
||||||
ULONG pRtlNtStatusToDosError(NTSTATUS status)
|
ULONG pRtlNtStatusToDosError(NTSTATUS status)
|
||||||
{
|
{
|
||||||
HMODULE hm = NULL;
|
HMODULE hm = NULL;
|
||||||
@ -173,3 +257,21 @@ ULONG pRtlNtStatusToDosError(NTSTATUS status)
|
|||||||
}
|
}
|
||||||
return pRtlNtStatusToDosError(status);
|
return pRtlNtStatusToDosError(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS pLsaClose(LSA_HANDLE lsa_h)
|
||||||
|
{
|
||||||
|
HMODULE hm = NULL;
|
||||||
|
typedef NTSTATUS(NTAPI *LsaCloseType)(LSA_HANDLE);
|
||||||
|
static LsaCloseType s_pLsaClose = NULL;
|
||||||
|
|
||||||
|
if (!s_pLsaClose) {
|
||||||
|
if ((hm = load_api_security_lsapolicy()) == NULL &&
|
||||||
|
((hm = load_advapi32()) == NULL))
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
|
||||||
|
if ((s_pLsaClose = (LsaCloseType)get_proc_address(hm, "LsaClose")) == NULL)
|
||||||
|
return STATUS_ASSERTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_pLsaClose(lsa_h);
|
||||||
|
}
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
BOOL pLogonUserExExW(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID *, PVOID *, LPDWORD, PQUOTA_LIMITS);
|
BOOL pLogonUserExExW(wchar_t *, wchar_t *, wchar_t *, DWORD, DWORD, PTOKEN_GROUPS, PHANDLE, PSID *, PVOID *, LPDWORD, PQUOTA_LIMITS);
|
||||||
BOOLEAN pTranslateNameW(LPCWSTR, EXTENDED_NAME_FORMAT, EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
|
BOOLEAN pTranslateNameW(LPCWSTR, EXTENDED_NAME_FORMAT, EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
|
||||||
NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE);
|
NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE);
|
||||||
|
NTSTATUS pLsaFreeMemory(PVOID);
|
||||||
NTSTATUS pLsaAddAccountRights(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG);
|
NTSTATUS pLsaAddAccountRights(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG);
|
||||||
ULONG pRtlNtStatusToDosError(NTSTATUS);
|
ULONG pRtlNtStatusToDosError(NTSTATUS);
|
||||||
|
NTSTATUS pLsaClose(LSA_HANDLE);
|
||||||
|
NTSTATUS pLsaRemoveAccountRights(LSA_HANDLE, PSID, BOOLEAN, PLSA_UNICODE_STRING, ULONG);
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "inc\sys\select.h"
|
#include "inc\sys\select.h"
|
||||||
#include "inc\sys\uio.h"
|
#include "inc\sys\uio.h"
|
||||||
#include "inc\sys\types.h"
|
#include "inc\sys\types.h"
|
||||||
|
#include "inc\sys\stat.h"
|
||||||
#include "inc\unistd.h"
|
#include "inc\unistd.h"
|
||||||
#include "inc\fcntl.h"
|
#include "inc\fcntl.h"
|
||||||
#include "inc\sys\un.h"
|
#include "inc\sys\un.h"
|
||||||
@ -73,6 +74,11 @@ void fd_decode_state(char*);
|
|||||||
/* __progname */
|
/* __progname */
|
||||||
char* __progname = "";
|
char* __progname = "";
|
||||||
|
|
||||||
|
/* __progdir */
|
||||||
|
char* __progdir = "";
|
||||||
|
wchar_t* __wprogdir = L"";
|
||||||
|
|
||||||
|
|
||||||
/* initializes mapping table*/
|
/* initializes mapping table*/
|
||||||
static int
|
static int
|
||||||
fd_table_initialize()
|
fd_table_initialize()
|
||||||
@ -176,41 +182,42 @@ fd_table_clear(int index)
|
|||||||
FD_CLR(index, &(fd_table.occupied));
|
FD_CLR(index, &(fd_table.occupied));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO - consolidate w32_programdir logic in here */
|
void
|
||||||
static int
|
|
||||||
init_prog_paths()
|
init_prog_paths()
|
||||||
{
|
{
|
||||||
wchar_t* wpgmptr;
|
wchar_t* wpgmptr;
|
||||||
char* pgmptr;
|
static int processed = 0;
|
||||||
|
|
||||||
if (_get_wpgmptr(&wpgmptr) != 0) {
|
if (processed)
|
||||||
errno = EOTHER;
|
return;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pgmptr = utf16_to_utf8(wpgmptr)) == NULL) {
|
if (_get_wpgmptr(&wpgmptr) != 0)
|
||||||
errno = ENOMEM;
|
fatal("unable to retrieve wpgmptr");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
__progname = strrchr(pgmptr, '\\') + 1;
|
if ((__wprogdir = _wcsdup(wpgmptr)) == NULL ||
|
||||||
*(__progname - 1) = '\0';
|
(__progdir = utf16_to_utf8(__wprogdir)) == NULL)
|
||||||
|
fatal("out of memory");
|
||||||
|
|
||||||
|
__progname = strrchr(__progdir, '\\') + 1;
|
||||||
|
/* TODO: retain trailing \ at the end of progdir* variants ? */
|
||||||
|
*(strrchr(__progdir, '\\')) = '\0';
|
||||||
|
*(wcsrchr(__wprogdir, L'\\')) = L'\0';
|
||||||
|
|
||||||
/* strip .exe off __progname */
|
/* strip .exe off __progname */
|
||||||
*(__progname + strlen(__progname) - 4) = '\0';
|
*(__progname + strlen(__progname) - 4) = '\0';
|
||||||
|
|
||||||
return 0;
|
processed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
w32posix_initialize()
|
w32posix_initialize()
|
||||||
{
|
{
|
||||||
|
init_prog_paths();
|
||||||
if ((fd_table_initialize() != 0) || (socketio_initialize() != 0))
|
if ((fd_table_initialize() != 0) || (socketio_initialize() != 0))
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
|
main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
|
||||||
if (main_thread == NULL ||
|
if (main_thread == NULL ||
|
||||||
sw_initialize() != 0 ||
|
sw_initialize() != 0 ) {
|
||||||
init_prog_paths() != 0 ) {
|
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
fatal("failed to initialize w32posix wrapper");
|
fatal("failed to initialize w32posix wrapper");
|
||||||
}
|
}
|
||||||
@ -962,6 +969,28 @@ w32_ftruncate(int fd, off_t length)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w32_fchmod(int fd, mode_t mode)
|
||||||
|
{
|
||||||
|
wchar_t *file_path;
|
||||||
|
char *file_path_utf8 = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
CHECK_FD(fd);
|
||||||
|
|
||||||
|
file_path = get_final_path_by_handle(fd_table.w32_ios[fd]->handle);
|
||||||
|
if (!file_path)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((file_path_utf8 = utf16_to_utf8(file_path)) == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = w32_chmod(file_path_utf8, mode);
|
||||||
|
cleanup:
|
||||||
|
if (file_path_utf8)
|
||||||
|
free(file_path_utf8);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
w32_fsync(int fd)
|
w32_fsync(int fd)
|
||||||
{
|
{
|
||||||
@ -1012,7 +1041,7 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
|
|||||||
|
|
||||||
/* compute total cmdline len*/
|
/* compute total cmdline len*/
|
||||||
if (add_module_path)
|
if (add_module_path)
|
||||||
cmdline_len += (DWORD)strlen(w32_programdir()) + 1 + (DWORD)strlen(cmd) + 1 + 2;
|
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(cmd) + 1 + 2;
|
||||||
else
|
else
|
||||||
cmdline_len += (DWORD)strlen(cmd) + 1 + 2;
|
cmdline_len += (DWORD)strlen(cmd) + 1 + 2;
|
||||||
|
|
||||||
@ -1032,8 +1061,8 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
|
|||||||
if (argv && argv[0])
|
if (argv && argv[0])
|
||||||
*t++ = '\"';
|
*t++ = '\"';
|
||||||
if (add_module_path) {
|
if (add_module_path) {
|
||||||
memcpy(t, w32_programdir(), strlen(w32_programdir()));
|
memcpy(t, __progdir, strlen(__progdir));
|
||||||
t += strlen(w32_programdir());
|
t += strlen(__progdir);
|
||||||
*t++ = '\\';
|
*t++ = '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
120
contrib/win32/win32compat/win32_pty.c
Normal file
120
contrib/win32/win32compat/win32_pty.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Author: Balu G <bagajjal@microsoft.com>
|
||||||
|
*
|
||||||
|
* This file contains the conpty related functions.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Debug.h"
|
||||||
|
#include "inc\fcntl.h"
|
||||||
|
#include "misc_internal.h"
|
||||||
|
|
||||||
|
// Return Value: 0 for success, -1 for failure
|
||||||
|
int
|
||||||
|
CreateConPty(const wchar_t *cmdline,
|
||||||
|
const unsigned short width,
|
||||||
|
const unsigned short height,
|
||||||
|
HANDLE const hInput,
|
||||||
|
HANDLE const hOutput,
|
||||||
|
HANDLE const tty_sighandle,
|
||||||
|
PROCESS_INFORMATION* const piPty)
|
||||||
|
{
|
||||||
|
wchar_t system32_path[PATH_MAX] = { 0, };
|
||||||
|
|
||||||
|
SetHandleInformation(tty_sighandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
|
|
||||||
|
wchar_t conhostCmdline[8191] = { 0, }; // msdn
|
||||||
|
wchar_t *cmd_fmt = L"%ls\\conhost.exe --headless --width %d --height %d --signal 0x%x -- %ls";
|
||||||
|
|
||||||
|
if (!GetSystemDirectoryW(system32_path, PATH_MAX))
|
||||||
|
fatal("unable to retrieve system32 path");
|
||||||
|
|
||||||
|
_snwprintf_s(conhostCmdline,
|
||||||
|
_countof(conhostCmdline),
|
||||||
|
_countof(conhostCmdline),
|
||||||
|
cmd_fmt,
|
||||||
|
system32_path,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
tty_sighandle,
|
||||||
|
cmdline);
|
||||||
|
|
||||||
|
STARTUPINFOW si;
|
||||||
|
memset(&si, 0, sizeof(STARTUPINFOW));
|
||||||
|
si.cb = sizeof(STARTUPINFOW);
|
||||||
|
si.hStdInput = hInput;
|
||||||
|
si.hStdOutput = hOutput;
|
||||||
|
si.hStdError = hOutput;
|
||||||
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
|
||||||
|
|
||||||
|
debug3("pty commandline: %ls", conhostCmdline);
|
||||||
|
|
||||||
|
if (0 == CreateProcessW(NULL, conhostCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, piPty)) {
|
||||||
|
debug("%s - failed to execute %ls, error:%d", __func__, conhostCmdline, GetLastError());
|
||||||
|
errno = EOTHER;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_conpty_supported()
|
||||||
|
{
|
||||||
|
/* TODO - enable this once conpty changes are validated */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exec_command_with_pty(wchar_t* cmd, STARTUPINFOW* si, PROCESS_INFORMATION* pi, int ttyfd)
|
||||||
|
{
|
||||||
|
HANDLE ttyh = (HANDLE)w32_fd_to_handle(ttyfd);
|
||||||
|
wchar_t pty_cmdline[MAX_CMD_LEN] = { 0, };
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (is_conpty_supported())
|
||||||
|
return CreateConPty(cmd, (short)si->dwXCountChars, (short)si->dwYCountChars, si->hStdInput, si->hStdOutput, ttyh, pi);
|
||||||
|
|
||||||
|
/* launch via "ssh-shellhost" -p command*/
|
||||||
|
|
||||||
|
_snwprintf_s(pty_cmdline, MAX_CMD_LEN, MAX_CMD_LEN, L"\"%ls\\ssh-shellhost.exe\" ---pty %ls", __wprogdir, cmd);
|
||||||
|
/*
|
||||||
|
* In PTY mode, ssh-shellhost takes stderr as control channel
|
||||||
|
* TODO - fix this and pass control channel pipe as a command line parameter
|
||||||
|
*/
|
||||||
|
si->hStdError = ttyh;
|
||||||
|
debug3("pty commandline: %ls", pty_cmdline);
|
||||||
|
|
||||||
|
if (!CreateProcessW(NULL, pty_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, si, pi)) {
|
||||||
|
debug("%s - failed to execute %ls, error:%d", __func__, pty_cmdline, GetLastError());
|
||||||
|
errno = EOTHER;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
@ -6,23 +6,34 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include "..\..\..\sshpty.h"
|
#include "..\..\..\sshpty.h"
|
||||||
|
#include "inc\unistd.h"
|
||||||
|
#include "misc_internal.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows versions of pty_*. Some of them are NO-OPs and should go
|
* Windows versions of pty_*. Some of them are NO-OPs and should go
|
||||||
* away when pty logic is refactored and abstracted out
|
* away when pty logic is refactored and abstracted out
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocates a control channel for Windows PTY
|
||||||
|
* ptyfd can be used to deliver Window size change events
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
||||||
{
|
{
|
||||||
/*
|
int p[2];
|
||||||
* Simple console screen implementation in Win32 to give a
|
|
||||||
* Unix like pty for interactive sessions
|
|
||||||
*/
|
|
||||||
*ttyfd = 0;
|
*ttyfd = 0;
|
||||||
*ptyfd = 0;
|
*ptyfd = 0;
|
||||||
strlcpy(namebuf, "console", namebuflen);
|
if (w32_pipe(p) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* enable blocking mode io*/
|
||||||
|
unset_nonblock(p[0]);
|
||||||
|
unset_nonblock(p[1]);
|
||||||
|
*ttyfd = p[0];
|
||||||
|
*ptyfd = p[1];
|
||||||
|
strlcpy(namebuf, "windows-pty", namebuflen);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +49,15 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
pty_change_window_size(int ptyfd, u_int row, u_int col,
|
pty_change_window_size(int ptyfd, u_int row, u_int col,
|
||||||
u_int xpixel, u_int ypixel) {
|
u_int xpixel, u_int ypixel)
|
||||||
/* TODO - Need to implement*/
|
{
|
||||||
|
unsigned short signalPacket[3];
|
||||||
|
signalPacket[0] = PTY_SIGNAL_RESIZE_WINDOW;
|
||||||
|
signalPacket[1] = col;
|
||||||
|
signalPacket[2] = row;
|
||||||
|
// TODO - xpixel, ypixel
|
||||||
|
|
||||||
|
w32_write(ptyfd, signalPacket, sizeof(signalPacket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ generate_s4u_user_token(wchar_t* user_cpn, int impersonation) {
|
|||||||
|
|
||||||
/* lookup the user principal name for the account */
|
/* lookup the user principal name for the account */
|
||||||
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
||||||
|
|
||||||
if (lookup_principal_name(user_cpn, domain_upn) != 0) {
|
if (lookup_principal_name(user_cpn, domain_upn) != 0) {
|
||||||
/* failure - fallback to NetBiosDomain\SamAccountName */
|
/* failure - fallback to NetBiosDomain\SamAccountName */
|
||||||
wcscpy_s(domain_upn, ARRAYSIZE(domain_upn), user_cpn);
|
wcscpy_s(domain_upn, ARRAYSIZE(domain_upn), user_cpn);
|
||||||
@ -488,7 +489,7 @@ add_sid_mapping_to_lsa(PUNICODE_STRING domain_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p_output) {
|
if (p_output) {
|
||||||
status = LsaFreeMemory(p_output);
|
status = pLsaFreeMemory(p_output);
|
||||||
if (status != STATUS_SUCCESS)
|
if (status != STATUS_SUCCESS)
|
||||||
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
||||||
}
|
}
|
||||||
@ -517,7 +518,7 @@ int remove_virtual_account_lsa_mapping(PUNICODE_STRING domain_name,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
if (p_output) {
|
if (p_output) {
|
||||||
status = LsaFreeMemory(p_output);
|
status = pLsaFreeMemory(p_output);
|
||||||
if (status != STATUS_SUCCESS)
|
if (status != STATUS_SUCCESS)
|
||||||
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
||||||
}
|
}
|
||||||
@ -623,7 +624,7 @@ HANDLE generate_sshd_virtual_token()
|
|||||||
|
|
||||||
/* assign service logon privilege to virtual account */
|
/* assign service logon privilege to virtual account */
|
||||||
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
||||||
if ((lsa_ret = LsaOpenPolicy(NULL, &ObjectAttributes,
|
if ((lsa_ret = pLsaOpenPolicy(NULL, &ObjectAttributes,
|
||||||
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
||||||
&lsa_policy)) != STATUS_SUCCESS) {
|
&lsa_policy)) != STATUS_SUCCESS) {
|
||||||
error("%s: unable to open policy handle, error: %d",
|
error("%s: unable to open policy handle, error: %d",
|
||||||
@ -632,7 +633,7 @@ HANDLE generate_sshd_virtual_token()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* alter security to allow policy to account to logon as a service */
|
/* alter security to allow policy to account to logon as a service */
|
||||||
if ((lsa_add_ret = LsaAddAccountRights(lsa_policy, sid_user, &svcLogonRight, 1)) != STATUS_SUCCESS) {
|
if ((lsa_add_ret = pLsaAddAccountRights(lsa_policy, sid_user, &svcLogonRight, 1)) != STATUS_SUCCESS) {
|
||||||
error("%s: unable to assign SE_SERVICE_LOGON_NAME privilege, error: %d",
|
error("%s: unable to assign SE_SERVICE_LOGON_NAME privilege, error: %d",
|
||||||
__FUNCTION__, (ULONG)pRtlNtStatusToDosError(lsa_add_ret));
|
__FUNCTION__, (ULONG)pRtlNtStatusToDosError(lsa_add_ret));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -656,7 +657,7 @@ cleanup:
|
|||||||
|
|
||||||
/* attempt to remove virtual account permissions if previous add succeeded */
|
/* attempt to remove virtual account permissions if previous add succeeded */
|
||||||
if (lsa_add_ret == STATUS_SUCCESS)
|
if (lsa_add_ret == STATUS_SUCCESS)
|
||||||
if ((lsa_ret = LsaRemoveAccountRights(lsa_policy, sid_user, FALSE, &svcLogonRight, 1)) != STATUS_SUCCESS)
|
if ((lsa_ret = pLsaRemoveAccountRights(lsa_policy, sid_user, FALSE, &svcLogonRight, 1)) != STATUS_SUCCESS)
|
||||||
debug("%s: unable to remove SE_SERVICE_LOGON_NAME privilege, error: %d", __FUNCTION__, pRtlNtStatusToDosError(lsa_ret));
|
debug("%s: unable to remove SE_SERVICE_LOGON_NAME privilege, error: %d", __FUNCTION__, pRtlNtStatusToDosError(lsa_ret));
|
||||||
|
|
||||||
if (sid_domain)
|
if (sid_domain)
|
||||||
@ -666,7 +667,7 @@ cleanup:
|
|||||||
if (sid_group)
|
if (sid_group)
|
||||||
FreeSid(sid_group);
|
FreeSid(sid_group);
|
||||||
if (lsa_policy)
|
if (lsa_policy)
|
||||||
LsaClose(lsa_policy);
|
pLsaClose(lsa_policy);
|
||||||
|
|
||||||
return va_token_restricted;
|
return va_token_restricted;
|
||||||
}
|
}
|
||||||
@ -709,6 +710,24 @@ get_custom_lsa_package()
|
|||||||
return s_lsa_auth_pkg;
|
return s_lsa_auth_pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not thread safe
|
||||||
|
* returned value is pointer from static buffer
|
||||||
|
* dont free()
|
||||||
|
*/
|
||||||
|
wchar_t* get_final_path_by_handle(HANDLE h)
|
||||||
|
{
|
||||||
|
static wchar_t path_buf[PATH_MAX];
|
||||||
|
|
||||||
|
if (GetFinalPathNameByHandleW(h, path_buf, PATH_MAX, 0) == 0) {
|
||||||
|
errno = EOTHER;
|
||||||
|
debug3("failed to get final path of file with handle:%d error:%d", h, GetLastError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (path_buf + 4);
|
||||||
|
}
|
||||||
|
|
||||||
/* using the netbiosname\samaccountname as an input, lookup the upn for the user.
|
/* using the netbiosname\samaccountname as an input, lookup the upn for the user.
|
||||||
* if no explicit upn is defined, implicit upn is returned (samaccountname@fqdn) */
|
* if no explicit upn is defined, implicit upn is returned (samaccountname@fqdn) */
|
||||||
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name)
|
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name)
|
||||||
|
@ -189,7 +189,7 @@ create_prgdata_ssh_folder()
|
|||||||
wcscat_s(sshd_config_path, _countof(sshd_config_path), L"\\sshd_config");
|
wcscat_s(sshd_config_path, _countof(sshd_config_path), L"\\sshd_config");
|
||||||
if (GetFileAttributesW(sshd_config_path) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesW(sshd_config_path) == INVALID_FILE_ATTRIBUTES) {
|
||||||
wchar_t sshd_config_default_path[PATH_MAX] = { 0, };
|
wchar_t sshd_config_default_path[PATH_MAX] = { 0, };
|
||||||
swprintf_s(sshd_config_default_path, PATH_MAX, L"%S\\%s", w32_programdir(), L"sshd_config_default");
|
swprintf_s(sshd_config_default_path, PATH_MAX, L"%S\\%s", __progdir, L"sshd_config_default");
|
||||||
|
|
||||||
if (CopyFileW(sshd_config_default_path, sshd_config_path, TRUE) == 0) {
|
if (CopyFileW(sshd_config_default_path, sshd_config_path, TRUE) == 0) {
|
||||||
printf("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
|
printf("Failed to copy %s to %s, error:%d", sshd_config_default_path, sshd_config_path, GetLastError());
|
||||||
@ -264,11 +264,9 @@ int wmain(int argc, wchar_t **wargv) {
|
|||||||
argc_original = argc;
|
argc_original = argc;
|
||||||
wargv_original = wargv;
|
wargv_original = wargv;
|
||||||
|
|
||||||
|
init_prog_paths();
|
||||||
/* change current directory to sshd.exe root */
|
/* change current directory to sshd.exe root */
|
||||||
if ( (path_utf16 = utf8_to_utf16(w32_programdir())) == NULL)
|
_wchdir(__wprogdir);
|
||||||
return -1;
|
|
||||||
_wchdir(path_utf16);
|
|
||||||
free(path_utf16);
|
|
||||||
|
|
||||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||||
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
|
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
|
||||||
|
@ -524,11 +524,6 @@ int
|
|||||||
hostfile_replace_entries(const char *filename, const char *host, const char *ip,
|
hostfile_replace_entries(const char *filename, const char *host, const char *ip,
|
||||||
struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg)
|
struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS
|
|
||||||
error("replacing host file entries is not supported in Windows yet");
|
|
||||||
errno = ENOTSUP;
|
|
||||||
return -1;
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
int r, fd, oerrno = 0;
|
int r, fd, oerrno = 0;
|
||||||
int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
|
int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
|
||||||
struct host_delete_ctx ctx;
|
struct host_delete_ctx ctx;
|
||||||
@ -643,7 +638,6 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
|
|||||||
if (r == SSH_ERR_SYSTEM_ERROR)
|
if (r == SSH_ERR_SYSTEM_ERROR)
|
||||||
errno = oerrno;
|
errno = oerrno;
|
||||||
return r;
|
return r;
|
||||||
#endif /* !WINDOWS */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -295,6 +295,30 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context "$tC ssh-keygen known_hosts operations" {
|
||||||
|
|
||||||
|
BeforeAll {$tI=1}
|
||||||
|
AfterAll{$tC++}
|
||||||
|
|
||||||
|
It "$tC.$tI - list and delete host key thumbprints" {
|
||||||
|
$kh = Join-Path $testDir "$tC.$tI.known_hosts"
|
||||||
|
$entry = "[localhost]:47002 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMtJMxwn+iJU0X4+EC7PSj/cfcMbdP6ahhodtXx+6RHv sshtest_hostkey_ed25519"
|
||||||
|
$entry | Set-Content $kh
|
||||||
|
$o = ssh-keygen -F [localhost]:47002 -f $kh
|
||||||
|
$o.Count | Should Be 2
|
||||||
|
$o[1] | Should Be $entry
|
||||||
|
|
||||||
|
$o = ssh-keygen -H -F [localhost]:47002 -f $kh
|
||||||
|
$o.StartsWith("|1|") | Should Be $true
|
||||||
|
|
||||||
|
$o = ssh-keygen -R [localhost]:47002 -f $kh
|
||||||
|
$o.count | Should Be 3
|
||||||
|
$o[0] | Should Be "# Host [localhost]:47002 found: line 1"
|
||||||
|
(dir $kh).Length | Should Be 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Context "$tC-ssh-add key files with different file perms" {
|
Context "$tC-ssh-add key files with different file perms" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$keyFileName = "sshadd_userPermTestkey_ed25519"
|
$keyFileName = "sshadd_userPermTestkey_ed25519"
|
||||||
|
@ -81,14 +81,16 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
param
|
param
|
||||||
(
|
(
|
||||||
[string] $default_shell_path,
|
[string] $default_shell_path,
|
||||||
[string] $default_shell_cmd_option_val
|
[string] $default_shell_cmd_option_val = $null
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!(Test-Path $dfltShellRegPath)) {
|
if (!(Test-Path $dfltShellRegPath)) {
|
||||||
New-Item -Path $dfltShellRegPath -Force | Out-Null
|
New-Item -Path $dfltShellRegPath -Force | Out-Null
|
||||||
}
|
}
|
||||||
New-ItemProperty -Path $dfltShellRegPath -Name $dfltShellRegKeyName -Value $default_shell_path -PropertyType String -Force
|
New-ItemProperty -Path $dfltShellRegPath -Name $dfltShellRegKeyName -Value $default_shell_path -PropertyType String -Force
|
||||||
New-ItemProperty -Path $dfltShellRegPath -Name $dfltShellCmdOptionRegKeyName -Value $default_shell_cmd_option_val -PropertyType String -Force
|
if ($default_shell_cmd_option_val -ne $null) {
|
||||||
|
New-ItemProperty -Path $dfltShellRegPath -Name $dfltShellCmdOptionRegKeyName -Value $default_shell_cmd_option_val -PropertyType String -Force
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +150,12 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "$tC.$tI - multiple double quotes in cmdline" {
|
||||||
|
# actual command line ssh target \"cmd\" /c \"echo hello\"
|
||||||
|
$o = ssh test_target `\`"cmd`\`" /c `\`"echo hello`\`"
|
||||||
|
$o | Should Be "hello"
|
||||||
|
}
|
||||||
|
|
||||||
It "$tC.$tI - stdin from PS object" -skip:$skip {
|
It "$tC.$tI - stdin from PS object" -skip:$skip {
|
||||||
# execute this script that dumps the length of input data, on the remote end
|
# execute this script that dumps the length of input data, on the remote end
|
||||||
$str = "begin {} process { Write-Output `$input.Length} end { }"
|
$str = "begin {} process { Write-Output `$input.Length} end { }"
|
||||||
@ -211,6 +219,14 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
$o | Should Contain "cmd"
|
$o | Should Contain "cmd"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "$tC.$tI - shellhost as default shell and multiple double quotes in cmdline" {
|
||||||
|
# actual command line ssh target \"cmd\" /c \"echo hello\"
|
||||||
|
$shell_path = (Get-Command ssh-shellhost -ErrorAction SilentlyContinue).path
|
||||||
|
ConfigureDefaultShell -default_shell_path $shell_path
|
||||||
|
$o = ssh test_target `\`"cmd`\`" /c `\`"echo hello`\`"
|
||||||
|
$o | Should Be "hello"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "$tC - cmdline parameters" {
|
Context "$tC - cmdline parameters" {
|
||||||
@ -271,105 +287,15 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
$logFile | Should Contain "[::1]"
|
$logFile | Should Contain "[::1]"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
It "$tC.$tI - auto populate known hosts" {
|
||||||
|
|
||||||
|
$kh = Join-Path $testDir "$tC.$tI.known_hosts"
|
||||||
<#Context "Key is not secured in ssh-agent on server" {
|
$nul | Set-Content $kh
|
||||||
BeforeAll {
|
# doing via cmd to intercept and drain stderr output
|
||||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
iex "cmd /c `"ssh -o UserKnownHostsFile=`"$kh`" -o StrictHostKeyChecking=no test_target hostname 2>&1`""
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
(Get-Content $kh).Count | Should Be 1
|
||||||
}
|
|
||||||
|
|
||||||
AfterEach {
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
It '<Title>' -TestCases:$testData1 {
|
|
||||||
param([string]$Title, $LogonStr, $Options, $SkipVerification = $false)
|
|
||||||
|
|
||||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\ssh $($Options) $($LogonStr) hostname > $filePath")
|
|
||||||
$client.RunCmd($str)
|
|
||||||
#validate file content.
|
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "Key is secured in ssh-agent" {
|
|
||||||
BeforeAll {
|
|
||||||
$server.SecureHostKeys($server.PrivateHostKeyPaths)
|
|
||||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterAll {
|
|
||||||
$Server.CleanupHostKeys()
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterEach {
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
It '<Title>' -TestCases:$testData1 {
|
|
||||||
param([string]$Title, $LogonStr, $Options, $SkipVerification = $false)
|
|
||||||
|
|
||||||
$str = $ExecutionContext.InvokeCommand.ExpandString(".\ssh $Options $LogonStr hostname > $filePath")
|
|
||||||
$client.RunCmd($str)
|
|
||||||
#validate file content.
|
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context "Single signon on client and keys secured in ssh-agent on server" {
|
|
||||||
BeforeAll {
|
|
||||||
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
|
|
||||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
|
||||||
#setup single signon
|
|
||||||
.\ssh-add.exe $identifyFile
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterAll {
|
|
||||||
$Server.CleanupHostKeys()
|
|
||||||
|
|
||||||
#cleanup single signon
|
|
||||||
.\ssh-add.exe -D
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterEach {
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
It '<Title>' -TestCases:$testData {
|
|
||||||
param([string]$Title, $LogonStr, $Options)
|
|
||||||
|
|
||||||
$str = ".\ssh $($Options) $($LogonStr) hostname > $filePath"
|
|
||||||
$client.RunCmd($str)
|
|
||||||
#validate file content.
|
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context "password authentication" {
|
|
||||||
BeforeAll {
|
|
||||||
$client.AddPasswordSetting($server.localAdminPassword)
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterAll {
|
|
||||||
$client.CleanupPasswordSetting()
|
|
||||||
}
|
|
||||||
|
|
||||||
AfterEach {
|
|
||||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
|
||||||
}
|
|
||||||
|
|
||||||
It '<Title>' -TestCases:$testData {
|
|
||||||
param([string]$Title, $LogonStr, $Options)
|
|
||||||
|
|
||||||
$str = ".\ssh $($Options) $($LogonStr) hostname > $filePath"
|
|
||||||
$client.RunCmd($str)
|
|
||||||
#validate file content.
|
|
||||||
Get-Content $filePath | Should be $server.MachineName
|
|
||||||
}
|
|
||||||
}#>
|
|
||||||
}
|
}
|
||||||
|
42
regress/pesterTests/ShellHost.Tests.ps1
Normal file
42
regress/pesterTests/ShellHost.Tests.ps1
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
$tC = 1
|
||||||
|
$tI = 0
|
||||||
|
$suite = "shellhost"
|
||||||
|
|
||||||
|
Describe "E2E scenarios for ssh-shellhost" -Tags "CI" {
|
||||||
|
BeforeAll {
|
||||||
|
}
|
||||||
|
|
||||||
|
BeforeEach {
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterEach {$tI++;}
|
||||||
|
|
||||||
|
Context "$tC - shellhost commandline scenarios" {
|
||||||
|
BeforeAll {$tI=1}
|
||||||
|
AfterAll{$tC++}
|
||||||
|
|
||||||
|
It "$tC.$tI - exit code tests" -skip:$skip {
|
||||||
|
foreach ($i in (0,1,4,5,44)) {
|
||||||
|
ssh-shellhost -c cmd /c exit $i
|
||||||
|
$LASTEXITCODE | Should Be $i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
It "$tC.$tI - various quote tests" -skip:$skip {
|
||||||
|
$o = ssh-shellhost -c cmd /c echo hello
|
||||||
|
$o | Should Be "hello"
|
||||||
|
$o = ssh-shellhost -c `"cmd /c echo hello`"
|
||||||
|
$o | Should Be "hello"
|
||||||
|
$o = ssh-shellhost -c cmd /c echo `"hello`"
|
||||||
|
$o | Should Be "`"hello`""
|
||||||
|
$o = ssh-shellhost -c `"cmd /c echo `"hello`"`"
|
||||||
|
$o | Should Be "`"hello`""
|
||||||
|
$o = ssh-shellhost -c `"cmd /c echo `"hello`"
|
||||||
|
$o | Should Be "`"hello"
|
||||||
|
$o = ssh-shellhost -c `"`"cmd`" /c echo `"hello`"`"
|
||||||
|
$o | Should Be "`"hello`""
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -64,7 +64,7 @@ test_sanitizedpath()
|
|||||||
{
|
{
|
||||||
TEST_START("win32 program dir");
|
TEST_START("win32 program dir");
|
||||||
|
|
||||||
char *win32prgdir_utf8 = w32_programdir();
|
char *win32prgdir_utf8 = __progdir;
|
||||||
ASSERT_PTR_NE(win32prgdir_utf8, NULL);
|
ASSERT_PTR_NE(win32prgdir_utf8, NULL);
|
||||||
|
|
||||||
ASSERT_PTR_EQ(resolved_path_utf16(NULL), NULL);
|
ASSERT_PTR_EQ(resolved_path_utf16(NULL), NULL);
|
||||||
@ -314,126 +314,92 @@ test_chroot()
|
|||||||
void
|
void
|
||||||
test_build_session_commandline()
|
test_build_session_commandline()
|
||||||
{
|
{
|
||||||
char *progdir = w32_programdir(), *out, buf[PATH_MAX*2], shellhost_path[PATH_MAX];
|
char *progdir = __progdir, *out, buf[PATH_MAX * 2];
|
||||||
shellhost_path[0] = '\0';
|
|
||||||
strcat(shellhost_path, "\"");
|
|
||||||
strcat(shellhost_path, progdir);
|
|
||||||
strcat(shellhost_path, "\\ssh-shellhost.exe\"");
|
|
||||||
int shellhost_path_len = (int)strlen(shellhost_path);
|
|
||||||
|
|
||||||
TEST_START("default interactive session tests");
|
TEST_START("default interactive session tests");
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, NULL, 0);
|
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, NULL);
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\system32\\cmd.exe\"");
|
ASSERT_STRING_EQ(out, "\"c:\\system32\\cmd.exe\"");
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, NULL, 1);
|
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\system32\\cmd.exe\"");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
TEST_DONE();
|
TEST_DONE();
|
||||||
|
|
||||||
TEST_START("cmd shell tests");
|
TEST_START("cmd shell tests");
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
strcat(buf, "\"c:\\system32\\cmd.exe\" /c \"");
|
strcat(buf, "\"c:\\system32\\cmd.exe\" /c \"\"");
|
||||||
strcat(buf, progdir);
|
strcat(buf, progdir);
|
||||||
int len_pg = strlen(buf);
|
int len_pg = strlen(buf);
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "internal-sftp -arg", 0);
|
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "internal-sftp -arg");
|
||||||
buf[len_pg] = '\0';
|
buf[len_pg] = '\0';
|
||||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||||
ASSERT_STRING_EQ(out, buf);
|
ASSERT_STRING_EQ(out, buf);
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "SFTP-server.exe -arg", 0);
|
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "SFTP-server.exe -arg");
|
||||||
buf[len_pg] = '\0';
|
buf[len_pg] = '\0';
|
||||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||||
ASSERT_STRING_EQ(out, buf);
|
ASSERT_STRING_EQ(out, buf);
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sftp-SERVER -arg", 0);
|
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sftp-SERVER -arg");
|
||||||
buf[len_pg] = '\0';
|
buf[len_pg] = '\0';
|
||||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||||
ASSERT_STRING_EQ(out, buf);
|
ASSERT_STRING_EQ(out, buf);
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sCp -arg", 0);
|
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sCp -arg");
|
||||||
buf[len_pg] = '\0';
|
buf[len_pg] = '\0';
|
||||||
strcat(buf, "\\scp.exe\" -arg");
|
strcat(buf, "\\scp.exe\" -arg\"");
|
||||||
ASSERT_STRING_EQ(out, buf);
|
ASSERT_STRING_EQ(out, buf);
|
||||||
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "mycommand -arg", 1);
|
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\system32\\cmd.exe\" /c mycommand -arg");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
free(out);
|
free(out);
|
||||||
|
|
||||||
TEST_DONE();
|
TEST_DONE();
|
||||||
|
|
||||||
TEST_START("bash shell tests");
|
TEST_START("bash shell tests");
|
||||||
out = build_session_commandline("c:\\system32\\bash.exe", NULL, "internal-sftp -arg", 0);
|
out = build_session_commandline("c:\\system32\\bash.exe", NULL, "internal-sftp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash.exe\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash.exe\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\system32\\bash", NULL, "internal-sftp -arg", 0);
|
out = build_session_commandline("c:\\system32\\bash", NULL, "internal-sftp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\system32\\bash", NULL, "sFTP-server -arg", 0);
|
out = build_session_commandline("c:\\system32\\bash", NULL, "sFTP-server -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\system32\\bash", NULL, "scP -arg", 0);
|
out = build_session_commandline("c:\\system32\\bash", NULL, "scP -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"scp.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"scp.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\bash", "-custom", "mycommand -arg", 1);
|
out = build_session_commandline("c:\\cygwin\\bash.exe", NULL, "internal-sftp -arg");
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\bash\" -custom \"mycommand -arg\"");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
free(out);
|
|
||||||
out = build_session_commandline("c:\\cygwin\\bash.exe", NULL, "internal-sftp -arg", 0);
|
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash.exe\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash.exe\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sftp-server -arg", 0);
|
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sftp-server -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sftp-seRVer.exe -arg", 0);
|
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sftp-seRVer.exe -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"sftp-server.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sCp -arg", 0);
|
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sCp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"scp.exe -arg\"");
|
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"scp.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\cygwin\\bash", "-custom", "mycommand -arg", 1);
|
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\cygwin\\bash\" -custom \"mycommand -arg\"");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
free(out);
|
|
||||||
TEST_DONE();
|
TEST_DONE();
|
||||||
|
|
||||||
TEST_START("powershell shell tests");
|
TEST_START("powershell shell tests");
|
||||||
out = build_session_commandline("c:\\powershell.exe", NULL, "internal-sftp -arg", 0);
|
out = build_session_commandline("c:\\powershell.exe", NULL, "internal-sftp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\powershell", NULL, "sftp-server -arg", 0);
|
out = build_session_commandline("c:\\powershell", NULL, "sftp-server -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\powershell\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\powershell\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\powershell.exe", NULL, "sftp-sERver.exe -arg", 0);
|
out = build_session_commandline("c:\\powershell.exe", NULL, "sftp-sERver.exe -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\powershell.exe", NULL, "scP -arg", 0);
|
out = build_session_commandline("c:\\powershell.exe", NULL, "scP -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c scp.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"scp.exe -arg\"");
|
||||||
free(out);
|
|
||||||
out = build_session_commandline("c:\\powershell.exe", "-custom", "mycommand -arg", 1);
|
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\powershell.exe\" -custom mycommand -arg");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
free(out);
|
free(out);
|
||||||
TEST_DONE();
|
TEST_DONE();
|
||||||
|
|
||||||
|
|
||||||
TEST_START("other shell tests");
|
TEST_START("other shell tests");
|
||||||
out = build_session_commandline("c:\\myshell.exe", NULL, "internal-sftp -arg", 0);
|
out = build_session_commandline("c:\\myshell.exe", NULL, "internal-sftp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\myshell.exe\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\myshell.exe\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-server -arg", 0);
|
out = build_session_commandline("c:\\myshell", NULL, "sftp-server -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-seRVer.exe -arg", 0);
|
out = build_session_commandline("c:\\myshell", NULL, "sftp-seRVer.exe -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c sftp-server.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"sftp-server.exe -arg\"");
|
||||||
free(out);
|
free(out);
|
||||||
out = build_session_commandline("c:\\myshell", NULL, "sCp -arg", 0);
|
out = build_session_commandline("c:\\myshell", NULL, "sCp -arg");
|
||||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c scp.exe -arg");
|
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"scp.exe -arg\"");
|
||||||
free(out);
|
|
||||||
out = build_session_commandline("c:\\myshell", "-custom", "mycommand -arg", 1);
|
|
||||||
ASSERT_STRING_EQ(out + shellhost_path_len + 1, "\"c:\\myshell\" -custom mycommand -arg");
|
|
||||||
out[shellhost_path_len] = '\0';
|
|
||||||
ASSERT_STRING_EQ(out, shellhost_path);
|
|
||||||
free(out);
|
free(out);
|
||||||
TEST_DONE();
|
TEST_DONE();
|
||||||
}
|
}
|
||||||
|
34
session.c
34
session.c
@ -537,7 +537,7 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int register_child(void* child, unsigned long pid);
|
int register_child(void* child, unsigned long pid);
|
||||||
char* build_session_commandline(const char *, const char *, const char *, int);
|
char* build_session_commandline(const char *, const char *, const char *);
|
||||||
|
|
||||||
int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
||||||
int pipein[2], pipeout[2], pipeerr[2], r, ret = -1;
|
int pipein[2], pipeout[2], pipeerr[2], r, ret = -1;
|
||||||
@ -582,7 +582,7 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
|||||||
pty = 0;
|
pty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_command = build_session_commandline(s->pw->pw_shell, shell_command_option, command, pty);
|
exec_command = build_session_commandline(s->pw->pw_shell, shell_command_option, command);
|
||||||
if (exec_command == NULL)
|
if (exec_command == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -606,11 +606,18 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
|||||||
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
||||||
si.lpDesktop = NULL;
|
si.lpDesktop = NULL;
|
||||||
|
|
||||||
debug("Executing command: %s", exec_command);
|
|
||||||
if ((exec_command_w = utf8_to_utf16(exec_command)) == NULL)
|
if ((exec_command_w = utf8_to_utf16(exec_command)) == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (!CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
|
debug("Executing command: %s with%spty", exec_command, pty? " ":" no ");
|
||||||
|
|
||||||
|
if (pty) {
|
||||||
|
fcntl(s->ptyfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
if (exec_command_with_pty(exec_command_w, &si, &pi, s->ttyfd) == -1)
|
||||||
|
goto cleanup;
|
||||||
|
close(s->ttyfd);
|
||||||
|
s->ttyfd = -1;
|
||||||
|
} else if (!CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
|
||||||
errno = EOTHER;
|
errno = EOTHER;
|
||||||
error("ERROR. Cannot create process (%u).\n", GetLastError());
|
error("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -641,12 +648,6 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
|||||||
register_child(pi.hProcess, pi.dwProcessId);
|
register_child(pi.hProcess, pi.dwProcessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set interactive/non-interactive mode.
|
|
||||||
*/
|
|
||||||
packet_set_interactive(s->display != NULL, options.ip_qos_interactive,
|
|
||||||
options.ip_qos_bulk);
|
|
||||||
|
|
||||||
/* Close the child sides of the socket pairs. */
|
/* Close the child sides of the socket pairs. */
|
||||||
close(pipein[0]);
|
close(pipein[0]);
|
||||||
close(pipeout[1]);
|
close(pipeout[1]);
|
||||||
@ -656,10 +657,17 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) {
|
|||||||
* Enter the interactive session. Note: server_loop must be able to
|
* Enter the interactive session. Note: server_loop must be able to
|
||||||
* handle the case that fdin and fdout are the same.
|
* handle the case that fdin and fdout are the same.
|
||||||
*/
|
*/
|
||||||
if (s->ttyfd == -1)
|
if (pty) {
|
||||||
|
/* Set interactive/non-interactive mode */
|
||||||
|
packet_set_interactive(1, options.ip_qos_interactive,
|
||||||
|
options.ip_qos_bulk);
|
||||||
|
session_set_fds(ssh, s, pipein[1], pipeout[0], -1, 1, 1);
|
||||||
|
} else {
|
||||||
|
/* Set interactive/non-interactive mode */
|
||||||
|
packet_set_interactive(s->display != NULL, options.ip_qos_interactive,
|
||||||
|
options.ip_qos_bulk);
|
||||||
session_set_fds(ssh, s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
|
session_set_fds(ssh, s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0);
|
||||||
else
|
}
|
||||||
session_set_fds(ssh, s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); /* tty interactive session */
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
35
ssh-keygen.c
35
ssh-keygen.c
@ -1053,19 +1053,12 @@ do_gen_all_hostkeys(struct passwd *pw)
|
|||||||
pub_tmp, strerror(errno));
|
pub_tmp, strerror(errno));
|
||||||
goto failnext;
|
goto failnext;
|
||||||
}
|
}
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
|
||||||
close(fd);
|
|
||||||
chmod(pub_tmp, 0644);
|
|
||||||
if ((f = fopen(pub_tmp, "w")) == NULL) {
|
|
||||||
error("fopen %s failed: %s", pub_tmp, strerror(errno));
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
(void)fchmod(fd, 0644);
|
(void)fchmod(fd, 0644);
|
||||||
f = fdopen(fd, "w");
|
f = fdopen(fd, "w");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
|
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
#endif /* !WINDOWS */
|
|
||||||
sshkey_free(public);
|
sshkey_free(public);
|
||||||
first = 0;
|
first = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -1232,10 +1225,6 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
|
|||||||
static void
|
static void
|
||||||
do_known_hosts(struct passwd *pw, const char *name)
|
do_known_hosts(struct passwd *pw, const char *name)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS
|
|
||||||
fatal("Updating known_hosts is not supported in Windows yet.");
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
|
|
||||||
char *cp, tmp[PATH_MAX], old[PATH_MAX];
|
char *cp, tmp[PATH_MAX], old[PATH_MAX];
|
||||||
int r, fd, oerrno, inplace = 0;
|
int r, fd, oerrno, inplace = 0;
|
||||||
struct known_hosts_ctx ctx;
|
struct known_hosts_ctx ctx;
|
||||||
@ -1327,7 +1316,6 @@ do_known_hosts(struct passwd *pw, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit (find_host && !ctx.found_key);
|
exit (find_host && !ctx.found_key);
|
||||||
#endif /* !WINDOWS */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1530,16 +1518,9 @@ do_change_comment(struct passwd *pw)
|
|||||||
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
fatal("Could not save your public key in %s", identity_file);
|
fatal("Could not save your public key in %s", identity_file);
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
|
||||||
close(fd);
|
|
||||||
if ((f = fopen(identity_file, "w")) == NULL)
|
|
||||||
fatal("fopen %s failed: %s", identity_file, strerror(errno));
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
f = fdopen(fd, "w");
|
f = fdopen(fd, "w");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
||||||
#endif /* !WINDOWS */
|
|
||||||
if ((r = sshkey_write(public, f)) != 0)
|
if ((r = sshkey_write(public, f)) != 0)
|
||||||
fatal("write key failed: %s", ssh_err(r));
|
fatal("write key failed: %s", ssh_err(r));
|
||||||
sshkey_free(public);
|
sshkey_free(public);
|
||||||
@ -1784,15 +1765,8 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
|
|||||||
if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
||||||
fatal("Could not open \"%s\" for writing: %s", out,
|
fatal("Could not open \"%s\" for writing: %s", out,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
|
||||||
close(fd);
|
|
||||||
if ((f = fopen(out, "w")) == NULL)
|
|
||||||
fatal("fopen %s failed: %s", identity_file, strerror(errno));
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
if ((f = fdopen(fd, "w")) == NULL)
|
if ((f = fdopen(fd, "w")) == NULL)
|
||||||
fatal("%s: fdopen: %s", __func__, strerror(errno));
|
fatal("%s: fdopen: %s", __func__, strerror(errno));
|
||||||
#endif /* !WINDOWS */
|
|
||||||
if ((r = sshkey_write(public, f)) != 0)
|
if ((r = sshkey_write(public, f)) != 0)
|
||||||
fatal("Could not write certified key to %s: %s",
|
fatal("Could not write certified key to %s: %s",
|
||||||
out, ssh_err(r));
|
out, ssh_err(r));
|
||||||
@ -2851,15 +2825,8 @@ passphrase_again:
|
|||||||
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
||||||
fatal("Unable to save public key to %s: %s",
|
fatal("Unable to save public key to %s: %s",
|
||||||
identity_file, strerror(errno));
|
identity_file, strerror(errno));
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Windows POSIX adpater does not support fdopen() on open(file)*/
|
|
||||||
close(fd);
|
|
||||||
if ((f = fopen(identity_file, "w")) == NULL)
|
|
||||||
fatal("fopen %s failed: %s", identity_file, strerror(errno));
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
if ((f = fdopen(fd, "w")) == NULL)
|
if ((f = fdopen(fd, "w")) == NULL)
|
||||||
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
||||||
#endif /* !WINDOWS */
|
|
||||||
if ((r = sshkey_write(public, f)) != 0)
|
if ((r = sshkey_write(public, f)) != 0)
|
||||||
error("write key failed: %s", ssh_err(r));
|
error("write key failed: %s", ssh_err(r));
|
||||||
fprintf(f, " %s\n", comment);
|
fprintf(f, " %s\n", comment);
|
||||||
|
4
sshd.c
4
sshd.c
@ -787,6 +787,9 @@ privsep_preauth(Authctxt *authctxt)
|
|||||||
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
|
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
|
||||||
pmonitor->m_log_sendfd = PRIVSEP_LOG_FD;
|
pmonitor->m_log_sendfd = PRIVSEP_LOG_FD;
|
||||||
|
|
||||||
|
fcntl(pmonitor->m_recvfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
fcntl(pmonitor->m_log_sendfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
/* Arrange for logging to be sent to the monitor */
|
/* Arrange for logging to be sent to the monitor */
|
||||||
set_log_handler(mm_log_handler, pmonitor);
|
set_log_handler(mm_log_handler, pmonitor);
|
||||||
|
|
||||||
@ -948,6 +951,7 @@ privsep_postauth(Authctxt *authctxt)
|
|||||||
close(pmonitor->m_recvfd);
|
close(pmonitor->m_recvfd);
|
||||||
|
|
||||||
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
|
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
|
||||||
|
fcntl(pmonitor->m_recvfd, F_SETFD, FD_CLOEXEC);
|
||||||
monitor_recv_keystate(pmonitor);
|
monitor_recv_keystate(pmonitor);
|
||||||
|
|
||||||
do_setusercontext(authctxt->pw);
|
do_setusercontext(authctxt->pw);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user