version 1.141, 2005/07/16 01:35:24 |
version 1.141.2.2, 2006/10/06 03:19:32 |
|
|
|
/* $OpenBSD$ */ |
/* |
/* |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
#include "includes.h" |
|
RCSID("$OpenBSD$"); |
|
|
|
|
#include <sys/types.h> |
|
#include <sys/ioctl.h> |
|
#include <sys/stat.h> |
|
#include <sys/socket.h> |
|
#include <sys/time.h> |
|
#include <sys/param.h> |
|
|
|
#include <ctype.h> |
|
#include <errno.h> |
|
#include <paths.h> |
|
#include <signal.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <termios.h> |
|
#include <pwd.h> |
|
#include <unistd.h> |
|
|
|
#include "xmalloc.h" |
#include "ssh.h" |
#include "ssh.h" |
#include "ssh1.h" |
#include "ssh1.h" |
#include "ssh2.h" |
#include "ssh2.h" |
#include "xmalloc.h" |
|
#include "packet.h" |
#include "packet.h" |
#include "buffer.h" |
#include "buffer.h" |
#include "compat.h" |
#include "compat.h" |
#include "channels.h" |
#include "channels.h" |
#include "dispatch.h" |
#include "dispatch.h" |
#include "buffer.h" |
|
#include "bufaux.h" |
|
#include "key.h" |
#include "key.h" |
|
#include "cipher.h" |
#include "kex.h" |
#include "kex.h" |
#include "log.h" |
#include "log.h" |
#include "readconf.h" |
#include "readconf.h" |
#include "clientloop.h" |
#include "clientloop.h" |
|
#include "sshconnect.h" |
#include "authfd.h" |
#include "authfd.h" |
#include "atomicio.h" |
#include "atomicio.h" |
#include "sshpty.h" |
#include "sshpty.h" |
|
|
static volatile sig_atomic_t received_window_change_signal = 0; |
static volatile sig_atomic_t received_window_change_signal = 0; |
static volatile sig_atomic_t received_signal = 0; |
static volatile sig_atomic_t received_signal = 0; |
|
|
/* Flag indicating whether the user\'s terminal is in non-blocking mode. */ |
/* Flag indicating whether the user's terminal is in non-blocking mode. */ |
static int in_non_blocking_mode = 0; |
static int in_non_blocking_mode = 0; |
|
|
/* Common data for the client loop code. */ |
/* Common data for the client loop code. */ |
static int quit_pending; /* Set to non-zero to quit the client loop. */ |
static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
static int escape_char; /* Escape character. */ |
static int escape_char; /* Escape character. */ |
static int escape_pending; /* Last character was the escape character */ |
static int escape_pending; /* Last character was the escape character */ |
static int last_was_cr; /* Last character was a newline. */ |
static int last_was_cr; /* Last character was a newline. */ |
|
|
* Signal handler for the window change signal (SIGWINCH). This just sets a |
* Signal handler for the window change signal (SIGWINCH). This just sets a |
* flag indicating that the window has changed. |
* flag indicating that the window has changed. |
*/ |
*/ |
|
/*ARGSUSED */ |
static void |
static void |
window_change_handler(int sig) |
window_change_handler(int sig) |
{ |
{ |
|
|
* Signal handler for signals that cause the program to terminate. These |
* Signal handler for signals that cause the program to terminate. These |
* signals must be trapped to restore terminal modes. |
* signals must be trapped to restore terminal modes. |
*/ |
*/ |
|
/*ARGSUSED */ |
static void |
static void |
signal_handler(int sig) |
signal_handler(int sig) |
{ |
{ |
|
|
} |
} |
} |
} |
snprintf(cmd, sizeof(cmd), |
snprintf(cmd, sizeof(cmd), |
"%s %s%s list %s . 2>" _PATH_DEVNULL, |
"%s %s%s list %s 2>" _PATH_DEVNULL, |
xauth_path, |
xauth_path, |
generated ? "-f " : "" , |
generated ? "-f " : "" , |
generated ? xauthfile : "", |
generated ? xauthfile : "", |
|
|
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) |
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) |
return; |
return; |
packet_start(SSH_CMSG_WINDOW_SIZE); |
packet_start(SSH_CMSG_WINDOW_SIZE); |
packet_put_int(ws.ws_row); |
packet_put_int((u_int)ws.ws_row); |
packet_put_int(ws.ws_col); |
packet_put_int((u_int)ws.ws_col); |
packet_put_int(ws.ws_xpixel); |
packet_put_int((u_int)ws.ws_xpixel); |
packet_put_int(ws.ws_ypixel); |
packet_put_int((u_int)ws.ws_ypixel); |
packet_send(); |
packet_send(); |
} |
} |
} |
} |
|
|
} |
} |
|
|
static void |
static void |
client_process_net_input(fd_set * readset) |
client_process_net_input(fd_set *readset) |
{ |
{ |
int len; |
int len; |
char buf[8192]; |
char buf[8192]; |
|
|
} |
} |
|
|
static void |
static void |
client_process_control(fd_set * readset) |
client_process_control(fd_set *readset) |
{ |
{ |
Buffer m; |
Buffer m; |
Channel *c; |
Channel *c; |
|
|
return; |
return; |
} |
} |
|
|
cctx = xmalloc(sizeof(*cctx)); |
cctx = xcalloc(1, sizeof(*cctx)); |
memset(cctx, 0, sizeof(*cctx)); |
|
cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; |
cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; |
cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; |
cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; |
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; |
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; |
|
|
env_len = MIN(env_len, 4096); |
env_len = MIN(env_len, 4096); |
debug3("%s: receiving %d env vars", __func__, env_len); |
debug3("%s: receiving %d env vars", __func__, env_len); |
if (env_len != 0) { |
if (env_len != 0) { |
cctx->env = xmalloc(sizeof(*cctx->env) * (env_len + 1)); |
cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env)); |
for (i = 0; i < env_len; i++) |
for (i = 0; i < env_len; i++) |
cctx->env[i] = buffer_get_string(&m, &len); |
cctx->env[i] = buffer_get_string(&m, &len); |
cctx->env[i] = NULL; |
cctx->env[i] = NULL; |
|
|
|
|
debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, |
debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, |
cctx->want_tty, cctx->want_subsys, cmd); |
cctx->want_tty, cctx->want_subsys, cmd); |
|
xfree(cmd); |
|
|
/* Gather fds from client */ |
/* Gather fds from client */ |
new_fd[0] = mm_receive_fd(client_fd); |
new_fd[0] = mm_receive_fd(client_fd); |
|
|
|
|
if (*s == 'h' || *s == 'H' || *s == '?') { |
if (*s == 'h' || *s == 'H' || *s == '?') { |
logit("Commands:"); |
logit("Commands:"); |
logit(" -Lport:host:hostport Request local forward"); |
logit(" -L[bind_address:]port:host:hostport " |
logit(" -Rport:host:hostport Request remote forward"); |
"Request local forward"); |
logit(" -KRhostport Cancel remote forward"); |
logit(" -R[bind_address:]port:host:hostport " |
|
"Request remote forward"); |
|
logit(" -KR[bind_address:]port " |
|
"Cancel remote forward"); |
|
if (!options.permit_local_command) |
|
goto out; |
|
logit(" !args " |
|
"Execute local command"); |
goto out; |
goto out; |
} |
} |
|
|
|
if (*s == '!' && options.permit_local_command) { |
|
s++; |
|
ssh_local_cmd(s); |
|
goto out; |
|
} |
|
|
if (*s == 'K') { |
if (*s == 'K') { |
delete = 1; |
delete = 1; |
s++; |
s++; |
|
|
goto out; |
goto out; |
} |
} |
} else { |
} else { |
channel_request_remote_forwarding(fwd.listen_host, |
if (channel_request_remote_forwarding(fwd.listen_host, |
fwd.listen_port, fwd.connect_host, |
fwd.listen_port, fwd.connect_host, |
fwd.connect_port); |
fwd.connect_port) < 0) { |
|
logit("Port forwarding failed."); |
|
goto out; |
|
} |
} |
} |
|
|
logit("Forwarding port."); |
logit("Forwarding port."); |
|
|
} |
} |
|
|
static void |
static void |
client_process_input(fd_set * readset) |
client_process_input(fd_set *readset) |
{ |
{ |
int len; |
int len; |
char buf[8192]; |
char buf[8192]; |
|
|
} |
} |
|
|
static void |
static void |
client_process_output(fd_set * writeset) |
client_process_output(fd_set *writeset) |
{ |
{ |
int len; |
int len; |
char buf[100]; |
char buf[100]; |
|
|
session_ident = ssh2_chan_id; |
session_ident = ssh2_chan_id; |
if (escape_char != SSH_ESCAPECHAR_NONE) |
if (escape_char != SSH_ESCAPECHAR_NONE) |
channel_register_filter(session_ident, |
channel_register_filter(session_ident, |
simple_escape_filter); |
simple_escape_filter, NULL); |
if (session_ident != -1) |
if (session_ident != -1) |
channel_register_cleanup(session_ident, |
channel_register_cleanup(session_ident, |
client_channel_closed); |
client_channel_closed, 0); |
} else { |
} else { |
/* Check if we should immediately send eof on stdin. */ |
/* Check if we should immediately send eof on stdin. */ |
client_check_initial_eof_on_stdin(); |
client_check_initial_eof_on_stdin(); |
|
|
|
|
if (!options.forward_x11) { |
if (!options.forward_x11) { |
error("Warning: ssh server tried X11 forwarding."); |
error("Warning: ssh server tried X11 forwarding."); |
error("Warning: this is probably a break in attempt by a malicious server."); |
error("Warning: this is probably a break-in attempt by a malicious server."); |
return NULL; |
return NULL; |
} |
} |
originator = packet_get_string(NULL); |
originator = packet_get_string(NULL); |
|
|
|
|
if (!options.forward_agent) { |
if (!options.forward_agent) { |
error("Warning: ssh server tried agent forwarding."); |
error("Warning: ssh server tried agent forwarding."); |
error("Warning: this is probably a break in attempt by a malicious server."); |
error("Warning: this is probably a break-in attempt by a malicious server."); |
return NULL; |
return NULL; |
} |
} |
sock = ssh_get_authentication_socket(); |
sock = ssh_get_authentication_socket(); |
|
|
|
|
channel_request_start(id, "pty-req", 0); |
channel_request_start(id, "pty-req", 0); |
packet_put_cstring(term != NULL ? term : ""); |
packet_put_cstring(term != NULL ? term : ""); |
packet_put_int(ws.ws_col); |
packet_put_int((u_int)ws.ws_col); |
packet_put_int(ws.ws_row); |
packet_put_int((u_int)ws.ws_row); |
packet_put_int(ws.ws_xpixel); |
packet_put_int((u_int)ws.ws_xpixel); |
packet_put_int(ws.ws_ypixel); |
packet_put_int((u_int)ws.ws_ypixel); |
tio = get_saved_tio(); |
tio = get_saved_tio(); |
tty_make_modes(-1, tiop != NULL ? tiop : &tio); |
tty_make_modes(-1, tiop != NULL ? tiop : &tio); |
packet_send(); |
packet_send(); |
|
|
/* Split */ |
/* Split */ |
name = xstrdup(env[i]); |
name = xstrdup(env[i]); |
if ((val = strchr(name, '=')) == NULL) { |
if ((val = strchr(name, '=')) == NULL) { |
free(name); |
xfree(name); |
continue; |
continue; |
} |
} |
*val++ = '\0'; |
*val++ = '\0'; |
|
|
} |
} |
if (!matched) { |
if (!matched) { |
debug3("Ignored env %s", name); |
debug3("Ignored env %s", name); |
free(name); |
xfree(name); |
continue; |
continue; |
} |
} |
|
|
|
|
packet_put_cstring(name); |
packet_put_cstring(name); |
packet_put_cstring(val); |
packet_put_cstring(val); |
packet_send(); |
packet_send(); |
free(name); |
xfree(name); |
} |
} |
} |
} |
|
|