Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix of 1211 and 1082 #349

Merged
merged 36 commits into from
Nov 5, 2018
Merged

Conversation

bingbing8
Copy link

@bingbing8 bingbing8 commented Oct 12, 2018

  1. fix of Unable to use scp with -oUserKnownHostsFile that has spaces Win32-OpenSSH#1211
  2. fix of Remote SSH commands require double escaping before hitting the DefaultShell Win32-OpenSSH#1082
  3. scp works when powershell and cmd as default shell
  4. have the escaping logic in posix_spawn only
  5. Add program dir as part of path in process context so scp and sftp in…
  6. only escape double quotes and backslash for common shells

1. fix of 1211 (scp works when powershell and cmd as default shell)
2. fix of 1082,
3. have the escaping logic in posix_spawn only4.
Add program dir as part of path in process context so scp and sftp in…
@bingbing8 bingbing8 closed this Oct 12, 2018
@bingbing8 bingbing8 reopened this Oct 15, 2018
@bingbing8 bingbing8 closed this Oct 15, 2018
@bingbing8 bingbing8 reopened this Oct 15, 2018
@bingbing8 bingbing8 changed the title (not ready for review yet) Fix of 1211 and 1082 Fix of 1211 and 1082 Oct 17, 2018
@bingbing8 bingbing8 closed this Oct 19, 2018
@bingbing8 bingbing8 reopened this Oct 19, 2018
contrib/win32/win32compat/misc.c Show resolved Hide resolved
* we want to launch scp and sftp executables from the same binary directory
* that sshd is hosted in. This will facilitate hosting and evaluating
* multiple versions of OpenSSH at the same time.
*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this function is not prepending the current binary location to command. are these comments obsolete ?

Copy link
Author

@bingbing8 bingbing8 Oct 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. we added current binary location to PATH
  2. If we prepend the path, some shells, like powershell will require shell specific additional characters (& for powershell) to be able to run scp, sftp. powershell -c "& <full path to scp>"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove the comments

@@ -1052,7 +1053,9 @@ spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDL
error("failed to duplicate %s", cmd);
return ret;
}

if (strstr(path, "system32\\cmd") || strstr(path, "ssh-shellhost"))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if you do:
bash.exe -c c:\windows\system32\cmd.exe /c "echo hi"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

Copy link
Author

@bingbing8 bingbing8 Oct 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this case is an issue when the path is user define cmd which contains both exe and arguments. in next version, I use the last parameter to define if it is user defined cmd. If so, we don't change anything.

