Manoj Ampalam af4e4113b2
Ported bash based E2E tests and integrated security fix for cve-2018-15473(#346)
- Updated code to dynamic load Lsa functions until RS5 SDK includes them
 - Add conpty support in openssh
- Fixed Wierd characters (?25l) are seen, when logged in from ssh client
- Backspace doesn't work in powershell window
- Changes to support ssh-shellhost as an alternative shell
- Added support to have ssh-shellhost work as a standby shell (ssh-shellhost -c "cmdline") simply executes cmdline via CreateProcess
- Added E2E test cases and fixed unittests broken from prior changes
- Added PTY launch interface that supports both conpty and ssh-shellhost pty.
- Implemented PTY control channel in ssh-shellhost that supports Window resize events.
- Fixed regression with starting a PTY session with an explicit command
- modified ssh-shellhost pty argument to ---pty to remove ambiguity in cases when both -p and -c are present in commandline. Ex. ssh-shellhost.exe -c "myprogram -p -c argument"
2018-10-04 14:16:02 -07:00

426 lines
12 KiB
C

#include "includes.h"
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <misc_internal.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include "../test_helper/test_helper.h"
#include "tests.h"
int retValue;
// The ioctl() testcase is failing when ran from Run-OpenSSHUnitTest.
void
test_ioctl()
{
if(!isatty(fileno(stdin))) return;
TEST_START("ioctl");
struct winsize ws;
memset(&ws, 0, sizeof(ws));
retValue = ioctl(fileno(stdin), TIOCGWINSZ, &ws);
ASSERT_INT_EQ(retValue, 0);
ASSERT_INT_NE(ws.ws_col, 0);
ASSERT_INT_NE(ws.ws_row, 0);
ASSERT_INT_NE(ws.ws_xpixel, 0);
ASSERT_INT_NE(ws.ws_ypixel, 0);
TEST_DONE();
}
void
test_path_conversion_utilities()
{
TEST_START("path conversion utilities");
char *s = "c:\\testdir\\test";
char *windows_style_path = dup_str(s);
int len = strlen(windows_style_path);
char *backup = malloc(len + 1);
strncpy(backup, windows_style_path, len);
backup[len] = '\0';
convertToForwardslash(windows_style_path);
char *tmpStr = strstr(windows_style_path, "\\");
ASSERT_PTR_EQ(tmpStr, NULL);
convertToBackslash(windows_style_path);
tmpStr = strstr(windows_style_path, "/");
ASSERT_PTR_EQ(tmpStr, NULL);
retValue = strcmp(windows_style_path, backup);
ASSERT_INT_EQ(retValue, 0);
free(windows_style_path);
TEST_DONE();
}
void
test_sanitizedpath()
{
TEST_START("win32 program dir");
char *win32prgdir_utf8 = __progdir;
ASSERT_PTR_NE(win32prgdir_utf8, NULL);
ASSERT_PTR_EQ(resolved_path_utf16(NULL), NULL);
ASSERT_INT_EQ(errno, EINVAL);
wchar_t *win32prgdir = utf8_to_utf16(win32prgdir_utf8);
wchar_t *ret = resolved_path_utf16(win32prgdir_utf8);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(win32prgdir, ret);
ASSERT_INT_EQ(retValue, 0);
free(ret);
char win32prgdir_len = strlen(win32prgdir_utf8);
char *tmp_path = malloc(win32prgdir_len + 2); /* 1-NULL and 1-adding "/" */
tmp_path[0] = '/';
strcpy(tmp_path+1, win32prgdir_utf8);
tmp_path[win32prgdir_len+1] = '\0';
ret = resolved_path_utf16(tmp_path);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(win32prgdir, ret);
ASSERT_INT_EQ(retValue, 0);
free(ret);
char s1[4];
wchar_t s2[4];
s1[0] = '/', s1[1] = win32prgdir[0], s1[2] = ':', s1[3] = '\0';
s2[0] = win32prgdir[0], s2[1] = ':', s2[2] = '\\', s2[3] = '\0';
ret = resolved_path_utf16(s1);
/* resolved path will return in unix file format ex - c:/test/1/ */
convertToBackslashW(ret);
retValue = wcscmp(ret, s2);
ASSERT_INT_EQ(retValue, 0);
free(ret);
free(win32prgdir);
TEST_DONE();
}
void
test_pw()
{
TEST_START("pw tests");
struct passwd *pw = NULL;
pw = getpwuid(0);
ASSERT_PTR_NE(pw, NULL);
struct passwd *pw1 = NULL;
char *user = dup_str(pw->pw_name);
pw1 = getpwnam(user);
ASSERT_PTR_NE(pw1, NULL);
TEST_DONE();
}
void
test_statvfs()
{
TEST_START("test statvfs");
struct statvfs st;
char cwd[MAX_PATH];
char *tmp = getcwd(cwd, MAX_PATH);
ASSERT_PTR_NE(tmp, NULL);
retValue = statvfs(NULL, &st);
ASSERT_INT_EQ(retValue, -1);
explicit_bzero(&st, sizeof(st));
retValue = statvfs(cwd, &st);
ASSERT_INT_EQ(retValue, 0);
ASSERT_INT_NE(st.f_bavail, 0);
TEST_DONE();
}
void test_realpath()
{
TEST_START("test realpath");
char resolved_path[MAX_PATH];
char *ret = NULL;
char *expectedOutput1 = "/c:/windows/system32";
char *expectedOutput2 = "/c:/";
ret = realpath(NULL, NULL);
ASSERT_PTR_EQ(ret, NULL);
ret = realpath("c:\\windows\\system32", NULL);
ASSERT_PTR_EQ(ret, NULL);
ret = realpath(NULL, resolved_path);
ASSERT_PTR_EQ(ret, NULL);
ret = realpath("c:\\windows\\system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("/c:\\windows\\system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("/c:\\windows\\.\\system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("/c:\\windows\\.\\..\\windows\\system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("/c:\\windows/.\\..\\windows\\system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("c:/windows/system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("/c:/windows/system32", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput1);
ret = realpath("c:", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput2);
ret = realpath("c:\\", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput2);
ret = realpath("/c:", resolved_path);
ASSERT_STRING_EQ(ret, expectedOutput2);
ASSERT_PTR_NE(ret = realpath("/c:/..", resolved_path), NULL);
ASSERT_STRING_EQ(ret, "/");
ASSERT_PTR_NE(ret = realpath("/", resolved_path), NULL);
ASSERT_STRING_EQ(ret, "/");
ASSERT_PTR_NE(ret = realpath("\\", resolved_path), NULL);
ASSERT_STRING_EQ(ret, "/");
TEST_DONE();
}
void
test_chroot()
{
int fd;
FILE *f;
char path[MAX_PATH], test_root[MAX_PATH];
/* test directory setup */
_wsystem(L"RD /S /Q chroot-testdir >NUL 2>&1");
CreateDirectoryW(L"chroot-testdir", NULL);
CreateDirectoryW(L"chroot-testdir\\world", NULL);
_wsystem(L"echo in-world > chroot-testdir\\world\\w.Txt");
CreateDirectoryW(L"chroot-testdir\\jail", NULL);
CreateDirectoryW(L"chroot-testdir\\jail\\d1", NULL);
_wsystem(L"echo in-jail > chroot-testdir\\jail\\d1\\j.Txt");
/* create links to world within jail */
_wsystem(L"mklink /D chroot-testdir\\jail\\world-sl ..\\world");
_wsystem(L"mklink /J chroot-testdir\\jail\\world-jn chroot-testdir\\world");
TEST_START("chroot on invalid path");
ASSERT_INT_EQ(chroot("blah"), -1);
ASSERT_INT_EQ(chroot("\\c:\\blah"), -1);
ASSERT_INT_EQ(chroot("/c:/blah"), -1);
TEST_DONE();
TEST_START("access world before chroot");
ASSERT_INT_NE(fd = open("chroot-testdir\\jail\\world-jn\\w.Txt", 0), -1);
close(fd);
ASSERT_PTR_NE(f = fopen("chroot-testdir\\jail\\world-jn\\w.Txt", "r"), NULL);
fclose(f);
TEST_DONE();
TEST_START("real chroot now");
getcwd(path, MAX_PATH);
getcwd(test_root, MAX_PATH);
strcat(path, "\\chroot-testdir\\jail");
ASSERT_INT_EQ(chdir(path), 0);
ASSERT_INT_EQ(chroot(path), 0);
TEST_DONE();
TEST_START("chdir; getcwd and realpath");
ASSERT_PTR_NE(getcwd(path, MAX_PATH), NULL);
ASSERT_STRING_EQ(path, "\\");
ASSERT_INT_NE(chdir(test_root), 0);
ASSERT_INT_EQ(chdir("d1"), 0);
ASSERT_PTR_NE(realpath("..", path), NULL);
ASSERT_STRING_EQ(path, "/");
ASSERT_PTR_NE(getcwd(path, MAX_PATH), NULL);
ASSERT_STRING_EQ(path, "\\d1");
ASSERT_PTR_NE(realpath(".", path), NULL);
ASSERT_STRING_EQ(path, "/d1");
ASSERT_PTR_EQ(realpath("..\\..\\", path), NULL);
ASSERT_INT_EQ(errno, EACCES);
TEST_DONE();
TEST_START("file io within jail");
ASSERT_INT_NE(fd = open("\\d1\\j.txt", 0), -1);
close(fd);
ASSERT_INT_NE(fd = open("\\d1/j.txt", 0), -1);
close(fd);
ASSERT_INT_NE(fd = open("/d1/j.txt", 0), -1);
close(fd);
ASSERT_INT_NE(fd = open("/dev/null", 0), -1);
close(fd);
ASSERT_PTR_NE(f = fopen("\\d1\\j.txt", "r"), NULL);
fclose(f);
ASSERT_PTR_NE(f = fopen("/dev/null", "w"), NULL);
fclose(f);
ASSERT_INT_EQ(chdir("/"), 0);
ASSERT_INT_NE(fd = open("d1/j.txt", 0), -1);
close(fd);
ASSERT_PTR_NE(f = fopen("d1\\j.txt", "r"), NULL);
fclose(f);
ASSERT_INT_EQ(chdir("\\d1"), 0);
ASSERT_INT_NE(fd = open("j.txt", 0), -1);
close(fd);
ASSERT_PTR_NE(f = fopen("j.txt", "r"), NULL);
fclose(f);
TEST_DONE();
TEST_START("access world after chroot");
ASSERT_INT_EQ(chdir("/"), 0);
ASSERT_INT_EQ(fd = open(test_root, 0), -1);
ASSERT_INT_EQ(errno, ENOENT);
ASSERT_INT_EQ(fd = open("..\\", 0), -1);
ASSERT_INT_EQ(errno, EACCES);
ASSERT_INT_EQ(fd = open("../", 0), -1);
ASSERT_INT_EQ(errno, EACCES);
ASSERT_INT_EQ(fd = open("../outofjail.txt", O_CREAT), -1);
ASSERT_INT_EQ(errno, EACCES);
/* ensure outofjail.txt is not created by the above call*/
path[0] = '\0';
strcat(path, test_root);
strcat(path, "\\chroot-testdir\\outofjail.txt");
ASSERT_INT_EQ(fd = _open(path, 0), -1);
ASSERT_INT_EQ(errno, ENOENT);
ASSERT_INT_EQ(fd = open("world-jn\\w.Txt", 0), -1);
ASSERT_INT_EQ(errno, EACCES);
ASSERT_PTR_EQ(f = fopen("world-jn\\w.Txt", "r"), NULL);
ASSERT_INT_EQ(errno, EACCES);
ASSERT_INT_EQ(fd = open("world-sl\\w.Txt", 0), -1);
ASSERT_INT_EQ(errno, EACCES);
ASSERT_PTR_EQ(f = fopen("world-sl\\w.Txt", "r"), NULL);
ASSERT_INT_EQ(errno, EACCES);
TEST_DONE();
//_wsystem(L"RD /S /Q chroot-testdir >NUL 2>&1");
}
void
test_build_session_commandline()
{
char *progdir = __progdir, *out, buf[PATH_MAX * 2];
TEST_START("default interactive session tests");
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, NULL);
ASSERT_STRING_EQ(out, "\"c:\\system32\\cmd.exe\"");
TEST_DONE();
TEST_START("cmd shell tests");
buf[0] = '\0';
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");
buf[len_pg] = '\0';
strcat(buf, "\\sftp-server.exe\" -arg\"");
ASSERT_STRING_EQ(out, buf);
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "SFTP-server.exe -arg");
buf[len_pg] = '\0';
strcat(buf, "\\sftp-server.exe\" -arg\"");
ASSERT_STRING_EQ(out, buf);
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sftp-SERVER -arg");
buf[len_pg] = '\0';
strcat(buf, "\\sftp-server.exe\" -arg\"");
ASSERT_STRING_EQ(out, buf);
out = build_session_commandline("c:\\system32\\cmd.exe", NULL, "sCp -arg");
buf[len_pg] = '\0';
strcat(buf, "\\scp.exe\" -arg\"");
ASSERT_STRING_EQ(out, buf);
free(out);
TEST_DONE();
TEST_START("bash shell tests");
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");
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");
ASSERT_STRING_EQ(out, "\"c:\\system32\\bash\" -c \"sftp-server.exe -arg\"");
free(out);
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:\\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");
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");
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"sftp-server.exe -arg\"");
free(out);
out = build_session_commandline("c:\\cygwin\\bash", NULL, "sCp -arg");
ASSERT_STRING_EQ(out, "\"c:\\cygwin\\bash\" -c \"scp.exe -arg\"");
free(out);
TEST_DONE();
TEST_START("powershell shell tests");
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");
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");
ASSERT_STRING_EQ(out, "\"c:\\powershell.exe\" -c \"sftp-server.exe -arg\"");
free(out);
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");
ASSERT_STRING_EQ(out, "\"c:\\myshell.exe\" -c \"sftp-server.exe -arg\"");
free(out);
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");
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"sftp-server.exe -arg\"");
free(out);
out = build_session_commandline("c:\\myshell", NULL, "sCp -arg");
ASSERT_STRING_EQ(out, "\"c:\\myshell\" -c \"scp.exe -arg\"");
free(out);
TEST_DONE();
}
void
miscellaneous_tests()
{
//test_ioctl();
test_path_conversion_utilities();
test_sanitizedpath();
test_pw();
test_realpath();
test_statvfs();
test_chroot();
test_build_session_commandline();
}