version 1.311, 2019/01/19 21:41:18 |
version 1.312, 2019/01/19 21:41:53 |
|
|
#include <kafs.h> |
#include <kafs.h> |
#endif |
#endif |
|
|
#include "opacket.h" /* XXX */ |
|
extern struct ssh *active_state; /* XXX */ |
|
|
|
#define IS_INTERNAL_SFTP(c) \ |
#define IS_INTERNAL_SFTP(c) \ |
(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ |
(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ |
(c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ |
(c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ |
|
|
|
|
/* Create private directory for socket */ |
/* Create private directory for socket */ |
if (mkdtemp(auth_sock_dir) == NULL) { |
if (mkdtemp(auth_sock_dir) == NULL) { |
packet_send_debug("Agent forwarding disabled: " |
ssh_packet_send_debug(ssh, "Agent forwarding disabled: " |
"mkdtemp() failed: %.100s", strerror(errno)); |
"mkdtemp() failed: %.100s", strerror(errno)); |
restore_uid(); |
restore_uid(); |
free(auth_sock_dir); |
free(auth_sock_dir); |
|
|
|
|
s->pid = pid; |
s->pid = pid; |
/* Set interactive/non-interactive mode. */ |
/* Set interactive/non-interactive mode. */ |
packet_set_interactive(s->display != NULL, |
ssh_packet_set_interactive(ssh, s->display != NULL, |
options.ip_qos_interactive, options.ip_qos_bulk); |
options.ip_qos_interactive, options.ip_qos_bulk); |
|
|
#ifdef USE_PIPES |
#ifdef USE_PIPES |
|
|
|
|
/* Enter interactive session. */ |
/* Enter interactive session. */ |
s->ptymaster = ptymaster; |
s->ptymaster = ptymaster; |
packet_set_interactive(1, |
ssh_packet_set_interactive(ssh, 1, |
options.ip_qos_interactive, options.ip_qos_bulk); |
options.ip_qos_interactive, options.ip_qos_bulk); |
session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); |
session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); |
return 0; |
return 0; |
|
|
*/ |
*/ |
memset(&from, 0, sizeof(from)); |
memset(&from, 0, sizeof(from)); |
fromlen = sizeof(from); |
fromlen = sizeof(from); |
if (packet_connection_is_on_socket()) { |
if (ssh_packet_connection_is_on_socket(ssh)) { |
if (getpeername(packet_get_connection_in(), |
if (getpeername(ssh_packet_get_connection_in(ssh), |
(struct sockaddr *)&from, &fromlen) < 0) { |
(struct sockaddr *)&from, &fromlen) < 0) { |
debug("getpeername: %.100s", strerror(errno)); |
debug("getpeername: %.100s", strerror(errno)); |
cleanup_exit(255); |
cleanup_exit(255); |
|
|
ssh_local_port(ssh)); |
ssh_local_port(ssh)); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
child_set_env(&env, &envsize, "SSH_CLIENT", buf); |
|
|
laddr = get_local_ipaddr(packet_get_connection_in()); |
laddr = get_local_ipaddr(ssh_packet_get_connection_in(ssh)); |
snprintf(buf, sizeof buf, "%.50s %d %.50s %d", |
snprintf(buf, sizeof buf, "%.50s %d %.50s %d", |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), |
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), |
laddr, ssh_local_port(ssh)); |
laddr, ssh_local_port(ssh)); |
|
|
component, strerror(errno)); |
component, strerror(errno)); |
if (st.st_uid != 0 || (st.st_mode & 022) != 0) |
if (st.st_uid != 0 || (st.st_mode & 022) != 0) |
fatal("bad ownership or modes for chroot " |
fatal("bad ownership or modes for chroot " |
"directory %s\"%s\"", |
"directory %s\"%s\"", |
cp == NULL ? "" : "component ", component); |
cp == NULL ? "" : "component ", component); |
if (!S_ISDIR(st.st_mode)) |
if (!S_ISDIR(st.st_mode)) |
fatal("chroot path %s\"%s\" is not a directory", |
fatal("chroot path %s\"%s\" is not a directory", |
|
|
auth_sock = -1; |
auth_sock = -1; |
} |
} |
|
|
if (packet_get_connection_in() == packet_get_connection_out()) |
if (ssh_packet_get_connection_in(ssh) == |
close(packet_get_connection_in()); |
ssh_packet_get_connection_out(ssh)) |
|
close(ssh_packet_get_connection_in(ssh)); |
else { |
else { |
close(packet_get_connection_in()); |
close(ssh_packet_get_connection_in(ssh)); |
close(packet_get_connection_out()); |
close(ssh_packet_get_connection_out(ssh)); |
} |
} |
/* |
/* |
* Close all descriptors related to channels. They will still remain |
* Close all descriptors related to channels. They will still remain |
|
|
|
|
/* remove hostkey from the child's memory */ |
/* remove hostkey from the child's memory */ |
destroy_sensitive_data(); |
destroy_sensitive_data(); |
packet_clear_keys(); |
ssh_packet_clear_keys(ssh); |
|
|
/* Force a password change */ |
/* Force a password change */ |
if (s->authctxt->force_pwchange) { |
if (s->authctxt->force_pwchange) { |
|
|
static int |
static int |
session_window_change_req(struct ssh *ssh, Session *s) |
session_window_change_req(struct ssh *ssh, Session *s) |
{ |
{ |
s->col = packet_get_int(); |
int r; |
s->row = packet_get_int(); |
|
s->xpixel = packet_get_int(); |
if ((r = sshpkt_get_u32(ssh, &s->col)) != 0 || |
s->ypixel = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->row)) != 0 || |
packet_check_eom(); |
(r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 || |
|
(r = sshpkt_get_u32(ssh, &s->ypixel)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); |
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); |
return 1; |
return 1; |
} |
} |
|
|
static int |
static int |
session_pty_req(struct ssh *ssh, Session *s) |
session_pty_req(struct ssh *ssh, Session *s) |
{ |
{ |
u_int len; |
int r; |
|
|
if (!auth_opts->permit_pty_flag || !options.permit_tty) { |
if (!auth_opts->permit_pty_flag || !options.permit_tty) { |
debug("Allocating a pty not permitted for this connection."); |
debug("Allocating a pty not permitted for this connection."); |
return 0; |
return 0; |
} |
} |
if (s->ttyfd != -1) { |
if (s->ttyfd != -1) { |
packet_disconnect("Protocol error: you already have a pty."); |
ssh_packet_disconnect(ssh, "Protocol error: you already have a pty."); |
return 0; |
return 0; |
} |
} |
|
|
s->term = packet_get_string(&len); |
if ((r = sshpkt_get_cstring(ssh, &s->term, NULL)) != 0 || |
s->col = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->col)) != 0 || |
s->row = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->row)) != 0 || |
s->xpixel = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 || |
s->ypixel = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->ypixel)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
if (strcmp(s->term, "") == 0) { |
if (strcmp(s->term, "") == 0) { |
free(s->term); |
free(s->term); |
|
|
|
|
ssh_tty_parse_modes(ssh, s->ttyfd); |
ssh_tty_parse_modes(ssh, s->ttyfd); |
|
|
|
if ((r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
if (!use_privsep) |
if (!use_privsep) |
pty_setowner(s->pw, s->tty); |
pty_setowner(s->pw, s->tty); |
|
|
/* Set window size from the packet. */ |
/* Set window size from the packet. */ |
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); |
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); |
|
|
packet_check_eom(); |
|
session_proctitle(s); |
session_proctitle(s); |
return 1; |
return 1; |
} |
} |
|
|
session_subsystem_req(struct ssh *ssh, Session *s) |
session_subsystem_req(struct ssh *ssh, Session *s) |
{ |
{ |
struct stat st; |
struct stat st; |
u_int len; |
int r, success = 0; |
int success = 0; |
|
char *prog, *cmd; |
char *prog, *cmd; |
u_int i; |
u_int i; |
|
|
s->subsys = packet_get_string(&len); |
if ((r = sshpkt_get_cstring(ssh, &s->subsys, NULL)) != 0 || |
packet_check_eom(); |
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
debug2("subsystem request for %.100s by user %s", s->subsys, |
debug2("subsystem request for %.100s by user %s", s->subsys, |
s->pw->pw_name); |
s->pw->pw_name); |
|
|
|
|
static int |
static int |
session_x11_req(struct ssh *ssh, Session *s) |
session_x11_req(struct ssh *ssh, Session *s) |
{ |
{ |
int success; |
int r, success; |
|
u_char single_connection = 0; |
|
|
if (s->auth_proto != NULL || s->auth_data != NULL) { |
if (s->auth_proto != NULL || s->auth_data != NULL) { |
error("session_x11_req: session %d: " |
error("session_x11_req: session %d: " |
"x11 forwarding already active", s->self); |
"x11 forwarding already active", s->self); |
return 0; |
return 0; |
} |
} |
s->single_connection = packet_get_char(); |
if ((r = sshpkt_get_u8(ssh, &single_connection)) != 0 || |
s->auth_proto = packet_get_string(NULL); |
(r = sshpkt_get_cstring(ssh, &s->auth_proto, NULL)) != 0 || |
s->auth_data = packet_get_string(NULL); |
(r = sshpkt_get_cstring(ssh, &s->auth_data, NULL)) != 0 || |
s->screen = packet_get_int(); |
(r = sshpkt_get_u32(ssh, &s->screen)) != 0 || |
packet_check_eom(); |
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
|
s->single_connection = single_connection; |
|
|
if (xauth_valid_string(s->auth_proto) && |
if (xauth_valid_string(s->auth_proto) && |
xauth_valid_string(s->auth_data)) |
xauth_valid_string(s->auth_data)) |
success = session_setup_x11fwd(ssh, s); |
success = session_setup_x11fwd(ssh, s); |
|
|
static int |
static int |
session_shell_req(struct ssh *ssh, Session *s) |
session_shell_req(struct ssh *ssh, Session *s) |
{ |
{ |
packet_check_eom(); |
int r; |
|
|
|
if ((r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
return do_exec(ssh, s, NULL) == 0; |
return do_exec(ssh, s, NULL) == 0; |
} |
} |
|
|
static int |
static int |
session_exec_req(struct ssh *ssh, Session *s) |
session_exec_req(struct ssh *ssh, Session *s) |
{ |
{ |
u_int len, success; |
u_int success; |
|
int r; |
|
char *command = NULL; |
|
|
char *command = packet_get_string(&len); |
if ((r = sshpkt_get_cstring(ssh, &command, NULL)) != 0 || |
packet_check_eom(); |
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
success = do_exec(ssh, s, command) == 0; |
success = do_exec(ssh, s, command) == 0; |
free(command); |
free(command); |
return success; |
return success; |
|
|
static int |
static int |
session_break_req(struct ssh *ssh, Session *s) |
session_break_req(struct ssh *ssh, Session *s) |
{ |
{ |
|
int r; |
|
|
packet_get_int(); /* ignored */ |
if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* ignore */ |
packet_check_eom(); |
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0) |
if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0) |
return 0; |
return 0; |
|
|
session_env_req(struct ssh *ssh, Session *s) |
session_env_req(struct ssh *ssh, Session *s) |
{ |
{ |
char *name, *val; |
char *name, *val; |
u_int name_len, val_len, i; |
u_int i; |
|
int r; |
|
|
name = packet_get_cstring(&name_len); |
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || |
val = packet_get_cstring(&val_len); |
(r = sshpkt_get_cstring(ssh, &val, NULL)) != 0 || |
packet_check_eom(); |
(r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
|
|
/* Don't set too many environment variables */ |
/* Don't set too many environment variables */ |
if (s->num_env > 128) { |
if (s->num_env > 128) { |
|
|
session_auth_agent_req(struct ssh *ssh, Session *s) |
session_auth_agent_req(struct ssh *ssh, Session *s) |
{ |
{ |
static int called = 0; |
static int called = 0; |
|
int r; |
|
|
packet_check_eom(); |
if ((r = sshpkt_get_end(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: parse packet", __func__); |
if (!auth_opts->permit_agent_forwarding_flag || |
if (!auth_opts->permit_agent_forwarding_flag || |
!options.allow_agent_forwarding) { |
!options.allow_agent_forwarding) { |
debug("%s: agent forwarding disabled", __func__); |
debug("%s: agent forwarding disabled", __func__); |
|
|
session_exit_message(struct ssh *ssh, Session *s, int status) |
session_exit_message(struct ssh *ssh, Session *s, int status) |
{ |
{ |
Channel *c; |
Channel *c; |
|
int r; |
|
|
if ((c = channel_lookup(ssh, s->chanid)) == NULL) |
if ((c = channel_lookup(ssh, s->chanid)) == NULL) |
fatal("%s: session %d: no channel %d", |
fatal("%s: session %d: no channel %d", |
|
|
|
|
if (WIFEXITED(status)) { |
if (WIFEXITED(status)) { |
channel_request_start(ssh, s->chanid, "exit-status", 0); |
channel_request_start(ssh, s->chanid, "exit-status", 0); |
packet_put_int(WEXITSTATUS(status)); |
if ((r = sshpkt_put_u32(ssh, WEXITSTATUS(status))) != 0 || |
packet_send(); |
(r = sshpkt_send(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: exit reply", __func__); |
} else if (WIFSIGNALED(status)) { |
} else if (WIFSIGNALED(status)) { |
channel_request_start(ssh, s->chanid, "exit-signal", 0); |
channel_request_start(ssh, s->chanid, "exit-signal", 0); |
packet_put_cstring(sig2name(WTERMSIG(status))); |
if ((r = sshpkt_put_cstring(ssh, sig2name(WTERMSIG(status)))) != 0 || |
packet_put_char(WCOREDUMP(status)? 1 : 0); |
(r = sshpkt_put_u8(ssh, WCOREDUMP(status)? 1 : 0)) != 0 || |
packet_put_cstring(""); |
(r = sshpkt_put_cstring(ssh, "")) != 0 || |
packet_put_cstring(""); |
(r = sshpkt_put_cstring(ssh, "")) != 0 || |
packet_send(); |
(r = sshpkt_send(ssh)) != 0) |
|
sshpkt_fatal(ssh, r, "%s: exit reply", __func__); |
} else { |
} else { |
/* Some weird exit cause. Just exit. */ |
/* Some weird exit cause. Just exit. */ |
packet_disconnect("wait returned status %04x.", status); |
ssh_packet_disconnect(ssh, "wait returned status %04x.", status); |
} |
} |
|
|
/* disconnect channel */ |
/* disconnect channel */ |
|
|
u_int i; |
u_int i; |
|
|
if (!auth_opts->permit_x11_forwarding_flag) { |
if (!auth_opts->permit_x11_forwarding_flag) { |
packet_send_debug("X11 forwarding disabled by key options."); |
ssh_packet_send_debug(ssh, "X11 forwarding disabled by key options."); |
return 0; |
return 0; |
} |
} |
if (!options.x11_forwarding) { |
if (!options.x11_forwarding) { |
|
|
} |
} |
if (options.xauth_location == NULL || |
if (options.xauth_location == NULL || |
(stat(options.xauth_location, &st) == -1)) { |
(stat(options.xauth_location, &st) == -1)) { |
packet_send_debug("No xauth program; cannot forward X11."); |
ssh_packet_send_debug(ssh, "No xauth program; cannot forward X11."); |
return 0; |
return 0; |
} |
} |
if (s->display != NULL) { |
if (s->display != NULL) { |