memcpy(t, tmp, strlen(tmp));
t += strlen(tmp);
} else {
tmp += strlen(exe_extenstion); /* move the pointer to the end of ".exe" */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you end up with an input command like the following here:

c:\windows\system32\cmd /c ping.exe localhost

If so, this logic would incorrectly identify the nested binary as the parent executable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the existing known shells and ssh executable, the first parts always ends with .exe. I don't see other ways to identify the file path (the first part) in the string.

Copy link

@manojampalam manojampalam Oct 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about with proxyCommand or SSH_ASK_PASS ? Also fix spelling mistake in exe_extenstion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right.

error("failed to allocation memory");
return -1;
}
swprintf_s(path_new_value, path_new_len, L"%s%s%s", __wprogdir, path_value ? L";" : L"", path_value);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the confirmed order of exe lookup (we figured that what's on msdn is wrong) ? Does this guarantee picking up exe from progdir in all scenarios?
Are we OK with adjusting PATH for user's remote sessions?

Copy link
Author

@bingbing8 bingbing8 Oct 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the msdn is correct, but the search order is for the executable, which is the first part of the command. but scp, sftp are the arguments part of the command.
So far, looks like it picked up binaries from progdir in all the scenarios.
I don't see a problem with adjusting PATH for user's remote session.

2. don't touch user defined cmd: no prepending, no escaping, no additional quotes
3. fix line ending
@bingbing8
Copy link
Author

@manojampalam , when you get time, please review the changes. Thanks!

@bingbing8
Copy link
Author

bingbing8 commented Oct 26, 2018

@manojampalam Please review. currently only escape non-user defined commands from common shells. for other shells, no escaping, no -c added if shell option is not specified

Copy link

@manojampalam manojampalam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments inline...

@@ -496,6 +496,7 @@
<ClInclude Include="$(OpenSSH-Src-Path)uuencode.h" />
<ClInclude Include="$(OpenSSH-Src-Path)version.h" />
<ClInclude Include="$(OpenSSH-Src-Path)xmalloc.h" />
<ClInclude Include="$(OpenSSH-Src-Path)pal-doexec.c.h" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pal-doexec.h

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@@ -1,473 +1,474 @@
<?xml version="1.0" encoding="utf-8"?>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix CRLF

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still shows up different

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finally fixed it.

@@ -70,9 +70,9 @@ int is_absolute_path(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 *);
char * build_command_string(const char * );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could get rid of this since this is internal to logic within w32_doexec.c

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Copy link
Author

@bingbing8 bingbing8 Nov 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added back and keep them in misc_internal.h. we need to call them from w32_doexec.c and unit tests

int is_conpty_supported();
int exec_command_with_pty(wchar_t*, STARTUPINFOW*, PROCESS_INFORMATION*, int);
int exec_command_with_pty(int * pid, char* cmd, int in, int out, int err, unsigned int col, unsigned int row, int ttyfd);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one too, you could get rid of this since this is internal to logic within w32_doexec.c

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Copy link
Author

@bingbing8 bingbing8 Nov 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I revert it back to misc.internal.h because the definition is in w32_pty.c and the caller is w32_doexe.c

t += strlen(path);


/*For user defined cmd, no need to add quotes*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? can you add some examples? What's a user defined command ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

t += strlen(__progdir);
*t++ = '\\';
}
/*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in favor of this. What issues are we hitting if we don't do this? If the module path has spaces in it, it is expected to be enclosed in quotes. This is a standard practice even on Unix.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the log below this.

while (*t1)
cmdline_len += (DWORD)strlen(*t1++) + 1 + 2;
while (*t1) {
if (!escape)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend pulling all the commandline building logic into a separate utility helper and writing an exhaustive set of unit tests.

Copy link
Author

@bingbing8 bingbing8 Oct 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate the utility helper out.
added unit tests.


memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwXSize = 5;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 5 ? Add comments if needed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove these two lines. It was from the existing codes.

argc_original = argc;
wargv_original = wargv;

init_prog_paths();
/* change current directory to sshd.exe root */
_wchdir(__wprogdir);

_wdupenv_s(&path_value, &len, L"PATH");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments on why we are doing this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

2. Add registry key to indicate escaping is needed or not for shells other than ps, shellhost, cmd, cygwin, bash. Default is escape the arg string
@bingbing8 bingbing8 closed this Oct 31, 2018
@bingbing8 bingbing8 reopened this Oct 31, 2018
…s createprocess failed. Remove the added quotes as failoever when arg is empty.
@@ -1,473 +1,474 @@
<?xml version="1.0" encoding="utf-8"?>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still shows up different

*t = '\0';

int ret = -1;
cmdline = build_commandline_string(cmd, argv, prepend_module_path);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if build_commandline_string fails ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add check

@@ -1034,115 +1034,25 @@ int fork()
verbose("fork is not supported");
return -1;
}
char * build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this move to misc_internal.h

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

else
b = CreateProcessW(NULL, t, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
*(cmdline_utf16 + wcslen(cmdline_utf16) - 1) = L'\0';
/*failover only when double quotes is potentially added necessary*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could simplify the below condition by putting this inside loop and getting rid of "num" and "t":

if ( !b && GetLastError() != ERROR_FILENOTFOUND && (argv == NULL || *argv == NULL) && cmd[0] != '"') {
cmdline_utf16++;
*(cmdline_utf16 + wcslen(cmdline_utf16) - 1) = L'\0';
}

break;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can get rid of num, but not t.
I need to free cmdline_utf16 at the end. the pointer can't change

debug3("pty commandline: %ls", pty_cmdline);

if (!CreateProcessW(NULL, pty_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, si, pi)) {
if (CreateProcessW(NULL, pty_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I may have missed this earlier but why can't we call posix_spawnp here ?

Copy link
Author

@bingbing8 bingbing8 Nov 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for pty, the si setting from session (col, row, and dwflag) are different from posix_spawnp. There is no args for col, row, and dwflag to posix_spawnp. One option is change the signature of posix_spawn_internal to take si info and pass them to spawn_child_internal. and then call posix_spawn_internal at here.

out = build_session_commandline("c:\\powershell", NULL, "sftp-server -arg");
ASSERT_STRING_EQ(out, "\"c:\\powershell\" -c \"sftp-server.exe -arg\"");
char *
build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can get rid of this by moving it to misc_internal

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@bingbing8
Copy link
Author

@manojampalam, please review the updated code

@manojampalam manojampalam merged commit a75116b into PowerShell:latestw_all Nov 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants