summaryrefslogtreecommitdiff
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 bc56709b1..567159410 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.196 2017/08/30 03:59:08 djm Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.197 2017/09/12 06:32:07 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -165,7 +165,7 @@ sigterm_handler(int sig)
165} 165}
166 166
167static void 167static void
168client_alive_check(void) 168client_alive_check(struct ssh *ssh)
169{ 169{
170 int channel_id; 170 int channel_id;
171 171
@@ -179,12 +179,13 @@ client_alive_check(void)
179 * send a bogus global/channel request with "wantreply", 179 * send a bogus global/channel request with "wantreply",
180 * we should get back a failure 180 * we should get back a failure
181 */ 181 */
182 if ((channel_id = channel_find_open()) == -1) { 182 if ((channel_id = channel_find_open(ssh)) == -1) {
183 packet_start(SSH2_MSG_GLOBAL_REQUEST); 183 packet_start(SSH2_MSG_GLOBAL_REQUEST);
184 packet_put_cstring("keepalive@openssh.com"); 184 packet_put_cstring("keepalive@openssh.com");
185 packet_put_char(1); /* boolean: want reply */ 185 packet_put_char(1); /* boolean: want reply */
186 } else { 186 } else {
187 channel_request_start(channel_id, "keepalive@openssh.com", 1); 187 channel_request_start(ssh, channel_id,
188 "keepalive@openssh.com", 1);
188 } 189 }
189 packet_send(); 190 packet_send();
190} 191}
@@ -196,7 +197,8 @@ client_alive_check(void)
196 * for the duration of the wait (0 = infinite). 197 * for the duration of the wait (0 = infinite).
197 */ 198 */
198static void 199static void
199wait_until_can_do_something(int connection_in, int connection_out, 200wait_until_can_do_something(struct ssh *ssh,
201 int connection_in, int connection_out,
200 fd_set **readsetp, fd_set **writesetp, int *maxfdp, 202 fd_set **readsetp, fd_set **writesetp, int *maxfdp,
201 u_int *nallocp, u_int64_t max_time_ms) 203 u_int *nallocp, u_int64_t max_time_ms)
202{ 204{
@@ -207,7 +209,7 @@ wait_until_can_do_something(int connection_in, int connection_out,
207 static time_t last_client_time; 209 static time_t last_client_time;
208 210
209 /* Allocate and update select() masks for channel descriptors. */ 211 /* Allocate and update select() masks for channel descriptors. */
210 channel_prepare_select(active_state, readsetp, writesetp, maxfdp, 212 channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
211 nallocp, &minwait_secs); 213 nallocp, &minwait_secs);
212 214
213 /* XXX need proper deadline system for rekey/client alive */ 215 /* XXX need proper deadline system for rekey/client alive */
@@ -273,12 +275,12 @@ wait_until_can_do_something(int connection_in, int connection_out,
273 time_t now = monotime(); 275 time_t now = monotime();
274 276
275 if (ret == 0) { /* timeout */ 277 if (ret == 0) { /* timeout */
276 client_alive_check(); 278 client_alive_check(ssh);
277 } else if (FD_ISSET(connection_in, *readsetp)) { 279 } else if (FD_ISSET(connection_in, *readsetp)) {
278 last_client_time = now; 280 last_client_time = now;
279 } else if (last_client_time != 0 && last_client_time + 281 } else if (last_client_time != 0 && last_client_time +
280 options.client_alive_interval <= now) { 282 options.client_alive_interval <= now) {
281 client_alive_check(); 283 client_alive_check(ssh);
282 last_client_time = now; 284 last_client_time = now;
283 } 285 }
284 } 286 }
@@ -291,9 +293,8 @@ wait_until_can_do_something(int connection_in, int connection_out,
291 * in buffers and processed later. 293 * in buffers and processed later.
292 */ 294 */
293static int 295static int
294process_input(fd_set *readset, int connection_in) 296process_input(struct ssh *ssh, fd_set *readset, int connection_in)
295{ 297{
296 struct ssh *ssh = active_state; /* XXX */
297 int len; 298 int len;
298 char buf[16384]; 299 char buf[16384];
299 300
@@ -333,13 +334,13 @@ process_output(fd_set *writeset, int connection_out)
333} 334}
334 335
335static void 336static void
336process_buffered_input_packets(void) 337process_buffered_input_packets(struct ssh *ssh)
337{ 338{
338 ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, NULL); 339 ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
339} 340}
340 341
341static void 342static void
342collect_children(void) 343collect_children(struct ssh *ssh)
343{ 344{
344 pid_t pid; 345 pid_t pid;
345 sigset_t oset, nset; 346 sigset_t oset, nset;
@@ -354,14 +355,14 @@ collect_children(void)
354 while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || 355 while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
355 (pid < 0 && errno == EINTR)) 356 (pid < 0 && errno == EINTR))
356 if (pid > 0) 357 if (pid > 0)
357 session_close_by_pid(pid, status); 358 session_close_by_pid(ssh, pid, status);
358 child_terminated = 0; 359 child_terminated = 0;
359 } 360 }
360 sigprocmask(SIG_SETMASK, &oset, NULL); 361 sigprocmask(SIG_SETMASK, &oset, NULL);
361} 362}
362 363
363void 364void
364server_loop2(Authctxt *authctxt) 365server_loop2(struct ssh *ssh, Authctxt *authctxt)
365{ 366{
366 fd_set *readset = NULL, *writeset = NULL; 367 fd_set *readset = NULL, *writeset = NULL;
367 int max_fd; 368 int max_fd;
@@ -389,18 +390,17 @@ server_loop2(Authctxt *authctxt)
389 server_init_dispatch(); 390 server_init_dispatch();
390 391
391 for (;;) { 392 for (;;) {
392 process_buffered_input_packets(); 393 process_buffered_input_packets(ssh);
393 394
394 if (!ssh_packet_is_rekeying(active_state) && 395 if (!ssh_packet_is_rekeying(ssh) &&
395 packet_not_very_much_data_to_write()) 396 packet_not_very_much_data_to_write())
396 channel_output_poll(); 397 channel_output_poll(ssh);
397 if (options.rekey_interval > 0 && 398 if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh))
398 !ssh_packet_is_rekeying(active_state))
399 rekey_timeout_ms = packet_get_rekey_timeout() * 1000; 399 rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
400 else 400 else
401 rekey_timeout_ms = 0; 401 rekey_timeout_ms = 0;
402 402
403 wait_until_can_do_something(connection_in, connection_out, 403 wait_until_can_do_something(ssh, connection_in, connection_out,
404 &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); 404 &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
405 405
406 if (received_sigterm) { 406 if (received_sigterm) {
@@ -409,23 +409,23 @@ server_loop2(Authctxt *authctxt)
409 cleanup_exit(255); 409 cleanup_exit(255);
410 } 410 }
411 411
412 collect_children(); 412 collect_children(ssh);
413 if (!ssh_packet_is_rekeying(active_state)) 413 if (!ssh_packet_is_rekeying(ssh))
414 channel_after_select(active_state, readset, writeset); 414 channel_after_select(ssh, readset, writeset);
415 if (process_input(readset, connection_in) < 0) 415 if (process_input(ssh, readset, connection_in) < 0)
416 break; 416 break;
417 process_output(writeset, connection_out); 417 process_output(writeset, connection_out);
418 } 418 }
419 collect_children(); 419 collect_children(ssh);
420 420
421 free(readset); 421 free(readset);
422 free(writeset); 422 free(writeset);
423 423
424 /* free all channels, no more reads and writes */ 424 /* free all channels, no more reads and writes */
425 channel_free_all(); 425 channel_free_all(ssh);
426 426
427 /* free remaining sessions, e.g. remove wtmp entries */ 427 /* free remaining sessions, e.g. remove wtmp entries */
428 session_destroy_all(NULL); 428 session_destroy_all(ssh, NULL);
429} 429}
430 430
431static int 431static int
@@ -442,7 +442,7 @@ server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
442} 442}
443 443
444static Channel * 444static Channel *
445server_request_direct_tcpip(int *reason, const char **errmsg) 445server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
446{ 446{
447 Channel *c = NULL; 447 Channel *c = NULL;
448 char *target, *originator; 448 char *target, *originator;
@@ -460,7 +460,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
460 /* XXX fine grained permissions */ 460 /* XXX fine grained permissions */
461 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && 461 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
462 !no_port_forwarding_flag && !options.disable_forwarding) { 462 !no_port_forwarding_flag && !options.disable_forwarding) {
463 c = channel_connect_to_port(target, target_port, 463 c = channel_connect_to_port(ssh, target, target_port,
464 "direct-tcpip", "direct-tcpip", reason, errmsg); 464 "direct-tcpip", "direct-tcpip", reason, errmsg);
465 } else { 465 } else {
466 logit("refused local port forward: " 466 logit("refused local port forward: "
@@ -477,7 +477,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
477} 477}
478 478
479static Channel * 479static Channel *
480server_request_direct_streamlocal(void) 480server_request_direct_streamlocal(struct ssh *ssh)
481{ 481{
482 Channel *c = NULL; 482 Channel *c = NULL;
483 char *target, *originator; 483 char *target, *originator;
@@ -499,7 +499,7 @@ server_request_direct_streamlocal(void)
499 if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && 499 if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
500 !no_port_forwarding_flag && !options.disable_forwarding && 500 !no_port_forwarding_flag && !options.disable_forwarding &&
501 (pw->pw_uid == 0 || use_privsep)) { 501 (pw->pw_uid == 0 || use_privsep)) {
502 c = channel_connect_to_path(target, 502 c = channel_connect_to_path(ssh, target,
503 "direct-streamlocal@openssh.com", "direct-streamlocal"); 503 "direct-streamlocal@openssh.com", "direct-streamlocal");
504 } else { 504 } else {
505 logit("refused streamlocal port forward: " 505 logit("refused streamlocal port forward: "
@@ -514,7 +514,7 @@ server_request_direct_streamlocal(void)
514} 514}
515 515
516static Channel * 516static Channel *
517server_request_tun(void) 517server_request_tun(struct ssh *ssh)
518{ 518{
519 Channel *c = NULL; 519 Channel *c = NULL;
520 int mode, tun; 520 int mode, tun;
@@ -544,7 +544,7 @@ server_request_tun(void)
544 sock = tun_open(tun, mode); 544 sock = tun_open(tun, mode);
545 if (sock < 0) 545 if (sock < 0)
546 goto done; 546 goto done;
547 c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, 547 c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
548 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); 548 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
549 c->datagram = 1; 549 c->datagram = 1;
550#if defined(SSH_TUN_FILTER) 550#if defined(SSH_TUN_FILTER)
@@ -560,7 +560,7 @@ server_request_tun(void)
560} 560}
561 561
562static Channel * 562static Channel *
563server_request_session(void) 563server_request_session(struct ssh *ssh)
564{ 564{
565 Channel *c; 565 Channel *c;
566 566
@@ -578,15 +578,15 @@ server_request_session(void)
578 * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all 578 * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
579 * CHANNEL_REQUEST messages is registered. 579 * CHANNEL_REQUEST messages is registered.
580 */ 580 */
581 c = channel_new("session", SSH_CHANNEL_LARVAL, 581 c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
582 -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 582 -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
583 0, "server-session", 1); 583 0, "server-session", 1);
584 if (session_open(the_authctxt, c->self) != 1) { 584 if (session_open(the_authctxt, c->self) != 1) {
585 debug("session open failed, free channel %d", c->self); 585 debug("session open failed, free channel %d", c->self);
586 channel_free(c); 586 channel_free(ssh, c);
587 return NULL; 587 return NULL;
588 } 588 }
589 channel_register_cleanup(c->self, session_close_by_channel, 0); 589 channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
590 return c; 590 return c;
591} 591}
592 592
@@ -608,13 +608,13 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
608 ctype, rchan, rwindow, rmaxpack); 608 ctype, rchan, rwindow, rmaxpack);
609 609
610 if (strcmp(ctype, "session") == 0) { 610 if (strcmp(ctype, "session") == 0) {
611 c = server_request_session(); 611 c = server_request_session(ssh);
612 } else if (strcmp(ctype, "direct-tcpip") == 0) { 612 } else if (strcmp(ctype, "direct-tcpip") == 0) {
613 c = server_request_direct_tcpip(&reason, &errmsg); 613 c = server_request_direct_tcpip(ssh, &reason, &errmsg);
614 } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { 614 } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
615 c = server_request_direct_streamlocal(); 615 c = server_request_direct_streamlocal(ssh);
616 } else if (strcmp(ctype, "tun@openssh.com") == 0) { 616 } else if (strcmp(ctype, "tun@openssh.com") == 0) {
617 c = server_request_tun(); 617 c = server_request_tun(ssh);
618 } 618 }
619 if (c != NULL) { 619 if (c != NULL) {
620 debug("server_input_channel_open: confirm %s", ctype); 620 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)
645} 645}
646 646
647static int 647static int
648server_input_hostkeys_prove(struct sshbuf **respp) 648server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
649{ 649{
650 struct ssh *ssh = active_state; /* XXX */
651 struct sshbuf *resp = NULL; 650 struct sshbuf *resp = NULL;
652 struct sshbuf *sigbuf = NULL; 651 struct sshbuf *sigbuf = NULL;
653 struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; 652 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)
750 packet_send_debug("Server has disabled port forwarding."); 749 packet_send_debug("Server has disabled port forwarding.");
751 } else { 750 } else {
752 /* Start listening on the port */ 751 /* Start listening on the port */
753 success = channel_setup_remote_fwd_listener(&fwd, 752 success = channel_setup_remote_fwd_listener(ssh, &fwd,
754 &allocated_listen_port, &options.fwd_opts); 753 &allocated_listen_port, &options.fwd_opts);
755 } 754 }
756 free(fwd.listen_host); 755 free(fwd.listen_host);
@@ -768,7 +767,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
768 debug("%s: cancel-tcpip-forward addr %s port %d", __func__, 767 debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
769 fwd.listen_host, fwd.listen_port); 768 fwd.listen_host, fwd.listen_port);
770 769
771 success = channel_cancel_rport_listener(&fwd); 770 success = channel_cancel_rport_listener(ssh, &fwd);
772 free(fwd.listen_host); 771 free(fwd.listen_host);
773 } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { 772 } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
774 struct Forward fwd; 773 struct Forward fwd;
@@ -787,7 +786,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
787 "streamlocal forwarding."); 786 "streamlocal forwarding.");
788 } else { 787 } else {
789 /* Start listening on the socket */ 788 /* Start listening on the socket */
790 success = channel_setup_remote_fwd_listener( 789 success = channel_setup_remote_fwd_listener(ssh,
791 &fwd, NULL, &options.fwd_opts); 790 &fwd, NULL, &options.fwd_opts);
792 } 791 }
793 free(fwd.listen_path); 792 free(fwd.listen_path);
@@ -799,19 +798,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
799 debug("%s: cancel-streamlocal-forward path %s", __func__, 798 debug("%s: cancel-streamlocal-forward path %s", __func__,
800 fwd.listen_path); 799 fwd.listen_path);
801 800
802 success = channel_cancel_rport_listener(&fwd); 801 success = channel_cancel_rport_listener(ssh, &fwd);
803 free(fwd.listen_path); 802 free(fwd.listen_path);
804 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { 803 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
805 no_more_sessions = 1; 804 no_more_sessions = 1;
806 success = 1; 805 success = 1;
807 } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { 806 } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
808 success = server_input_hostkeys_prove(&resp); 807 success = server_input_hostkeys_prove(ssh, &resp);
809 } 808 }
810 if (want_reply) { 809 if (want_reply) {
811 packet_start(success ? 810 packet_start(success ?
812 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); 811 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
813 if (success && resp != NULL) 812 if (success && resp != NULL)
814 ssh_packet_put_raw(active_state, sshbuf_ptr(resp), 813 ssh_packet_put_raw(ssh, sshbuf_ptr(resp),
815 sshbuf_len(resp)); 814 sshbuf_len(resp));
816 packet_send(); 815 packet_send();
817 packet_write_wait(); 816 packet_write_wait();
@@ -835,15 +834,15 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
835 debug("server_input_channel_req: channel %d request %s reply %d", 834 debug("server_input_channel_req: channel %d request %s reply %d",
836 id, rtype, reply); 835 id, rtype, reply);
837 836
838 if ((c = channel_lookup(id)) == NULL) 837 if ((c = channel_lookup(ssh, id)) == NULL)
839 packet_disconnect("server_input_channel_req: " 838 packet_disconnect("server_input_channel_req: "
840 "unknown channel %d", id); 839 "unknown channel %d", id);
841 if (!strcmp(rtype, "eow@openssh.com")) { 840 if (!strcmp(rtype, "eow@openssh.com")) {
842 packet_check_eom(); 841 packet_check_eom();
843 chan_rcvd_eow(c); 842 chan_rcvd_eow(ssh, c);
844 } else if ((c->type == SSH_CHANNEL_LARVAL || 843 } else if ((c->type == SSH_CHANNEL_LARVAL ||
845 c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) 844 c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
846 success = session_input_channel_req(c, rtype); 845 success = session_input_channel_req(ssh, c, rtype);
847 if (reply && !(c->flags & CHAN_CLOSE_SENT)) { 846 if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
848 packet_start(success ? 847 packet_start(success ?
849 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 848 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);