version 1.388, 2019/01/19 21:31:32 |
version 1.389, 2019/01/19 21:37:13 |
|
|
#include "pathnames.h" |
#include "pathnames.h" |
#include "match.h" |
#include "match.h" |
|
|
#include "opacket.h" /* XXX */ |
|
extern struct ssh *active_state; /* XXX */ |
|
|
|
/* -- agent forwarding */ |
/* -- agent forwarding */ |
#define NUM_SOCKS 10 |
#define NUM_SOCKS 10 |
|
|
|
|
return 0; |
return 0; |
|
|
/* Get the data. */ |
/* Get the data. */ |
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) |
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) |
fatal("%s: channel %d: get data: %s", __func__, |
fatal("%s: channel %d: get data: %s", __func__, |
c->self, ssh_err(r)); |
c->self, ssh_err(r)); |
ssh_packet_check_eom(ssh); |
|
|
|
win_len = data_len; |
win_len = data_len; |
if (c->datagram) |
if (c->datagram) |
|
|
logit("channel %d: bad ext data", c->self); |
logit("channel %d: bad ext data", c->self); |
return 0; |
return 0; |
} |
} |
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) { |
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) { |
error("%s: parse data: %s", __func__, ssh_err(r)); |
error("%s: parse data: %s", __func__, ssh_err(r)); |
ssh_packet_disconnect(ssh, "Invalid extended_data message"); |
ssh_packet_disconnect(ssh, "Invalid extended_data message"); |
} |
} |
ssh_packet_check_eom(ssh); |
|
|
|
if (data_len > c->local_window) { |
if (data_len > c->local_window) { |
logit("channel %d: rcvd too much extended_data %zu, win %u", |
logit("channel %d: rcvd too much extended_data %zu, win %u", |
|
|
channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) |
channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) |
{ |
{ |
Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); |
Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); |
|
int r; |
|
|
ssh_packet_check_eom(ssh); |
if ((r = sshpkt_get_end(ssh)) != 0) { |
|
error("%s: parse data: %s", __func__, ssh_err(r)); |
|
ssh_packet_disconnect(ssh, "Invalid ieof message"); |
|
} |
|
|
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
|
|
channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) |
channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) |
{ |
{ |
Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); |
Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); |
|
int r; |
|
|
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
ssh_packet_check_eom(ssh); |
if ((r = sshpkt_get_end(ssh)) != 0) { |
|
error("%s: parse data: %s", __func__, ssh_err(r)); |
|
ssh_packet_disconnect(ssh, "Invalid oclose message"); |
|
} |
chan_rcvd_oclose(ssh, c); |
chan_rcvd_oclose(ssh, c); |
return 0; |
return 0; |
} |
} |
|
|
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
if (c->type != SSH_CHANNEL_OPENING) |
if (c->type != SSH_CHANNEL_OPENING) |
packet_disconnect("Received open confirmation for " |
ssh_packet_disconnect(ssh, "Received open confirmation for " |
"non-opening channel %d.", c->self); |
"non-opening channel %d.", c->self); |
/* |
/* |
* Record the remote channel number and mark that the channel |
* Record the remote channel number and mark that the channel |
|
|
*/ |
*/ |
if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || |
if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || |
(r = sshpkt_get_u32(ssh, &remote_window)) != 0 || |
(r = sshpkt_get_u32(ssh, &remote_window)) != 0 || |
(r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { |
(r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) { |
error("%s: window/maxpacket: %s", __func__, ssh_err(r)); |
error("%s: window/maxpacket: %s", __func__, ssh_err(r)); |
packet_disconnect("Invalid open confirmation message"); |
ssh_packet_disconnect(ssh, "Invalid open confirmation message"); |
} |
} |
ssh_packet_check_eom(ssh); |
|
|
|
c->have_remote_id = 1; |
c->have_remote_id = 1; |
c->remote_window = remote_window; |
c->remote_window = remote_window; |
|
|
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
if (c->type != SSH_CHANNEL_OPENING) |
if (c->type != SSH_CHANNEL_OPENING) |
packet_disconnect("Received open failure for " |
ssh_packet_disconnect(ssh, "Received open failure for " |
"non-opening channel %d.", c->self); |
"non-opening channel %d.", c->self); |
if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { |
if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { |
error("%s: reason: %s", __func__, ssh_err(r)); |
error("%s: reason: %s", __func__, ssh_err(r)); |
packet_disconnect("Invalid open failure message"); |
ssh_packet_disconnect(ssh, "Invalid open failure message"); |
} |
} |
/* skip language */ |
/* skip language */ |
if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || |
if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || |
(r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0) { |
(r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) { |
error("%s: message/lang: %s", __func__, ssh_err(r)); |
error("%s: message/lang: %s", __func__, ssh_err(r)); |
packet_disconnect("Invalid open failure message"); |
ssh_packet_disconnect(ssh, "Invalid open failure message"); |
} |
} |
ssh_packet_check_eom(ssh); |
|
logit("channel %d: open failed: %s%s%s", c->self, |
logit("channel %d: open failed: %s%s%s", c->self, |
reason2txt(reason), msg ? ": ": "", msg ? msg : ""); |
reason2txt(reason), msg ? ": ": "", msg ? msg : ""); |
free(msg); |
free(msg); |
|
|
|
|
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) { |
if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 || |
|
(r = sshpkt_get_end(ssh)) != 0) { |
error("%s: adjust: %s", __func__, ssh_err(r)); |
error("%s: adjust: %s", __func__, ssh_err(r)); |
packet_disconnect("Invalid window adjust message"); |
ssh_packet_disconnect(ssh, "Invalid window adjust message"); |
} |
} |
ssh_packet_check_eom(ssh); |
|
debug2("channel %d: rcvd adjust %u", c->self, adjust); |
debug2("channel %d: rcvd adjust %u", c->self, adjust); |
if ((new_rwin = c->remote_window + adjust) < c->remote_window) { |
if ((new_rwin = c->remote_window + adjust) < c->remote_window) { |
fatal("channel %d: adjust %u overflows remote window %u", |
fatal("channel %d: adjust %u overflows remote window %u", |
|
|
int id = channel_parse_id(ssh, __func__, "status confirm"); |
int id = channel_parse_id(ssh, __func__, "status confirm"); |
Channel *c; |
Channel *c; |
struct channel_confirm *cc; |
struct channel_confirm *cc; |
|
int r; |
|
|
/* Reset keepalive timeout */ |
/* Reset keepalive timeout */ |
packet_set_alive_timeouts(0); |
ssh_packet_set_alive_timeouts(ssh, 0); |
|
|
debug2("%s: type %d id %d", __func__, type, id); |
debug2("%s: type %d id %d", __func__, type, id); |
|
|
|
|
} |
} |
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
ssh_packet_check_eom(ssh); |
if ((r = sshpkt_get_end(ssh)) != 0) |
|
ssh_packet_disconnect(ssh, "Invalid status confirm message"); |
if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) |
if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) |
return 0; |
return 0; |
cc->cb(ssh, type, c, cc->ctx); |
cc->cb(ssh, type, c, cc->ctx); |
|
|
* "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set |
* "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set |
*/ |
*/ |
static const char * |
static const char * |
channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, |
channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp, |
int is_client, struct ForwardOptions *fwd_opts) |
int is_client, struct ForwardOptions *fwd_opts) |
{ |
{ |
const char *addr = NULL; |
const char *addr = NULL; |
|
|
if (*listen_addr != '\0' && |
if (*listen_addr != '\0' && |
strcmp(listen_addr, "0.0.0.0") != 0 && |
strcmp(listen_addr, "0.0.0.0") != 0 && |
strcmp(listen_addr, "*") != 0) { |
strcmp(listen_addr, "*") != 0) { |
packet_send_debug("Forwarding listen address " |
ssh_packet_send_debug(ssh, |
|
"Forwarding listen address " |
"\"%s\" overridden by server " |
"\"%s\" overridden by server " |
"GatewayPorts", listen_addr); |
"GatewayPorts", listen_addr); |
} |
} |
|
|
} |
} |
|
|
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */ |
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */ |
addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard, |
addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard, |
is_client, fwd_opts); |
is_client, fwd_opts); |
debug3("%s: type %d wildcard %d addr %s", __func__, |
debug3("%s: type %d wildcard %d addr %s", __func__, |
type, wildcard, (addr == NULL) ? "NULL" : addr); |
type, wildcard, (addr == NULL) ? "NULL" : addr); |
|
|
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { |
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { |
if (addr == NULL) { |
if (addr == NULL) { |
/* This really shouldn't happen */ |
/* This really shouldn't happen */ |
packet_disconnect("getaddrinfo: fatal error: %s", |
ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s", |
ssh_gai_strerror(r)); |
ssh_gai_strerror(r)); |
} else { |
} else { |
error("%s: getaddrinfo(%.64s): %s", __func__, addr, |
error("%s: getaddrinfo(%.64s): %s", __func__, addr, |
|
|
{ |
{ |
u_int i; |
u_int i; |
int found = 0; |
int found = 0; |
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); |
const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts); |
|
|
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
Channel *c = ssh->chanctxt->channels[i]; |
Channel *c = ssh->chanctxt->channels[i]; |
|
|
int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
{ |
{ |
if (!check_rfwd_permission(ssh, fwd)) { |
if (!check_rfwd_permission(ssh, fwd)) { |
packet_send_debug("port forwarding refused"); |
ssh_packet_send_debug(ssh, "port forwarding refused"); |
return 0; |
return 0; |
} |
} |
if (fwd->listen_path != NULL) { |
if (fwd->listen_path != NULL) { |