diff --git a/contrib/win32/openssh/Win32-OpenSSH.sln b/contrib/win32/openssh/Win32-OpenSSH.sln
index c73130587..3d860fea9 100644
--- a/contrib/win32/openssh/Win32-OpenSSH.sln
+++ b/contrib/win32/openssh/Win32-OpenSSH.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh", "ssh.vcxproj", "{74E69D5E-A1EF-46EA-9173-19A412774104}"
ProjectSection(ProjectDependencies) = postProject
@@ -68,6 +68,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-shellhost", "ssh-shellhost.vcxproj", "{C0AE8A30-E4FA-49CE-A2B5-0C072C77EC64}"
ProjectSection(ProjectDependencies) = postProject
{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
+ {DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-agent", "ssh-agent.vcxproj", "{F6644EC5-D6B6-42A1-828C-75E2977470E0}"
diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs
index c6b3b86c0..b4d487838 100644
--- a/contrib/win32/openssh/config.h.vs
+++ b/contrib/win32/openssh/config.h.vs
@@ -1673,6 +1673,7 @@
#define HAVE_DECL_HOWMANY 0
#define HAVE_STRTOULL 1
#define HAVE_USLEEP 1
+#define HAVE_EVP_RIPEMD160 1
#if defined ( WIN32 )
#define __func__ __FUNCTION__
diff --git a/contrib/win32/openssh/ssh-shellhost.vcxproj b/contrib/win32/openssh/ssh-shellhost.vcxproj
index 5c8ac5f82..d43161847 100644
--- a/contrib/win32/openssh/ssh-shellhost.vcxproj
+++ b/contrib/win32/openssh/ssh-shellhost.vcxproj
@@ -21,6 +21,7 @@
+
@@ -113,7 +114,7 @@
Console
true
- kernel32.lib;user32.lib;%(AdditionalDependencies)
+ openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Debug-Path)lib;%(AdditionalLibraryDirectories)
@@ -133,7 +134,7 @@
Console
true
- kernel32.lib;user32.lib;%(AdditionalDependencies)
+ openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Debug-Path)lib;%(AdditionalLibraryDirectories)
@@ -156,7 +157,7 @@
true
true
true
- kernel32.lib;user32.lib;%(AdditionalDependencies)
+ openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
$(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-Win32-Release-Path)lib;%(AdditionalLibraryDirectories)
true
No
@@ -181,9 +182,10 @@
true
true
true
- kernel32.lib;user32.lib;%(AdditionalDependencies)
+ openbsd_compat.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)
true
No
+ $(OpenSSH-Lib-Path)$(Platform)\$(Configuration);$(OpenSSL-x64-Release-Path)lib;%(AdditionalLibraryDirectories)
diff --git a/contrib/win32/openssh/win32iocompat.vcxproj b/contrib/win32/openssh/win32iocompat.vcxproj
index 741649c2c..6039af70c 100644
--- a/contrib/win32/openssh/win32iocompat.vcxproj
+++ b/contrib/win32/openssh/win32iocompat.vcxproj
@@ -159,6 +159,7 @@
+
diff --git a/contrib/win32/openssh/win32iocompat.vcxproj.filters b/contrib/win32/openssh/win32iocompat.vcxproj.filters
index ac34a356d..07a88fa4c 100644
--- a/contrib/win32/openssh/win32iocompat.vcxproj.filters
+++ b/contrib/win32/openssh/win32iocompat.vcxproj.filters
@@ -18,6 +18,7 @@
+
diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c
index 4a58b83df..9e87efa1b 100644
--- a/contrib/win32/win32compat/misc.c
+++ b/contrib/win32/win32compat/misc.c
@@ -42,6 +42,7 @@
#include "inc\sys\types.h"
#include "inc\sys\ioctl.h"
#include "inc\fcntl.h"
+#include "inc\utf.h"
#include "signal_internal.h"
static char* s_programdir = NULL;
@@ -275,33 +276,6 @@ w32_fopen_utf8(const char *path, const char *mode)
return f;
}
-
-wchar_t *
-utf8_to_utf16(const char *utf8)
-{
- int needed = 0;
- wchar_t* utf16 = NULL;
- if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
- (utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
- MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0)
- return NULL;
-
- return utf16;
-}
-
-char *
-utf16_to_utf8(const wchar_t* utf16)
-{
- int needed = 0;
- char* utf8 = NULL;
- if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
- (utf8 = malloc(needed)) == NULL ||
- WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
- return NULL;
-
- return utf8;
-}
-
char *
w32_programdir()
{
diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c
index b92e02af1..de8ae2f32 100644
--- a/contrib/win32/win32compat/shell-host.c
+++ b/contrib/win32/win32compat/shell-host.c
@@ -37,6 +37,7 @@
#include
#include
#include "misc_internal.h"
+#include "inc\utf.h"
#define MAX_CONSOLE_COLUMNS 9999
#define MAX_CONSOLE_ROWS 9999
@@ -917,7 +918,7 @@ cleanup:
}
int
-start_with_pty(int ac, wchar_t **av)
+start_with_pty(wchar_t *command)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -974,17 +975,12 @@ start_with_pty(int ac, wchar_t **av)
/*TODO - pick this up from system32*/
cmd[0] = L'\0';
- if (ac)
- GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe"));
- ac--;
- av++;
- if (ac)
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe"));
+
+ if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
- while (ac) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" "));
- GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av));
- ac--;
- av++;
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, command));
}
SetConsoleCtrlHandler(NULL, FALSE);
@@ -1047,7 +1043,7 @@ MonitorChild_nopty( _In_ LPVOID lpParameter)
}
int
-start_withno_pty(int ac, wchar_t **av)
+start_withno_pty(wchar_t *command)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -1083,15 +1079,10 @@ start_withno_pty(int ac, wchar_t **av)
/*TODO - pick this up from system32*/
cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe"));
- ac -= 2;
- av += 2;
- if (ac)
+ if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
- while (ac) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" "));
- GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, *av));
- ac--;
- av++;
+ GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, command));
}
GOTO_CLEANUP_ON_FALSE(CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi));
@@ -1181,20 +1172,51 @@ cleanup:
return child_exit_code;
}
+int b64_pton(char const *src, u_char *target, size_t targsize);
+
int
wmain(int ac, wchar_t **av)
{
- /* create job to hold all child processes */
- HANDLE job = CreateJobObject(NULL, NULL);
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info;
- memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
- job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
- if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)))
- return -1;
- CloseHandle(job);
+ int pty_requested = 0;
+ wchar_t *cmd = NULL, *cmd_b64 = NULL;
+ {
+ /* create job to hold all child processes */
+ HANDLE job = CreateJobObject(NULL, NULL);
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info;
+ memset(&job_info, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+ job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info)))
+ return -1;
+ CloseHandle(job);
+ }
- if ((ac == 1) || wcscmp(av[1], L"-nopty"))
- return start_with_pty(ac, av);
+ if ((ac == 1) || (ac == 2 && wcscmp(av[1], L"-nopty"))) {
+ pty_requested = 1;
+ cmd_b64 = ac == 2? av[1] : NULL;
+ } else if (ac <= 3 && wcscmp(av[1], L"-nopty") == 0)
+ cmd_b64 = ac == 3? av[2] : NULL;
+ else {
+ printf("ssh-shellhost received unexpected input arguments");
+ return -1;
+ }
+
+ /* decode cmd_b64*/
+ if (cmd_b64) {
+ char *cmd_b64_utf8, *cmd_utf8;
+ if ((cmd_b64_utf8 = utf16_to_utf8(cmd_b64)) == NULL ||
+ /* strlen(b64) should be sufficient for decoded length */
+ (cmd_utf8 = malloc(strlen(cmd_b64_utf8))) == NULL ||
+ b64_pton(cmd_b64_utf8, cmd_utf8, strlen(cmd_b64_utf8)) == -1 ||
+ (cmd = utf8_to_utf16(cmd_utf8)) == NULL) {
+ printf("ssh-shellhost encountered an internal error while decoding base64 cmdline");
+ return -1;
+ }
+ free(cmd_b64_utf8);
+ free(cmd_utf8);
+ }
+
+ if (pty_requested)
+ return start_with_pty(cmd);
else
- return start_withno_pty(ac, av);
+ return start_withno_pty(cmd);
}
\ No newline at end of file
diff --git a/contrib/win32/win32compat/ssh-agent/authagent-request.c b/contrib/win32/win32compat/ssh-agent/authagent-request.c
index e688a5fae..0fd765eb6 100644
--- a/contrib/win32/win32compat/ssh-agent/authagent-request.c
+++ b/contrib/win32/win32compat/ssh-agent/authagent-request.c
@@ -225,7 +225,7 @@ int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response
*tmp = L'\0';
}
- if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
+ if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
goto done;
}
diff --git a/contrib/win32/win32compat/utf.c b/contrib/win32/win32compat/utf.c
new file mode 100644
index 000000000..bd93d42bc
--- /dev/null
+++ b/contrib/win32/win32compat/utf.c
@@ -0,0 +1,59 @@
+/*
+* Author: Manoj Ampalam
+*
+* Copyright(c) 2016 Microsoft Corp.
+* All rights reserved
+*
+* UTF8 <--> UTF16 conversion routines
+*
+* 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
+#include "inc\utf.h"
+
+wchar_t *
+utf8_to_utf16(const char *utf8)
+{
+ int needed = 0;
+ wchar_t* utf16 = NULL;
+ if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
+ (utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0)
+ return NULL;
+
+ return utf16;
+}
+
+char *
+utf16_to_utf8(const wchar_t* utf16)
+{
+ int needed = 0;
+ char* utf8 = NULL;
+ if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
+ (utf8 = malloc(needed)) == NULL ||
+ WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
+ return NULL;
+
+ return utf8;
+}
+
diff --git a/session.c b/session.c
index 13543c831..54b3087d4 100644
--- a/session.c
+++ b/session.c
@@ -499,8 +499,22 @@ int do_exec_windows(Session *s, const char *command, int pty) {
memcpy(exec_command + strlen(progdir) + 1, command, strlen(command) + 1);
}
} else {
+ /*
+ * contruct %programdir%\ssh-shellhost.exe <-nopty> base64encoded(command)
+ * command is base64 encoded to preserve original special charecters like '"'
+ * else they will get lost in CreateProcess translation
+ */
char *shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty ", *c;
- exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command ? strlen(command) : 0) + 1);
+ char *command_b64 = NULL;
+ size_t command_b64_len = 0;
+ if (command) {
+ /* accomodate bas64 encoding bloat and null terminator */
+ command_b64_len = ((strlen(command) + 2) / 3) * 4 + 1;
+ if ((command_b64 = malloc(command_b64_len)) == NULL ||
+ b64_ntop(command, strlen(command), command_b64, command_b64_len) == -1)
+ fatal("%s, error encoding session command");
+ }
+ exec_command = malloc(strlen(progdir) + 1 + strlen(shell_host) + (command_b64 ? strlen(command_b64): 0) + 1);
if (exec_command == NULL)
fatal("%s, out of memory", __func__);
c = exec_command;
@@ -509,9 +523,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
*c++ = '\\';
memcpy(c, shell_host, strlen(shell_host));
c += strlen(shell_host);
- if (command) {
- memcpy(c, command, strlen(command));
- c += strlen(command);
+ if (command_b64) {
+ memcpy(c, command_b64, strlen(command_b64));
+ c += strlen(command_b64);
}
*c = '\0';
}