summaryrefslogtreecommitdiffstats
path: root/serverloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2017-09-12 06:32:07 +0000
committerDamien Miller <djm@mindrot.org>2017-09-12 17:37:02 +1000
commitdbee4119b502e3f8b6cd3282c69c537fd01d8e16 (patch)
treeb8a3263a79e0920e8d08f188654f1ccb7c254406 /serverloop.c
parentabd59663df37a42152e37980113ccaa405b9a282 (diff)
upstream commit
refactor channels.c Move static state to a "struct ssh_channels" that is allocated at runtime and tracked as a member of struct ssh. Explicitly pass "struct ssh" to all channels functions. Replace use of the legacy packet APIs in channels.c. Rework sshd_config PermitOpen handling: previously the configuration parser would call directly into the channels layer. After the refactor this is not possible, as the channels structures are allocated at connection time and aren't available when the configuration is parsed. The server config parser now tracks PermitOpen itself and explicitly configures the channels code later. ok markus@ Upstream-ID: 11828f161656b965cc306576422613614bea2d8f
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/serverloop.c b/serverloop.c
index bc56709b..56715941 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.196 2017/08/30 03:59:08 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.197 2017/09/12 06:32:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -165,7 +165,7 @@ sigterm_handler(int sig)
}
static void
-client_alive_check(void)
+client_alive_check(struct ssh *ssh)
{
int channel_id;
@@ -179,12 +179,13 @@ client_alive_check(void)
* send a bogus global/channel request with "wantreply",
* we should get back a failure
*/
- if ((channel_id = channel_find_open()) == -1) {
+ if ((channel_id = channel_find_open(ssh)) == -1) {
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("keepalive@openssh.com");
packet_put_char(1); /* boolean: want reply */
} else {
- channel_request_start(channel_id, "keepalive@openssh.com", 1);
+ channel_request_start(ssh, channel_id,
+ "keepalive@openssh.com", 1);
}
packet_send();
}
@@ -196,7 +197,8 @@ client_alive_check(void)
* for the duration of the wait (0 = infinite).
*/
static void
-wait_until_can_do_something(int connection_in, int connection_out,
+wait_until_can_do_something(struct ssh *ssh,
+ int connection_in, int connection_out,
fd_set **readsetp, fd_set **writesetp, int *maxfdp,
u_int *nallocp, u_int64_t max_time_ms)
{
@@ -207,7 +209,7 @@ wait_until_can_do_something(int connection_in, int connection_out,
static time_t last_client_time;
/* Allocate and update select() masks for channel descriptors. */
- channel_prepare_select(active_state, readsetp, writesetp, maxfdp,
+ channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
nallocp, &minwait_secs);
/* XXX need proper deadline system for rekey/client alive */
@@ -273,12 +275,12 @@ wait_until_can_do_something(int connection_in, int connection_out,
time_t now = monotime();
if (ret == 0) { /* timeout */
- client_alive_check();
+ client_alive_check(ssh);
} else if (FD_ISSET(connection_in, *readsetp)) {
last_client_time = now;
} else if (last_client_time != 0 && last_client_time +
options.client_alive_interval <= now) {
- client_alive_check();
+ client_alive_check(ssh);
last_client_time = now;
}
}
@@ -291,9 +293,8 @@ wait_until_can_do_something(int connection_in, int connection_out,
* in buffers and processed later.
*/
static int
-process_input(fd_set *readset, int connection_in)
+process_input(struct ssh *ssh, fd_set *readset, int connection_in)
{
- struct ssh *ssh = active_state; /* XXX */
int len;
char buf[16384];
@@ -333,13 +334,13 @@ process_output(fd_set *writeset, int connection_out)
}
static void
-process_buffered_input_packets(void)
+process_buffered_input_packets(struct ssh *ssh)
{
- ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, NULL);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
}
static void
-collect_children(void)
+collect_children(struct ssh *ssh)
{
pid_t pid;
sigset_t oset, nset;
@@ -354,14 +355,14 @@ collect_children(void)
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
if (pid > 0)
- session_close_by_pid(pid, status);
+ session_close_by_pid(ssh, pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
}
void
-server_loop2(Authctxt *authctxt)
+server_loop2(struct ssh *ssh, Authctxt *authctxt)
{
fd_set *readset = NULL, *writeset = NULL;
int max_fd;
@@ -389,18 +390,17 @@ server_loop2(Authctxt *authctxt)
server_init_dispatch();
for (;;) {
- process_buffered_input_packets();
+ process_buffered_input_packets(ssh);
- if (!ssh_packet_is_rekeying(active_state) &&
+ if (!ssh_packet_is_rekeying(ssh) &&
packet_not_very_much_data_to_write())
- channel_output_poll();
- if (options.rekey_interval > 0 &&
- !ssh_packet_is_rekeying(active_state))
+ channel_output_poll(ssh);
+ if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh))
rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
else
rekey_timeout_ms = 0;
- wait_until_can_do_something(connection_in, connection_out,
+ wait_until_can_do_something(ssh, connection_in, connection_out,
&readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
if (received_sigterm) {
@@ -409,23 +409,23 @@ server_loop2(Authctxt *authctxt)
cleanup_exit(255);
}
- collect_children();
- if (!ssh_packet_is_rekeying(active_state))
- channel_after_select(active_state, readset, writeset);
- if (process_input(readset, connection_in) < 0)
+ collect_children(ssh);
+ if (!ssh_packet_is_rekeying(ssh))
+ channel_after_select(ssh, readset, writeset);
+ if (process_input(ssh, readset, connection_in) < 0)
break;
process_output(writeset, connection_out);
}
- collect_children();
+ collect_children(ssh);
free(readset);
free(writeset);
/* free all channels, no more reads and writes */
- channel_free_all();
+ channel_free_all(ssh);
/* free remaining sessions, e.g. remove wtmp entries */
- session_destroy_all(NULL);
+ session_destroy_all(ssh, NULL);
}
static int
@@ -442,7 +442,7 @@ server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
}
static Channel *
-server_request_direct_tcpip(int *reason, const char **errmsg)
+server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
{
Channel *c = NULL;
char *target, *originator;
@@ -460,7 +460,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding) {
- c = channel_connect_to_port(target, target_port,
+ c = channel_connect_to_port(ssh, target, target_port,
"direct-tcpip", "direct-tcpip", reason, errmsg);
} else {
logit("refused local port forward: "
@@ -477,7 +477,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
}
static Channel *
-server_request_direct_streamlocal(void)
+server_request_direct_streamlocal(struct ssh *ssh)
{
Channel *c = NULL;
char *target, *originator;
@@ -499,7 +499,7 @@ server_request_direct_streamlocal(void)
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding &&
(pw->pw_uid == 0 || use_privsep)) {
- c = channel_connect_to_path(target,
+ c = channel_connect_to_path(ssh, target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
logit("refused streamlocal port forward: "
@@ -514,7 +514,7 @@ server_request_direct_streamlocal(void)
}
static Channel *
-server_request_tun(void)
+server_request_tun(struct ssh *ssh)
{
Channel *c = NULL;
int mode, tun;
@@ -544,7 +544,7 @@ server_request_tun(void)
sock = tun_open(tun, mode);
if (sock < 0)
goto done;
- c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+ c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
#if defined(SSH_TUN_FILTER)
@@ -560,7 +560,7 @@ server_request_tun(void)
}
static Channel *
-server_request_session(void)
+server_request_session(struct ssh *ssh)
{
Channel *c;
@@ -578,15 +578,15 @@ server_request_session(void)
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
- c = channel_new("session", SSH_CHANNEL_LARVAL,
+ c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
-1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
0, "server-session", 1);
if (session_open(the_authctxt, c->self) != 1) {
debug("session open failed, free channel %d", c->self);
- channel_free(c);
+ channel_free(ssh, c);
return NULL;
}
- channel_register_cleanup(c->self, session_close_by_channel, 0);
+ channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
return c;
}
@@ -608,13 +608,13 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) {
- c = server_request_session();
+ c = server_request_session(ssh);
} else if (strcmp(ctype, "direct-tcpip") == 0) {
- c = server_request_direct_tcpip(&reason, &errmsg);
+ c = server_request_direct_tcpip(ssh, &reason, &errmsg);
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
- c = server_request_direct_streamlocal();
+ c = server_request_direct_streamlocal(ssh);
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
- c = server_request_tun();
+ c = server_request_tun(ssh);
}
if (c != NULL) {
debug("server_input_channel_open: confirm %s", ctype);
@@ -645,9 +645,8 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
}
static int
-server_input_hostkeys_prove(struct sshbuf **respp)
+server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *resp = NULL;
struct sshbuf *sigbuf = NULL;
struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
@@ -750,7 +749,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
packet_send_debug("Server has disabled port forwarding.");
} else {
/* Start listening on the port */
- success = channel_setup_remote_fwd_listener(&fwd,
+ success = channel_setup_remote_fwd_listener(ssh, &fwd,
&allocated_listen_port, &options.fwd_opts);
}
free(fwd.listen_host);
@@ -768,7 +767,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
fwd.listen_host, fwd.listen_port);
- success = channel_cancel_rport_listener(&fwd);
+ success = channel_cancel_rport_listener(ssh, &fwd);
free(fwd.listen_host);
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
struct Forward fwd;
@@ -787,7 +786,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
"streamlocal forwarding.");
} else {
/* Start listening on the socket */
- success = channel_setup_remote_fwd_listener(
+ success = channel_setup_remote_fwd_listener(ssh,
&fwd, NULL, &options.fwd_opts);
}
free(fwd.listen_path);
@@ -799,19 +798,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
debug("%s: cancel-streamlocal-forward path %s", __func__,
fwd.listen_path);
- success = channel_cancel_rport_listener(&fwd);
+ success = channel_cancel_rport_listener(ssh, &fwd);
free(fwd.listen_path);
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1;
success = 1;
} else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
- success = server_input_hostkeys_prove(&resp);
+ success = server_input_hostkeys_prove(ssh, &resp);
}
if (want_reply) {
packet_start(success ?
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
if (success && resp != NULL)
- ssh_packet_put_raw(active_state, sshbuf_ptr(resp),
+ ssh_packet_put_raw(ssh, sshbuf_ptr(resp),
sshbuf_len(resp));
packet_send();
packet_write_wait();
@@ -835,15 +834,15 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
debug("server_input_channel_req: channel %d request %s reply %d",
id, rtype, reply);
- if ((c = channel_lookup(id)) == NULL)
+ if ((c = channel_lookup(ssh, id)) == NULL)
packet_disconnect("server_input_channel_req: "
"unknown channel %d", id);
if (!strcmp(rtype, "eow@openssh.com")) {
packet_check_eom();
- chan_rcvd_eow(c);
+ chan_rcvd_eow(ssh, c);
} else if ((c->type == SSH_CHANNEL_LARVAL ||
c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
- success = session_input_channel_req(c, rtype);
+ success = session_input_channel_req(ssh, c, rtype);
if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
packet_start(success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);