version 1.435, 2023/12/18 14:47:20 |
version 1.436, 2024/01/09 22:19:00 |
|
|
/* Channel timeouts by type */ |
/* Channel timeouts by type */ |
struct ssh_channel_timeout *timeouts; |
struct ssh_channel_timeout *timeouts; |
size_t ntimeouts; |
size_t ntimeouts; |
|
/* Global timeout for all OPEN channels */ |
|
int global_deadline; |
|
time_t lastused; |
}; |
}; |
|
|
/* helper */ |
/* helper */ |
|
|
{ |
{ |
struct ssh_channels *sc = ssh->chanctxt; |
struct ssh_channels *sc = ssh->chanctxt; |
|
|
|
if (strcmp(type_pattern, "global") == 0) { |
|
debug2_f("global channel timeout %d seconds", timeout_secs); |
|
sc->global_deadline = timeout_secs; |
|
return; |
|
} |
debug2_f("channel type \"%s\" timeout %d seconds", |
debug2_f("channel type \"%s\" timeout %d seconds", |
type_pattern, timeout_secs); |
type_pattern, timeout_secs); |
sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts, |
sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts, |
|
|
} |
} |
|
|
/* |
/* |
|
* update "last used" time on a channel. |
|
* NB. nothing else should update lastused except to clear it. |
|
*/ |
|
static void |
|
channel_set_used_time(struct ssh *ssh, Channel *c) |
|
{ |
|
ssh->chanctxt->lastused = monotime(); |
|
if (c != NULL) |
|
c->lastused = ssh->chanctxt->lastused; |
|
} |
|
|
|
/* |
|
* Get the time at which a channel is due to time out for inactivity. |
|
* Returns 0 if the channel is not due to time out ever. |
|
*/ |
|
static time_t |
|
channel_get_expiry(struct ssh *ssh, Channel *c) |
|
{ |
|
struct ssh_channels *sc = ssh->chanctxt; |
|
time_t expiry = 0, channel_expiry; |
|
|
|
if (sc->lastused != 0 && sc->global_deadline != 0) |
|
expiry = sc->lastused + sc->global_deadline; |
|
if (c->lastused != 0 && c->inactive_deadline != 0) { |
|
channel_expiry = c->lastused + c->inactive_deadline; |
|
if (expiry == 0 || channel_expiry < expiry) |
|
expiry = channel_expiry; |
|
} |
|
return expiry; |
|
} |
|
|
|
/* |
* Register filedescriptors for a channel, used when allocating a channel or |
* Register filedescriptors for a channel, used when allocating a channel or |
* when the channel consumer/producer is ready, e.g. shell exec'd |
* when the channel consumer/producer is ready, e.g. shell exec'd |
*/ |
*/ |
|
|
if (efd != -1) |
if (efd != -1) |
set_nonblock(efd); |
set_nonblock(efd); |
} |
} |
|
/* channel might be entering a larval state, so reset global timeout */ |
|
channel_set_used_time(ssh, NULL); |
} |
} |
|
|
/* |
/* |
|
|
|
|
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); |
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
c->local_window = c->local_window_max = window_max; |
c->local_window = c->local_window_max = window_max; |
|
|
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
|
|
|
|
if (ret == 1) { |
if (ret == 1) { |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
channel_pre_open(ssh, c); |
channel_pre_open(ssh, c); |
} else if (ret == -1) { |
} else if (ret == -1) { |
logit("X11 connection rejected because of wrong " |
logit("X11 connection rejected because of wrong " |
|
|
c->self, c->connect_ctx.host, c->connect_ctx.port); |
c->self, c->connect_ctx.host, c->connect_ctx.port); |
channel_connect_ctx_free(&c->connect_ctx); |
channel_connect_ctx_free(&c->connect_ctx); |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
if (isopen) { |
if (isopen) { |
/* no message necessary */ |
/* no message necessary */ |
} else { |
} else { |
|
|
goto rfail; |
goto rfail; |
} |
} |
if (nr != 0) |
if (nr != 0) |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
return 1; |
return 1; |
} |
} |
|
|
|
|
} |
} |
return -1; |
return -1; |
} |
} |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
if (c->input_filter != NULL) { |
if (c->input_filter != NULL) { |
if (c->input_filter(ssh, c, buf, len) == -1) { |
if (c->input_filter(ssh, c, buf, len) == -1) { |
debug2("channel %d: filter stops", c->self); |
debug2("channel %d: filter stops", c->self); |
|
|
} |
} |
return -1; |
return -1; |
} |
} |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
if (c->isatty && dlen >= 1 && buf[0] != '\r') { |
if (c->isatty && dlen >= 1 && buf[0] != '\r') { |
if (tcgetattr(c->wfd, &tio) == 0 && |
if (tcgetattr(c->wfd, &tio) == 0 && |
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
|
|
if ((r = sshbuf_consume(c->extended, len)) != 0) |
if ((r = sshbuf_consume(c->extended, len)) != 0) |
fatal_fr(r, "channel %i: consume", c->self); |
fatal_fr(r, "channel %i: consume", c->self); |
c->local_consumed += len; |
c->local_consumed += len; |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
} |
} |
return 1; |
return 1; |
} |
} |
|
|
channel_close_fd(ssh, c, &c->efd); |
channel_close_fd(ssh, c, &c->efd); |
return 1; |
return 1; |
} |
} |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
if (c->extended_usage == CHAN_EXTENDED_IGNORE) |
if (c->extended_usage == CHAN_EXTENDED_IGNORE) |
debug3("channel %d: discard efd", c->self); |
debug3("channel %d: discard efd", c->self); |
else if ((r = sshbuf_put(c->extended, buf, len)) != 0) |
else if ((r = sshbuf_put(c->extended, buf, len)) != 0) |
|
|
continue; |
continue; |
} |
} |
if (ftab[c->type] != NULL) { |
if (ftab[c->type] != NULL) { |
if (table == CHAN_PRE && |
if (table == CHAN_PRE && c->type == SSH_CHANNEL_OPEN && |
c->type == SSH_CHANNEL_OPEN && |
channel_get_expiry(ssh, c) != 0 && |
c->inactive_deadline != 0 && c->lastused != 0 && |
now >= channel_get_expiry(ssh, c)) { |
now >= c->lastused + c->inactive_deadline) { |
|
/* channel closed for inactivity */ |
/* channel closed for inactivity */ |
verbose("channel %d: closing after %u seconds " |
verbose("channel %d: closing after %u seconds " |
"of inactivity", c->self, |
"of inactivity", c->self, |
|
|
/* inactivity timeouts must interrupt poll() */ |
/* inactivity timeouts must interrupt poll() */ |
if (timeout != NULL && |
if (timeout != NULL && |
c->type == SSH_CHANNEL_OPEN && |
c->type == SSH_CHANNEL_OPEN && |
c->lastused != 0 && |
channel_get_expiry(ssh, c) != 0) { |
c->inactive_deadline != 0) { |
|
ptimeout_deadline_monotime(timeout, |
ptimeout_deadline_monotime(timeout, |
c->lastused + c->inactive_deadline); |
channel_get_expiry(ssh, c)); |
} |
} |
} else if (timeout != NULL) { |
} else if (timeout != NULL) { |
/* |
/* |
|
|
c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); |
c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); |
debug2_f("channel %d: callback done", c->self); |
debug2_f("channel %d: callback done", c->self); |
} |
} |
c->lastused = monotime(); |
channel_set_used_time(ssh, c); |
debug2("channel %d: open confirm rwindow %u rmax %u", c->self, |
debug2("channel %d: open confirm rwindow %u rmax %u", c->self, |
c->remote_window, c->remote_maxpacket); |
c->remote_window, c->remote_maxpacket); |
return 0; |
return 0; |