mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-29 16:54:51 +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
|
||||
{
|
||||
[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)
|
||||
{
|
||||
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\spawn.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>
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
||||
|
@ -40,11 +40,14 @@
|
||||
#include "debug.h"
|
||||
#include "console.h"
|
||||
#include "ansiprsr.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
HANDLE hOutputConsole = NULL;
|
||||
DWORD stdin_dwSavedAttributes = 0;
|
||||
DWORD stdout_dwSavedAttributes = 0;
|
||||
WORD wStartingAttributes = 0;
|
||||
unsigned int console_out_cp_saved = 0;
|
||||
unsigned int console_in_cp_saved = 0;
|
||||
|
||||
int ScreenX;
|
||||
int ScreenY;
|
||||
@ -142,8 +145,22 @@ ConEnterRawMode()
|
||||
SavedViewRect = csbi.srWindow;
|
||||
debug("console doesn't support the ansi parsing");
|
||||
} else {
|
||||
ConSaveViewRect();
|
||||
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();
|
||||
@ -160,6 +177,22 @@ ConExitRawMode()
|
||||
{
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), stdin_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 */
|
||||
@ -223,7 +256,7 @@ ConSetScreenRect(int xSize, int ySize)
|
||||
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
if (bSuccess && !is_conpty_supported())
|
||||
ConSaveViewRect();
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
if (bSuccess && !is_conpty_supported())
|
||||
ConSaveViewRect();
|
||||
|
||||
/* if the current buffer *is* the size we want, don't do anything! */
|
||||
@ -1490,7 +1523,6 @@ void
|
||||
ConSaveViewRect()
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
|
||||
SavedViewRect = csbi.srWindow;
|
||||
}
|
||||
@ -1590,7 +1622,8 @@ ConMoveCursorTopOfVisibleWindow()
|
||||
offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top;
|
||||
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.lpSecurityDescriptor = NULL;
|
||||
sec_attributes.nLength = 0;
|
||||
sec_attributes.nLength = sizeof(sec_attributes);
|
||||
|
||||
/* create named pipe */
|
||||
write_handle = CreateNamedPipeA(pipe_name,
|
||||
@ -415,18 +415,18 @@ cleanup:
|
||||
|
||||
/* returns 1 if true, 0 otherwise */
|
||||
int
|
||||
file_in_chroot_jail(HANDLE handle, const char* path_utf8) {
|
||||
file_in_chroot_jail(HANDLE handle) {
|
||||
/* ensure final path is within chroot */
|
||||
wchar_t path_buf[MAX_PATH], *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());
|
||||
wchar_t *final_path;
|
||||
|
||||
final_path = get_final_path_by_handle(handle);
|
||||
if (!final_path)
|
||||
return 0;
|
||||
}
|
||||
final_path = path_buf + 4;
|
||||
|
||||
to_wlower_case(final_path);
|
||||
if ((wcslen(final_path) < wcslen(chroot_pathw)) ||
|
||||
memcmp(final_path, chroot_pathw, 2 * wcslen(chroot_pathw)) != 0 ||
|
||||
final_path[wcslen(chroot_pathw)] != '\\') {
|
||||
memcmp(final_path, chroot_pathw, 2 * wcslen(chroot_pathw)) != 0 ||
|
||||
final_path[wcslen(chroot_pathw)] != '\\') {
|
||||
debug3("access denied due to attempt to escape chroot jail");
|
||||
return 0;
|
||||
}
|
||||
@ -478,7 +478,8 @@ fileio_open(const char *path_utf8, int flags, mode_t mode)
|
||||
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;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -776,7 +777,7 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = _open_osfhandle(dup_handle, 0);
|
||||
int fd = _open_osfhandle((intptr_t)dup_handle, 0);
|
||||
debug4("fstat - pio:%p", pio);
|
||||
if (fd == -1) {
|
||||
CloseHandle(dup_handle);
|
||||
@ -902,44 +903,41 @@ fileio_lseek(struct w32_io* pio, unsigned __int64 offset, int origin)
|
||||
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*
|
||||
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);
|
||||
|
||||
/* logic below doesn't work with overlapped file HANDLES */
|
||||
if (mode[1] == '\0') {
|
||||
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;
|
||||
}
|
||||
if ((wmode = utf8_to_utf16(mode)) == NULL)
|
||||
goto cleanup;
|
||||
|
||||
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;
|
||||
debug3("fdopen - ERROR:%d _open_osfhandle()", errno);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* close the win32 handle right away and remove entry from table
|
||||
* otherwise, wfopen will get an access denied due to sharing violation
|
||||
*/
|
||||
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
|
||||
|
@ -38,6 +38,10 @@ int w32_mkdir(const char *pathname, unsigned short mode);
|
||||
int w32_chmod(const char *, mode_t);
|
||||
#define chmod w32_chmod
|
||||
|
||||
int w32_fchmod(int fd, mode_t mode);
|
||||
#define fchmod w32_fchmod
|
||||
|
||||
|
||||
struct w32_stat {
|
||||
dev_t st_dev; /* ID of device containing file */
|
||||
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) {
|
||||
/* ensure final path is within chroot */
|
||||
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);
|
||||
f = NULL;
|
||||
errno = EACCES;
|
||||
@ -419,34 +420,6 @@ w32_setvbuf(FILE *stream, char *buffer, int mode, size_t 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
|
||||
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 */
|
||||
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 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);
|
||||
|
||||
#define CMDLINE_APPEND(P, S) \
|
||||
@ -1650,7 +1623,7 @@ do { \
|
||||
if (!command)
|
||||
break;
|
||||
command_len = (int)strlen(command);
|
||||
|
||||
/*TODO - replace numbers below with readable compile time operators*/
|
||||
if (command_len >= 13 && _memicmp(command, "internal-sftp", 13) == 0) {
|
||||
command_type = CMD_SFTP;
|
||||
command_args = command + 13;
|
||||
@ -1687,7 +1660,6 @@ do { \
|
||||
p = cmd_sp;
|
||||
|
||||
if (shell_type == SH_CMD) {
|
||||
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
CMDLINE_APPEND(p, progdir);
|
||||
|
||||
@ -1709,8 +1681,6 @@ do { \
|
||||
} while (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 */
|
||||
if (command) {
|
||||
len += 15; /* for shell command argument, typically -c or /c */
|
||||
@ -1723,11 +1693,6 @@ do { \
|
||||
}
|
||||
|
||||
p = cmdline;
|
||||
if (pty) {
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
CMDLINE_APPEND(p, progdir);
|
||||
CMDLINE_APPEND(p, "\\ssh-shellhost.exe\" ");
|
||||
}
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
CMDLINE_APPEND(p, shell);
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
@ -1742,14 +1707,10 @@ do { \
|
||||
else
|
||||
CMDLINE_APPEND(p, " -c ");
|
||||
|
||||
/* bash type shells require " decoration around command*/
|
||||
if (shell_type == SH_BASH)
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
|
||||
/* Add double quotes around command */
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
CMDLINE_APPEND(p, command);
|
||||
|
||||
if (shell_type == SH_BASH)
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
CMDLINE_APPEND(p, "\"");
|
||||
}
|
||||
*p = '\0';
|
||||
ret = cmdline;
|
||||
|
@ -25,6 +25,17 @@
|
||||
/* maximum size for user principal name as defined in ad schema */
|
||||
#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;
|
||||
|
||||
extern char* chroot_path;
|
||||
@ -35,7 +46,7 @@ extern wchar_t* chroot_pathw;
|
||||
wchar_t * resolved_path_utf16(const char *);
|
||||
void w32posix_initialize();
|
||||
void w32posix_done();
|
||||
char* w32_programdir();
|
||||
void init_prog_paths();
|
||||
void convertToBackslash(char *str);
|
||||
void convertToBackslashW(wchar_t *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 create_directory_withsddl(wchar_t *path, wchar_t *sddl);
|
||||
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*);
|
||||
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();
|
||||
wchar_t* get_final_path_by_handle(HANDLE h);
|
||||
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_ROWS 9999
|
||||
#define MAX_CMD_LEN 8191 // msdn
|
||||
#define WM_APPEXIT WM_USER+1
|
||||
#define MAX_EXPECTED_BUFFER_SIZE 1024
|
||||
/* 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 pipe_in = 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 job = NULL;
|
||||
HANDLE hConsoleBuffer = INVALID_HANDLE_VALUE;
|
||||
HANDLE monitor_thread = INVALID_HANDLE_VALUE;
|
||||
HANDLE io_thread = INVALID_HANDLE_VALUE;
|
||||
HANDLE ux_thread = INVALID_HANDLE_VALUE;
|
||||
HANDLE ctrl_thread = INVALID_HANDLE_VALUE;
|
||||
|
||||
DWORD child_exit_code = 0;
|
||||
DWORD hostProcessId = 0;
|
||||
@ -800,6 +800,48 @@ MonitorChild(_In_ LPVOID lpParameter)
|
||||
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
|
||||
ProcessEvent(void *p)
|
||||
{
|
||||
@ -1231,10 +1273,10 @@ start_with_pty(wchar_t *command)
|
||||
|
||||
pipe_in = GetStdHandle(STD_INPUT_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*/
|
||||
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;
|
||||
|
||||
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
|
||||
*/
|
||||
cmd[0] = L'\0';
|
||||
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));
|
||||
_snwprintf_s(cmd, MAX_CMD_LEN, MAX_CMD_LEN, L"\"%ls\\cmd.exe\" /c \"%ls\"", system32_path, command);
|
||||
|
||||
SetConsoleCtrlHandler(NULL, FALSE);
|
||||
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))
|
||||
goto cleanup;
|
||||
|
||||
ctrl_thread = (HANDLE)_beginthreadex(NULL, 0, ControlThread, NULL, 0, NULL);
|
||||
if (IS_INVALID_HANDLE(ctrl_thread))
|
||||
goto cleanup;
|
||||
|
||||
ProcessMessages(NULL);
|
||||
cleanup:
|
||||
dwStatus = GetLastError();
|
||||
@ -1330,6 +1373,11 @@ cleanup:
|
||||
CloseHandle(io_thread);
|
||||
}
|
||||
|
||||
if (!IS_INVALID_HANDLE(ctrl_thread)) {
|
||||
TerminateThread(ctrl_thread, 0);
|
||||
CloseHandle(ctrl_thread);
|
||||
}
|
||||
|
||||
if (hEventHook)
|
||||
__UnhookWinEvent(hEventHook);
|
||||
|
||||
@ -1349,20 +1397,99 @@ cleanup:
|
||||
return child_exit_code;
|
||||
}
|
||||
|
||||
int
|
||||
wmain(int ac, wchar_t **av)
|
||||
/* implements a basic shell - launches given cmd using CreateProcess */
|
||||
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) {
|
||||
printf("usage: shellhost.exe <cmdline to be executed with PTY support>\n");
|
||||
if (CreateProcessW(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == FALSE) {
|
||||
printf("ssh-shellhost cannot run '%ls', error: %d", cmd, GetLastError());
|
||||
exit(255);
|
||||
}
|
||||
|
||||
/* get past shellhost.exe in commandline */
|
||||
exec_command = wcsstr(GetCommandLineW(), L"shellhost.exe") + wcslen(L"shellhost.exe") + 1;
|
||||
CloseHandle(pi.hThread);
|
||||
/* 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)
|
||||
{
|
||||
debug5("SIGTERM APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGWINCH);
|
||||
sigaddset(&pending_signals, SIGWINCH);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -56,7 +56,7 @@
|
||||
#define SHIFT_TAB_KEY "\x1b[~"
|
||||
#define SHIFT_ALT_Q "\x1b?"
|
||||
#define ESCAPE_KEY "\x1b"
|
||||
#define BACKSPACE_KEY "\b"
|
||||
#define BACKSPACE_KEY "\x7f"
|
||||
|
||||
// VT100 Function Key's
|
||||
#define VT100_PF1_KEY "\x1bO2"
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "ansiprsr.h"
|
||||
#include "inc\utf.h"
|
||||
#include "console.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
#define dwBuffer 4096
|
||||
|
||||
@ -51,16 +52,17 @@ BOOL isFirstPacket = TRUE;
|
||||
* are hardcoded in the server and will be transformed to Windows Console commands.
|
||||
*/
|
||||
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 *pszHead = NULL;
|
||||
unsigned char *pszTail = NULL;
|
||||
const char *applicationModeSeq = "\x1b[?1h";
|
||||
const int applicationModeSeqLen = (int)strlen(applicationModeSeq);
|
||||
const DWORD applicationModeSeqLen = (DWORD)strlen(applicationModeSeq);
|
||||
const char *normalModeSeq = "\x1b[?1l";
|
||||
const int normalModeSeqLen = (int)strlen(normalModeSeq);
|
||||
const DWORD normalModeSeqLen = (DWORD)strlen(normalModeSeq);
|
||||
const char *clsSeq = "\x1b[2J";
|
||||
static int track_view_port = 1;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
@ -68,6 +70,10 @@ processBuffer(HANDLE handle, char *buf, size_t len, unsigned char **respbuf, siz
|
||||
if (false == isAnsiParsingRequired) {
|
||||
if(isFirstPacket) {
|
||||
isFirstPacket = FALSE;
|
||||
|
||||
if (is_conpty_supported())
|
||||
track_view_port = 0;
|
||||
|
||||
/* 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
|
||||
* 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))
|
||||
gbVTAppMode = false;
|
||||
|
||||
/* Console has the capability to parse so pass the raw buffer to console directly */
|
||||
ConRestoreViewRect(); /* Restore the visible window, otherwise WriteConsoleW() gets messy */
|
||||
wchar_t* t = utf8_to_utf16(buf);
|
||||
if (t) {
|
||||
WriteConsoleW(handle, t, (DWORD)wcslen(t), 0, 0);
|
||||
free(t);
|
||||
}
|
||||
/* WriteFile() gets messy when user does scroll up/down so we need to restore the visible window.
|
||||
* It's a conhost bug but we need to live with it as they are not going to back port the fix.
|
||||
*/
|
||||
if(track_view_port)
|
||||
ConRestoreViewRect();
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,6 @@
|
||||
|
||||
#ifndef __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
|
@ -51,7 +51,7 @@ system32_dir()
|
||||
static HMODULE
|
||||
load_module(wchar_t* name)
|
||||
{
|
||||
HMODULE hm;
|
||||
HMODULE hm = NULL;
|
||||
|
||||
/*system uses a standard search strategy to find the module */
|
||||
if ((hm = LoadLibraryW(name)) == NULL)
|
||||
@ -82,6 +82,17 @@ load_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
|
||||
load_secur32()
|
||||
{
|
||||
@ -106,6 +117,9 @@ load_ntdll()
|
||||
|
||||
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);
|
||||
if (!ret)
|
||||
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)
|
||||
{
|
||||
HMODULE hm = NULL;
|
||||
|
||||
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;
|
||||
|
||||
@ -154,10 +169,79 @@ BOOLEAN pTranslateNameW(LPCWSTR name,
|
||||
if ((s_pTranslateNameW = (TranslateNameWType)get_proc_address(hm, "TranslateNameW")) == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
HMODULE hm = NULL;
|
||||
@ -173,3 +257,21 @@ ULONG pRtlNtStatusToDosError(NTSTATUS 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);
|
||||
BOOLEAN pTranslateNameW(LPCWSTR, EXTENDED_NAME_FORMAT, EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
|
||||
NTSTATUS pLsaOpenPolicy(PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE);
|
||||
NTSTATUS pLsaFreeMemory(PVOID);
|
||||
NTSTATUS pLsaAddAccountRights(LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG);
|
||||
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\uio.h"
|
||||
#include "inc\sys\types.h"
|
||||
#include "inc\sys\stat.h"
|
||||
#include "inc\unistd.h"
|
||||
#include "inc\fcntl.h"
|
||||
#include "inc\sys\un.h"
|
||||
@ -73,6 +74,11 @@ void fd_decode_state(char*);
|
||||
/* __progname */
|
||||
char* __progname = "";
|
||||
|
||||
/* __progdir */
|
||||
char* __progdir = "";
|
||||
wchar_t* __wprogdir = L"";
|
||||
|
||||
|
||||
/* initializes mapping table*/
|
||||
static int
|
||||
fd_table_initialize()
|
||||
@ -176,41 +182,42 @@ fd_table_clear(int index)
|
||||
FD_CLR(index, &(fd_table.occupied));
|
||||
}
|
||||
|
||||
/* TODO - consolidate w32_programdir logic in here */
|
||||
static int
|
||||
void
|
||||
init_prog_paths()
|
||||
{
|
||||
wchar_t* wpgmptr;
|
||||
char* pgmptr;
|
||||
static int processed = 0;
|
||||
|
||||
if (_get_wpgmptr(&wpgmptr) != 0) {
|
||||
errno = EOTHER;
|
||||
return -1;
|
||||
}
|
||||
if (processed)
|
||||
return;
|
||||
|
||||
if ((pgmptr = utf16_to_utf8(wpgmptr)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (_get_wpgmptr(&wpgmptr) != 0)
|
||||
fatal("unable to retrieve wpgmptr");
|
||||
|
||||
__progname = strrchr(pgmptr, '\\') + 1;
|
||||
*(__progname - 1) = '\0';
|
||||
if ((__wprogdir = _wcsdup(wpgmptr)) == NULL ||
|
||||
(__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 */
|
||||
*(__progname + strlen(__progname) - 4) = '\0';
|
||||
|
||||
return 0;
|
||||
processed = 1;
|
||||
}
|
||||
|
||||
void
|
||||
w32posix_initialize()
|
||||
{
|
||||
init_prog_paths();
|
||||
if ((fd_table_initialize() != 0) || (socketio_initialize() != 0))
|
||||
DebugBreak();
|
||||
main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
|
||||
if (main_thread == NULL ||
|
||||
sw_initialize() != 0 ||
|
||||
init_prog_paths() != 0 ) {
|
||||
sw_initialize() != 0 ) {
|
||||
DebugBreak();
|
||||
fatal("failed to initialize w32posix wrapper");
|
||||
}
|
||||
@ -962,6 +969,28 @@ w32_ftruncate(int fd, off_t length)
|
||||
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
|
||||
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*/
|
||||
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
|
||||
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])
|
||||
*t++ = '\"';
|
||||
if (add_module_path) {
|
||||
memcpy(t, w32_programdir(), strlen(w32_programdir()));
|
||||
t += strlen(w32_programdir());
|
||||
memcpy(t, __progdir, strlen(__progdir));
|
||||
t += strlen(__progdir);
|
||||
*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 "..\..\..\sshpty.h"
|
||||
|
||||
#include "inc\unistd.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
/*
|
||||
* Windows versions of pty_*. Some of them are NO-OPs and should go
|
||||
* 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
|
||||
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
|
||||
{
|
||||
/*
|
||||
* Simple console screen implementation in Win32 to give a
|
||||
* Unix like pty for interactive sessions
|
||||
*/
|
||||
int p[2];
|
||||
*ttyfd = 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;
|
||||
}
|
||||
|
||||
@ -38,8 +49,15 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) {
|
||||
|
||||
void
|
||||
pty_change_window_size(int ptyfd, u_int row, u_int col,
|
||||
u_int xpixel, u_int ypixel) {
|
||||
/* TODO - Need to implement*/
|
||||
u_int xpixel, u_int ypixel)
|
||||
{
|
||||
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 */
|
||||
WCHAR domain_upn[MAX_UPN_LEN + 1];
|
||||
|
||||
if (lookup_principal_name(user_cpn, domain_upn) != 0) {
|
||||
/* failure - fallback to NetBiosDomain\SamAccountName */
|
||||
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) {
|
||||
status = LsaFreeMemory(p_output);
|
||||
status = pLsaFreeMemory(p_output);
|
||||
if (status != STATUS_SUCCESS)
|
||||
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
||||
}
|
||||
@ -517,7 +518,7 @@ int remove_virtual_account_lsa_mapping(PUNICODE_STRING domain_name,
|
||||
ret = -1;
|
||||
|
||||
if (p_output) {
|
||||
status = LsaFreeMemory(p_output);
|
||||
status = pLsaFreeMemory(p_output);
|
||||
if (status != STATUS_SUCCESS)
|
||||
debug3("LsaFreeMemory failed with ntstatus: %d", status);
|
||||
}
|
||||
@ -623,7 +624,7 @@ HANDLE generate_sshd_virtual_token()
|
||||
|
||||
/* assign service logon privilege to virtual account */
|
||||
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
||||
if ((lsa_ret = LsaOpenPolicy(NULL, &ObjectAttributes,
|
||||
if ((lsa_ret = pLsaOpenPolicy(NULL, &ObjectAttributes,
|
||||
POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
|
||||
&lsa_policy)) != STATUS_SUCCESS) {
|
||||
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 */
|
||||
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",
|
||||
__FUNCTION__, (ULONG)pRtlNtStatusToDosError(lsa_add_ret));
|
||||
goto cleanup;
|
||||
@ -656,7 +657,7 @@ cleanup:
|
||||
|
||||
/* attempt to remove virtual account permissions if previous add succeeded */
|
||||
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));
|
||||
|
||||
if (sid_domain)
|
||||
@ -666,7 +667,7 @@ cleanup:
|
||||
if (sid_group)
|
||||
FreeSid(sid_group);
|
||||
if (lsa_policy)
|
||||
LsaClose(lsa_policy);
|
||||
pLsaClose(lsa_policy);
|
||||
|
||||
return va_token_restricted;
|
||||
}
|
||||
@ -709,6 +710,24 @@ get_custom_lsa_package()
|
||||
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.
|
||||
* 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)
|
||||
|
@ -189,7 +189,7 @@ create_prgdata_ssh_folder()
|
||||
wcscat_s(sshd_config_path, _countof(sshd_config_path), L"\\sshd_config");
|
||||
if (GetFileAttributesW(sshd_config_path) == INVALID_FILE_ATTRIBUTES) {
|
||||
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) {
|
||||
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;
|
||||
wargv_original = wargv;
|
||||
|
||||
init_prog_paths();
|
||||
/* change current directory to sshd.exe root */
|
||||
if ( (path_utf16 = utf8_to_utf16(w32_programdir())) == NULL)
|
||||
return -1;
|
||||
_wchdir(path_utf16);
|
||||
free(path_utf16);
|
||||
_wchdir(__wprogdir);
|
||||
|
||||
if (!StartServiceCtrlDispatcherW(dispatch_table)) {
|
||||
if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
|
||||
|
@ -524,11 +524,6 @@ int
|
||||
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)
|
||||
{
|
||||
#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 loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
|
||||
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)
|
||||
errno = oerrno;
|
||||
return r;
|
||||
#endif /* !WINDOWS */
|
||||
}
|
||||
|
||||
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" {
|
||||
BeforeAll {
|
||||
$keyFileName = "sshadd_userPermTestkey_ed25519"
|
||||
|
@ -81,14 +81,16 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
||||
param
|
||||
(
|
||||
[string] $default_shell_path,
|
||||
[string] $default_shell_cmd_option_val
|
||||
[string] $default_shell_cmd_option_val = $null
|
||||
)
|
||||
|
||||
if (!(Test-Path $dfltShellRegPath)) {
|
||||
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 $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"
|
||||
}
|
||||
|
||||
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 {
|
||||
# execute this script that dumps the length of input data, on the remote 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"
|
||||
}
|
||||
}
|
||||
|
||||
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" {
|
||||
@ -271,105 +287,15 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
||||
$o | Should Be "1234"
|
||||
$logFile | Should Contain "[::1]"
|
||||
}
|
||||
}
|
||||
|
||||
It "$tC.$tI - auto populate known hosts" {
|
||||
|
||||
|
||||
<#Context "Key is not secured in ssh-agent on server" {
|
||||
BeforeAll {
|
||||
$identifyFile = $client.clientPrivateKeyPaths[0]
|
||||
Remove-Item -Path $filePath -Force -ea silentlycontinue
|
||||
}
|
||||
|
||||
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
|
||||
$kh = Join-Path $testDir "$tC.$tI.known_hosts"
|
||||
$nul | Set-Content $kh
|
||||
# doing via cmd to intercept and drain stderr output
|
||||
iex "cmd /c `"ssh -o UserKnownHostsFile=`"$kh`" -o StrictHostKeyChecking=no test_target hostname 2>&1`""
|
||||
(Get-Content $kh).Count | Should Be 1
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
char *win32prgdir_utf8 = w32_programdir();
|
||||
char *win32prgdir_utf8 = __progdir;
|
||||
ASSERT_PTR_NE(win32prgdir_utf8, NULL);
|
||||
|
||||
ASSERT_PTR_EQ(resolved_path_utf16(NULL), NULL);
|
||||
@ -314,126 +314,92 @@ test_chroot()
|
||||
void
|
||||
test_build_session_commandline()
|
||||
{
|
||||
char *progdir = w32_programdir(), *out, buf[PATH_MAX*2], shellhost_path[PATH_MAX];
|
||||
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);
|
||||
char *progdir = __progdir, *out, buf[PATH_MAX * 2];
|
||||
|
||||
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\"");
|
||||
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_START("cmd shell tests");
|
||||
buf[0] = '\0';
|
||||
strcat(buf, "\"c:\\system32\\cmd.exe\" /c \"");
|
||||
strcat(buf, "\"c:\\system32\\cmd.exe\" /c \"\"");
|
||||
strcat(buf, progdir);
|
||||
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';
|
||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
||||
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||
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';
|
||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
||||
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||
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';
|
||||
strcat(buf, "\\sftp-server.exe\" -arg");
|
||||
strcat(buf, "\\sftp-server.exe\" -arg\"");
|
||||
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';
|
||||
strcat(buf, "\\scp.exe\" -arg");
|
||||
strcat(buf, "\\scp.exe\" -arg\"");
|
||||
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);
|
||||
|
||||
TEST_DONE();
|
||||
|
||||
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\"");
|
||||
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\"");
|
||||
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\"");
|
||||
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\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\bash", "-custom", "mycommand -arg", 1);
|
||||
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);
|
||||
out = build_session_commandline("c:\\cygwin\\bash.exe", NULL, "internal-sftp -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash.exe\" -c \"sftp-server.exe -arg\"");
|
||||
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\"");
|
||||
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\"");
|
||||
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\"");
|
||||
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_START("powershell shell tests");
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "internal-sftp -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "internal-sftp -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\powershell", NULL, "sftp-server -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\powershell", NULL, "sftp-server -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "sftp-sERver.exe -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "sftp-sERver.exe -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "scP -arg", 0);
|
||||
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);
|
||||
out = build_session_commandline("c:\\powershell.exe", NULL, "scP -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"scp.exe -arg\"");
|
||||
free(out);
|
||||
TEST_DONE();
|
||||
|
||||
|
||||
TEST_START("other shell tests");
|
||||
out = build_session_commandline("c:\\myshell.exe", NULL, "internal-sftp -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell.exe\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\myshell.exe", NULL, "internal-sftp -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell.exe\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-server -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-server -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-seRVer.exe -arg", 0);
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c sftp-server.exe -arg");
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sftp-seRVer.exe -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"sftp-server.exe -arg\"");
|
||||
free(out);
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sCp -arg", 0);
|
||||
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);
|
||||
out = build_session_commandline("c:\\myshell", NULL, "sCp -arg");
|
||||
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"scp.exe -arg\"");
|
||||
free(out);
|
||||
TEST_DONE();
|
||||
}
|
||||
|
34
session.c
34
session.c
@ -537,7 +537,7 @@ cleanup:
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
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)
|
||||
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.lpDesktop = NULL;
|
||||
|
||||
debug("Executing command: %s", exec_command);
|
||||
if ((exec_command_w = utf8_to_utf16(exec_command)) == NULL)
|
||||
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;
|
||||
error("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(pipein[0]);
|
||||
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
|
||||
* 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);
|
||||
else
|
||||
session_set_fds(ssh, s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 1); /* tty interactive session */
|
||||
}
|
||||
|
||||
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));
|
||||
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);
|
||||
f = fdopen(fd, "w");
|
||||
if (f == NULL) {
|
||||
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
|
||||
close(fd);
|
||||
#endif /* !WINDOWS */
|
||||
sshkey_free(public);
|
||||
first = 0;
|
||||
continue;
|
||||
@ -1232,10 +1225,6 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
|
||||
static void
|
||||
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];
|
||||
int r, fd, oerrno, inplace = 0;
|
||||
struct known_hosts_ctx ctx;
|
||||
@ -1327,7 +1316,6 @@ do_known_hosts(struct passwd *pw, const char *name)
|
||||
}
|
||||
|
||||
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);
|
||||
if (fd == -1)
|
||||
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");
|
||||
if (f == NULL)
|
||||
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
||||
#endif /* !WINDOWS */
|
||||
if ((r = sshkey_write(public, f)) != 0)
|
||||
fatal("write key failed: %s", ssh_err(r));
|
||||
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)
|
||||
fatal("Could not open \"%s\" for writing: %s", out,
|
||||
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)
|
||||
fatal("%s: fdopen: %s", __func__, strerror(errno));
|
||||
#endif /* !WINDOWS */
|
||||
if ((r = sshkey_write(public, f)) != 0)
|
||||
fatal("Could not write certified key to %s: %s",
|
||||
out, ssh_err(r));
|
||||
@ -2851,15 +2825,8 @@ passphrase_again:
|
||||
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
|
||||
fatal("Unable to save public key to %s: %s",
|
||||
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)
|
||||
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
|
||||
#endif /* !WINDOWS */
|
||||
if ((r = sshkey_write(public, f)) != 0)
|
||||
error("write key failed: %s", ssh_err(r));
|
||||
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_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 */
|
||||
set_log_handler(mm_log_handler, pmonitor);
|
||||
|
||||
@ -948,6 +951,7 @@ privsep_postauth(Authctxt *authctxt)
|
||||
close(pmonitor->m_recvfd);
|
||||
|
||||
pmonitor->m_recvfd = PRIVSEP_MONITOR_FD;
|
||||
fcntl(pmonitor->m_recvfd, F_SETFD, FD_CLOEXEC);
|
||||
monitor_recv_keystate(pmonitor);
|
||||
|
||||
do_setusercontext(authctxt->pw);
|
||||
|
Loading…
x
Reference in New Issue
Block a user