From f5226a3b70a010deaf07e8d1bc673bf08380039e Mon Sep 17 00:00:00 2001 From: Manoj Ampalam Date: Thu, 29 Sep 2016 17:27:21 -0700 Subject: [PATCH] Added PTY support to account for client TTY window size changes --- channels.c | 37 +++++++++------------- channels.h | 4 --- clientloop.c | 24 ++------------- contrib/win32/win32compat/signal.c | 16 +++++++++- contrib/win32/win32compat/tncon.c | 8 ++--- session.c | 49 ++++++++++++++++-------------- sshpty.c | 39 +++--------------------- 7 files changed, 65 insertions(+), 112 deletions(-) diff --git a/channels.c b/channels.c index b98069e..bc1c6c4 100644 --- a/channels.c +++ b/channels.c @@ -3895,7 +3895,6 @@ channel_connect_to_path(const char *path, char *ctype, char *rname) return connect_to(path, PORT_STREAMLOCAL, ctype, rname); } -#ifndef WIN32_FIXME//N void channel_send_window_changes(void) { @@ -3907,8 +3906,21 @@ channel_send_window_changes(void) if (channels[i] == NULL || !channels[i]->client_tty || channels[i]->type != SSH_CHANNEL_OPEN) continue; +#ifndef WIN32_FIXME if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) - continue; + continue +#else + { + CONSOLE_SCREEN_BUFFER_INFO c_info; + /* TODO - Fix this for multiple channels*/ + if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &c_info)) + continue; + ws.ws_col = c_info.dwSize.X; + ws.ws_row = c_info.dwSize.Y; + ws.ws_xpixel = 640; + ws.ws_ypixel = 480; + } +#endif channel_request_start(i, "window-change", 0); packet_put_int((u_int)ws.ws_col); packet_put_int((u_int)ws.ws_row); @@ -3918,27 +3930,6 @@ channel_send_window_changes(void) } } -#else // WIN32_FIXME -void -channel_send_window_changes(int col, int row, int xpixel, int ypixel) -{ - u_int i; - struct winsize ws; - - for (i = 0; i < channels_alloc; i++) { - if (channels[i] == NULL || !channels[i]->client_tty || - channels[i]->type != SSH_CHANNEL_OPEN) - continue; - channel_request_start(i, "window-change", 0); - packet_put_int((u_int)col); - packet_put_int((u_int)row); - packet_put_int((u_int)xpixel); - packet_put_int((u_int)ypixel); - packet_send(); - } -} -#endif - /* -- X11 forwarding */ diff --git a/channels.h b/channels.h index e7288db..07c6a21 100644 --- a/channels.h +++ b/channels.h @@ -226,11 +226,7 @@ void channel_register_status_confirm(int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(int); int channel_close_fd(int *); -#ifndef WIN32_FIXME void channel_send_window_changes(void); -#else -void channel_send_window_changes(int, int, int, int); -#endif /* protocol handler */ diff --git a/clientloop.c b/clientloop.c index cd05d83..ddc3078 100644 --- a/clientloop.c +++ b/clientloop.c @@ -537,7 +537,7 @@ client_make_packets_from_stdin_data(void) static void client_check_window_change(void) { -#ifndef WIN32_FIXME + struct winsize ws; if (! received_window_change_signal) @@ -550,6 +550,7 @@ client_check_window_change(void) if (compat20) { channel_send_window_changes(); } else { +#ifndef WIN32_FIXME if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) return; packet_start(SSH_CMSG_WINDOW_SIZE); @@ -558,27 +559,8 @@ client_check_window_change(void) packet_put_int((u_int)ws.ws_xpixel); packet_put_int((u_int)ws.ws_ypixel); packet_send(); +#endif } -#else - - if (! win_received_window_change_signal) - return; - /** XXX race */ - win_received_window_change_signal = 0; - - debug2("client_check_window_change: changed"); - - if (compat20) { - channel_send_window_changes(ScreenX, ScrollBottom, 640, 480); - } else { - packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int((u_int)ScreenX); - packet_put_int((u_int)ScrollBottom); - packet_put_int((u_int)640); - packet_put_int((u_int)480); - packet_send(); - } -#endif /* !WIN32_FIXME */ } static int diff --git a/contrib/win32/win32compat/signal.c b/contrib/win32/win32compat/signal.c index 20f4df8..8c112ca 100644 --- a/contrib/win32/win32compat/signal.c +++ b/contrib/win32/win32compat/signal.c @@ -86,6 +86,20 @@ native_sig_handler(DWORD dwCtrlType) } } +static VOID CALLBACK +sigwinch_APCProc( + _In_ ULONG_PTR dwParam + ) { + debug3("SIGTERM APCProc()"); + sigaddset(&pending_signals, W32_SIGWINCH); +} + + +void +queue_terminal_window_change_event() { + QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL); +} + void sw_init_signal_handler_table() { int i; @@ -163,7 +177,7 @@ sw_process_pending_signals() { BOOL sig_int = FALSE; /* has any signal actually interrupted */ debug3("process_signals()"); - int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP }; + int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP, W32_SIGWINCH }; /* check for expected signals*/ for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++) diff --git a/contrib/win32/win32compat/tncon.c b/contrib/win32/win32compat/tncon.c index 43f7fc5..9b272c1 100644 --- a/contrib/win32/win32compat/tncon.c +++ b/contrib/win32/win32compat/tncon.c @@ -116,6 +116,8 @@ BOOL DataAvailable(HANDLE h) return FALSE; } +void queue_terminal_window_change_event(); + int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) { HANDLE hHandle[] = { hInput, NULL }; @@ -148,11 +150,7 @@ int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen) switch (InputRecord.EventType) { case WINDOW_BUFFER_SIZE_EVENT: - memcpy(szResponse, NAWSSTR, 9); - szResponse[4] = ConScreenSizeX(); - szResponse[6] = ConWindowSizeY(); - ScreenX = ConScreenSizeX(); - ScreenY = ConWindowSizeY(); + queue_terminal_window_change_event(); break; case FOCUS_EVENT: diff --git a/session.c b/session.c index d5803fe..cf96680 100644 --- a/session.c +++ b/session.c @@ -497,6 +497,10 @@ do_authenticated1(Authctxt *authctxt) #define USE_PIPES 1 #endif +#ifdef WIN32_FIXME +extern int debug_flag; +#endif + /* * This is called to fork and execute a command when we have no tty. This * will call do_child from the child, and server_loop from the parent after @@ -548,8 +552,6 @@ do_exec_no_pty(Session *s, const char *command) char *exec_command; char *laddr; char buf[256]; - int prot_scr_width = 80; - int prot_scr_height = 25; #ifdef WIN32_PRAGMA_REMCON char exec_command_str[512]; #endif @@ -590,8 +592,6 @@ do_exec_no_pty(Session *s, const char *command) int retcode = -1; if ( (!s -> is_subsystem) && (s ->ttyfd != -1)) { - prot_scr_width = s->col; - prot_scr_height = s->row; extern HANDLE hInputConsole; extern HANDLE hOutputConsole ; hInputConsole = GetConsoleInputHandle(); @@ -620,10 +620,10 @@ do_exec_no_pty(Session *s, const char *command) si.lpTitle = NULL; /* NULL means use exe name as title */ si.dwX = 0; si.dwY = 0; - si.dwXSize = 640; - si.dwYSize = 480; - si.dwXCountChars = prot_scr_width; - si.dwYCountChars = prot_scr_height; + si.dwXSize = 5; + si.dwYSize = 5; + si.dwXCountChars = s->col; + si.dwYCountChars = s->row; si.dwFillAttribute = 0; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS; si.wShowWindow = 0; // FALSE ; @@ -794,32 +794,35 @@ do_exec_no_pty(Session *s, const char *command) wchar_t exec_command_w[MAX_PATH]; MultiByteToWideChar(CP_UTF8, 0, exec_command, -1, exec_command_w, MAX_PATH); - DWORD dwStartupFlags = 0;// CREATE_SUSPENDED; // 0 + DWORD dwStartupFlags = DETACHED_PROCESS;// CREATE_SUSPENDED; // 0 SetConsoleCtrlHandler(NULL, FALSE); - b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE, + if (debug_flag) + b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, + /*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s->pw->pw_dir, + &si, &pi); + else + b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE, /*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s -> pw -> pw_dir, &si, &pi); - /* - * If CreateProcessAsUser() fails we will try CreateProcess() - * but only if current user and login user are the same. - */ - - if ((!b) && (strcmp(name, s -> pw -> pw_name) == 0)) - { - b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE, - /*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s -> pw -> pw_dir, - &si, &pi); - } - if (!b) { - debug("ERROR. Cannot create process as new user (%u).\n", GetLastError()); + debug("ERROR. Cannot create process (%u).\n", GetLastError()); CloseHandle(hToken); exit(1); } + else { + FreeConsole(); + if (!debug_flag) + ImpersonateLoggedOnUser(hToken); + while (AttachConsole(pi.dwProcessId) == FALSE) { + Sleep(200); + } + if (!debug_flag) + RevertToSelf(); + } /* * Save token used for create child process. We'll need it on cleanup diff --git a/sshpty.c b/sshpty.c index 7c387bd..731fdac 100644 --- a/sshpty.c +++ b/sshpty.c @@ -197,32 +197,6 @@ pty_make_controlling_tty(int *ttyfd, const char *tty) #endif } -#ifdef WIN32_PRAGMA_REMCON -/* Changes the window size associated with the pty. */ - -void pty_change_window_size_oob(int ptyfd, u_int row, u_int col, u_int xpixel, u_int ypixel) -{ - int rc; - char unsigned data[16]; - size_t data_len; - - // IAC SB NAWS <16-bit value width> <16-bit value height> IAC - //sprintf (data,"%c%c%c%c%c%c%c%c", 255, 250, 31, 0, col, 0, row, 255 ); - data[0] = 255; // IAC; - data[1] = 250; // SB - data[2] = 31; // NAWS - data[3] = 0; - data[4] = (unsigned char)col; - data[5] = 0; - data[6] = (unsigned char)row; - data[7] = 255; // IAC - data[8] = 240; // iac end - data_len = 9; //strlen (data); - rc = write(ptyfd, data, (DWORD)data_len); - //rc = AsyncWrite(c->hInputHandle, (char *)data, (DWORD)data_len); -} - -#endif /* Changes the window size associated with the pty. */ void @@ -239,15 +213,10 @@ pty_change_window_size(int ptyfd, u_int row, u_int col, w.ws_ypixel = ypixel; (void) ioctl(ptyfd, TIOCSWINSZ, &w); #else - extern HANDLE hOutputConsole ; - #ifndef WIN32_PRAGMA_REMCON - if (hOutputConsole != NULL) { - ConSetScreenSize(col, row); - } - #else - if (ptyfd > 0 ) - pty_change_window_size_oob(ptyfd, row, col, xpixel, ypixel); - #endif + COORD coord; + coord.X = col; + coord.Y = row; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord); #endif }