1 /* $OpenBSD: serverloop.c,v 1.198 2017/09/12 06:35:32 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * Server main loop for handling the interactive session.
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
14 * SSH2 support by Markus Friedl.
15 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <sys/types.h>
42 #include <sys/socket.h>
43 #ifdef HAVE_SYS_TIME_H
44 # include <sys/time.h>
47 #include <netinet/in.h>
58 #include "openbsd-compat/sys-queue.h"
77 #include "auth-options.h"
78 #include "serverloop.h"
81 extern ServerOptions options
;
84 extern Authctxt
*the_authctxt
;
85 extern int use_privsep
;
87 static int no_more_sessions
= 0; /* Disallow further sessions. */
90 * This SIGCHLD kludge is used to detect when the child exits. The server
91 * will exit after that, as soon as forwarded connections have terminated.
94 static volatile sig_atomic_t child_terminated
= 0; /* The child has terminated. */
96 /* Cleanup on signals (!use_privsep case only) */
97 static volatile sig_atomic_t received_sigterm
= 0;
100 static void server_init_dispatch(void);
103 * we write to this pipe if a SIGCHLD is caught in order to avoid
104 * the race between select() and child_terminated
106 static int notify_pipe
[2];
110 if (pipe(notify_pipe
) < 0) {
111 error("pipe(notify_pipe) failed %s", strerror(errno
));
112 } else if ((fcntl(notify_pipe
[0], F_SETFD
, FD_CLOEXEC
) == -1) ||
113 (fcntl(notify_pipe
[1], F_SETFD
, FD_CLOEXEC
) == -1)) {
114 error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno
));
115 close(notify_pipe
[0]);
116 close(notify_pipe
[1]);
118 set_nonblock(notify_pipe
[0]);
119 set_nonblock(notify_pipe
[1]);
122 notify_pipe
[0] = -1; /* read end */
123 notify_pipe
[1] = -1; /* write end */
128 if (notify_pipe
[1] != -1)
129 (void)write(notify_pipe
[1], "", 1);
132 notify_prepare(fd_set
*readset
)
134 if (notify_pipe
[0] != -1)
135 FD_SET(notify_pipe
[0], readset
);
138 notify_done(fd_set
*readset
)
142 if (notify_pipe
[0] != -1 && FD_ISSET(notify_pipe
[0], readset
))
143 while (read(notify_pipe
[0], &c
, 1) != -1)
144 debug2("notify_done: reading");
149 sigchld_handler(int sig
)
151 int save_errno
= errno
;
152 child_terminated
= 1;
154 mysignal(SIGCHLD
, sigchld_handler
);
162 sigterm_handler(int sig
)
164 received_sigterm
= sig
;
168 client_alive_check(struct ssh
*ssh
)
172 /* timeout, check to see how many we have had */
173 if (packet_inc_alive_timeouts() > options
.client_alive_count_max
) {
174 logit("Timeout, client not responding.");
179 * send a bogus global/channel request with "wantreply",
180 * we should get back a failure
182 if ((channel_id
= channel_find_open(ssh
)) == -1) {
183 packet_start(SSH2_MSG_GLOBAL_REQUEST
);
184 packet_put_cstring("keepalive@openssh.com");
185 packet_put_char(1); /* boolean: want reply */
187 channel_request_start(ssh
, channel_id
,
188 "keepalive@openssh.com", 1);
194 * Sleep in select() until we can do something. This will initialize the
195 * select masks. Upon return, the masks will indicate which descriptors
196 * have data or can accept data. Optionally, a maximum time can be specified
197 * for the duration of the wait (0 = infinite).
200 wait_until_can_do_something(struct ssh
*ssh
,
201 int connection_in
, int connection_out
,
202 fd_set
**readsetp
, fd_set
**writesetp
, int *maxfdp
,
203 u_int
*nallocp
, u_int64_t max_time_ms
)
205 struct timeval tv
, *tvp
;
207 time_t minwait_secs
= 0;
208 int client_alive_scheduled
= 0;
209 static time_t last_client_time
;
211 /* Allocate and update select() masks for channel descriptors. */
212 channel_prepare_select(ssh
, readsetp
, writesetp
, maxfdp
,
213 nallocp
, &minwait_secs
);
215 /* XXX need proper deadline system for rekey/client alive */
216 if (minwait_secs
!= 0)
217 max_time_ms
= MINIMUM(max_time_ms
, (u_int
)minwait_secs
* 1000);
220 * if using client_alive, set the max timeout accordingly,
221 * and indicate that this particular timeout was for client
222 * alive by setting the client_alive_scheduled flag.
224 * this could be randomized somewhat to make traffic
225 * analysis more difficult, but we're not doing it yet.
227 if (options
.client_alive_interval
) {
228 uint64_t keepalive_ms
=
229 (uint64_t)options
.client_alive_interval
* 1000;
231 client_alive_scheduled
= 1;
232 if (max_time_ms
== 0 || max_time_ms
> keepalive_ms
)
233 max_time_ms
= keepalive_ms
;
237 /* wrong: bad condition XXX */
238 if (channel_not_very_much_buffered_data())
240 FD_SET(connection_in
, *readsetp
);
241 notify_prepare(*readsetp
);
244 * If we have buffered packet data going to the client, mark that
247 if (packet_have_data_to_write())
248 FD_SET(connection_out
, *writesetp
);
251 * If child has terminated and there is enough buffer space to read
252 * from it, then read as much as is available and exit.
254 if (child_terminated
&& packet_not_very_much_data_to_write())
255 if (max_time_ms
== 0 || client_alive_scheduled
)
258 if (max_time_ms
== 0)
261 tv
.tv_sec
= max_time_ms
/ 1000;
262 tv
.tv_usec
= 1000 * (max_time_ms
% 1000);
266 /* Wait for something to happen, or the timeout to expire. */
267 ret
= select((*maxfdp
)+1, *readsetp
, *writesetp
, NULL
, tvp
);
270 memset(*readsetp
, 0, *nallocp
);
271 memset(*writesetp
, 0, *nallocp
);
273 error("select: %.100s", strerror(errno
));
274 } else if (client_alive_scheduled
) {
275 time_t now
= monotime();
277 if (ret
== 0) { /* timeout */
278 client_alive_check(ssh
);
279 } else if (FD_ISSET(connection_in
, *readsetp
)) {
280 last_client_time
= now
;
281 } else if (last_client_time
!= 0 && last_client_time
+
282 options
.client_alive_interval
<= now
) {
283 client_alive_check(ssh
);
284 last_client_time
= now
;
288 notify_done(*readsetp
);
292 * Processes input from the client and the program. Input data is stored
293 * in buffers and processed later.
296 process_input(struct ssh
*ssh
, fd_set
*readset
, int connection_in
)
301 /* Read and buffer any input data from the client. */
302 if (FD_ISSET(connection_in
, readset
)) {
303 len
= read(connection_in
, buf
, sizeof(buf
));
305 verbose("Connection closed by %.100s port %d",
306 ssh_remote_ipaddr(ssh
), ssh_remote_port(ssh
));
308 } else if (len
< 0) {
309 if (errno
!= EINTR
&& errno
!= EAGAIN
&&
310 errno
!= EWOULDBLOCK
) {
311 verbose("Read error from remote host "
312 "%.100s port %d: %.100s",
313 ssh_remote_ipaddr(ssh
),
314 ssh_remote_port(ssh
), strerror(errno
));
318 /* Buffer any received data. */
319 packet_process_incoming(buf
, len
);
326 * Sends data from internal buffers to client program stdin.
329 process_output(fd_set
*writeset
, int connection_out
)
331 /* Send any buffered packet data to the client. */
332 if (FD_ISSET(connection_out
, writeset
))
337 process_buffered_input_packets(struct ssh
*ssh
)
339 ssh_dispatch_run_fatal(ssh
, DISPATCH_NONBLOCK
, NULL
);
343 collect_children(struct ssh
*ssh
)
349 /* block SIGCHLD while we check for dead children */
351 sigaddset(&nset
, SIGCHLD
);
352 sigprocmask(SIG_BLOCK
, &nset
, &oset
);
353 if (child_terminated
) {
354 debug("Received SIGCHLD.");
355 while ((pid
= waitpid(-1, &status
, WNOHANG
)) > 0 ||
356 (pid
< 0 && errno
== EINTR
))
358 session_close_by_pid(ssh
, pid
, status
);
359 child_terminated
= 0;
361 sigprocmask(SIG_SETMASK
, &oset
, NULL
);
365 server_loop2(struct ssh
*ssh
, Authctxt
*authctxt
)
367 fd_set
*readset
= NULL
, *writeset
= NULL
;
369 u_int nalloc
= 0, connection_in
, connection_out
;
370 u_int64_t rekey_timeout_ms
= 0;
372 debug("Entering interactive session for SSH2.");
374 mysignal(SIGCHLD
, sigchld_handler
);
375 child_terminated
= 0;
376 connection_in
= packet_get_connection_in();
377 connection_out
= packet_get_connection_out();
380 signal(SIGTERM
, sigterm_handler
);
381 signal(SIGINT
, sigterm_handler
);
382 signal(SIGQUIT
, sigterm_handler
);
387 max_fd
= MAXIMUM(connection_in
, connection_out
);
388 max_fd
= MAXIMUM(max_fd
, notify_pipe
[0]);
390 server_init_dispatch();
393 process_buffered_input_packets(ssh
);
395 if (!ssh_packet_is_rekeying(ssh
) &&
396 packet_not_very_much_data_to_write())
397 channel_output_poll(ssh
);
398 if (options
.rekey_interval
> 0 && !ssh_packet_is_rekeying(ssh
))
399 rekey_timeout_ms
= packet_get_rekey_timeout() * 1000;
401 rekey_timeout_ms
= 0;
403 wait_until_can_do_something(ssh
, connection_in
, connection_out
,
404 &readset
, &writeset
, &max_fd
, &nalloc
, rekey_timeout_ms
);
406 if (received_sigterm
) {
407 logit("Exiting on signal %d", (int)received_sigterm
);
408 /* Clean up sessions, utmp, etc. */
412 collect_children(ssh
);
413 if (!ssh_packet_is_rekeying(ssh
))
414 channel_after_select(ssh
, readset
, writeset
);
415 if (process_input(ssh
, readset
, connection_in
) < 0)
417 process_output(writeset
, connection_out
);
419 collect_children(ssh
);
424 /* free all channels, no more reads and writes */
425 channel_free_all(ssh
);
427 /* free remaining sessions, e.g. remove wtmp entries */
428 session_destroy_all(ssh
, NULL
);
432 server_input_keep_alive(int type
, u_int32_t seq
, struct ssh
*ssh
)
434 debug("Got %d/%u for keepalive", type
, seq
);
436 * reset timeout, since we got a sane answer from the client.
437 * even if this was generated by something other than
438 * the bogus CHANNEL_REQUEST we send for keepalives.
440 packet_set_alive_timeouts(0);
445 server_request_direct_tcpip(struct ssh
*ssh
, int *reason
, const char **errmsg
)
448 char *target
, *originator
;
449 u_short target_port
, originator_port
;
451 target
= packet_get_string(NULL
);
452 target_port
= packet_get_int();
453 originator
= packet_get_string(NULL
);
454 originator_port
= packet_get_int();
457 debug("server_request_direct_tcpip: originator %s port %d, target %s "
458 "port %d", originator
, originator_port
, target
, target_port
);
460 /* XXX fine grained permissions */
461 if ((options
.allow_tcp_forwarding
& FORWARD_LOCAL
) != 0 &&
462 !no_port_forwarding_flag
&& !options
.disable_forwarding
) {
463 c
= channel_connect_to_port(ssh
, target
, target_port
,
464 "direct-tcpip", "direct-tcpip", reason
, errmsg
);
466 logit("refused local port forward: "
467 "originator %s port %d, target %s port %d",
468 originator
, originator_port
, target
, target_port
);
470 *reason
= SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
;
480 server_request_direct_streamlocal(struct ssh
*ssh
)
483 char *target
, *originator
;
484 u_short originator_port
;
485 struct passwd
*pw
= the_authctxt
->pw
;
487 if (pw
== NULL
|| !the_authctxt
->valid
)
488 fatal("server_input_global_request: no/invalid user");
490 target
= packet_get_string(NULL
);
491 originator
= packet_get_string(NULL
);
492 originator_port
= packet_get_int();
495 debug("server_request_direct_streamlocal: originator %s port %d, target %s",
496 originator
, originator_port
, target
);
498 /* XXX fine grained permissions */
499 if ((options
.allow_streamlocal_forwarding
& FORWARD_LOCAL
) != 0 &&
500 !no_port_forwarding_flag
&& !options
.disable_forwarding
&&
501 (pw
->pw_uid
== 0 || use_privsep
)) {
502 c
= channel_connect_to_path(ssh
, target
,
503 "direct-streamlocal@openssh.com", "direct-streamlocal");
505 logit("refused streamlocal port forward: "
506 "originator %s port %d, target %s",
507 originator
, originator_port
, target
);
517 server_request_tun(struct ssh
*ssh
)
523 mode
= packet_get_int();
525 case SSH_TUNMODE_POINTOPOINT
:
526 case SSH_TUNMODE_ETHERNET
:
529 packet_send_debug("Unsupported tunnel device mode.");
532 if ((options
.permit_tun
& mode
) == 0) {
533 packet_send_debug("Server has rejected tunnel device "
538 tun
= packet_get_int();
539 if (forced_tun_device
!= -1) {
540 if (tun
!= SSH_TUNID_ANY
&& forced_tun_device
!= tun
)
542 tun
= forced_tun_device
;
544 sock
= tun_open(tun
, mode
);
547 c
= channel_new(ssh
, "tun", SSH_CHANNEL_OPEN
, sock
, sock
, -1,
548 CHAN_TCP_WINDOW_DEFAULT
, CHAN_TCP_PACKET_DEFAULT
, 0, "tun", 1);
550 #if defined(SSH_TUN_FILTER)
551 if (mode
== SSH_TUNMODE_POINTOPOINT
)
552 channel_register_filter(ssh
, c
->self
, sys_tun_infilter
,
553 sys_tun_outfilter
, NULL
, NULL
);
558 packet_send_debug("Failed to open the tunnel device.");
563 server_request_session(struct ssh
*ssh
)
567 debug("input_session_request");
570 if (no_more_sessions
) {
571 packet_disconnect("Possible attack: attempt to open a session "
572 "after additional sessions disabled");
576 * A server session has no fd to read or write until a
577 * CHANNEL_REQUEST for a shell is made, so we set the type to
578 * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
579 * CHANNEL_REQUEST messages is registered.
581 c
= channel_new(ssh
, "session", SSH_CHANNEL_LARVAL
,
582 -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT
,
583 0, "server-session", 1);
584 if (session_open(the_authctxt
, c
->self
) != 1) {
585 debug("session open failed, free channel %d", c
->self
);
586 channel_free(ssh
, c
);
589 channel_register_cleanup(ssh
, c
->self
, session_close_by_channel
, 0);
594 server_input_channel_open(int type
, u_int32_t seq
, struct ssh
*ssh
)
598 const char *errmsg
= NULL
;
599 int rchan
, reason
= SSH2_OPEN_CONNECT_FAILED
;
600 u_int rmaxpack
, rwindow
, len
;
602 ctype
= packet_get_string(&len
);
603 rchan
= packet_get_int();
604 rwindow
= packet_get_int();
605 rmaxpack
= packet_get_int();
607 debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
608 ctype
, rchan
, rwindow
, rmaxpack
);
610 if (strcmp(ctype
, "session") == 0) {
611 c
= server_request_session(ssh
);
612 } else if (strcmp(ctype
, "direct-tcpip") == 0) {
613 c
= server_request_direct_tcpip(ssh
, &reason
, &errmsg
);
614 } else if (strcmp(ctype
, "direct-streamlocal@openssh.com") == 0) {
615 c
= server_request_direct_streamlocal(ssh
);
616 } else if (strcmp(ctype
, "tun@openssh.com") == 0) {
617 c
= server_request_tun(ssh
);
620 debug("server_input_channel_open: confirm %s", ctype
);
621 c
->remote_id
= rchan
;
622 c
->have_remote_id
= 1;
623 c
->remote_window
= rwindow
;
624 c
->remote_maxpacket
= rmaxpack
;
625 if (c
->type
!= SSH_CHANNEL_CONNECTING
) {
626 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
);
627 packet_put_int(c
->remote_id
);
628 packet_put_int(c
->self
);
629 packet_put_int(c
->local_window
);
630 packet_put_int(c
->local_maxpacket
);
634 debug("server_input_channel_open: failure %s", ctype
);
635 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE
);
636 packet_put_int(rchan
);
637 packet_put_int(reason
);
638 if (!(datafellows
& SSH_BUG_OPENFAILURE
)) {
639 packet_put_cstring(errmsg
? errmsg
: "open failed");
640 packet_put_cstring("");
649 server_input_hostkeys_prove(struct ssh
*ssh
, struct sshbuf
**respp
)
651 struct sshbuf
*resp
= NULL
;
652 struct sshbuf
*sigbuf
= NULL
;
653 struct sshkey
*key
= NULL
, *key_pub
= NULL
, *key_prv
= NULL
;
654 int r
, ndx
, success
= 0;
659 if ((resp
= sshbuf_new()) == NULL
|| (sigbuf
= sshbuf_new()) == NULL
)
660 fatal("%s: sshbuf_new", __func__
);
662 while (ssh_packet_remaining(ssh
) > 0) {
665 if ((r
= sshpkt_get_string_direct(ssh
, &blob
, &blen
)) != 0 ||
666 (r
= sshkey_from_blob(blob
, blen
, &key
)) != 0) {
667 error("%s: couldn't parse key: %s",
668 __func__
, ssh_err(r
));
672 * Better check that this is actually one of our hostkeys
673 * before attempting to sign anything with it.
675 if ((ndx
= ssh
->kex
->host_key_index(key
, 1, ssh
)) == -1) {
676 error("%s: unknown host %s key",
677 __func__
, sshkey_type(key
));
681 * XXX refactor: make kex->sign just use an index rather
682 * than passing in public and private keys
684 if ((key_prv
= get_hostkey_by_index(ndx
)) == NULL
&&
685 (key_pub
= get_hostkey_public_by_index(ndx
, ssh
)) == NULL
) {
686 error("%s: can't retrieve hostkey %d", __func__
, ndx
);
689 sshbuf_reset(sigbuf
);
692 if ((r
= sshbuf_put_cstring(sigbuf
,
693 "hostkeys-prove-00@openssh.com")) != 0 ||
694 (r
= sshbuf_put_string(sigbuf
,
695 ssh
->kex
->session_id
, ssh
->kex
->session_id_len
)) != 0 ||
696 (r
= sshkey_puts(key
, sigbuf
)) != 0 ||
697 (r
= ssh
->kex
->sign(key_prv
, key_pub
, &sig
, &slen
,
698 sshbuf_ptr(sigbuf
), sshbuf_len(sigbuf
), NULL
, 0)) != 0 ||
699 (r
= sshbuf_put_string(resp
, sig
, slen
)) != 0) {
700 error("%s: couldn't prepare signature: %s",
701 __func__
, ssh_err(r
));
707 resp
= NULL
; /* don't free it */
718 server_input_global_request(int type
, u_int32_t seq
, struct ssh
*ssh
)
722 int r
, success
= 0, allocated_listen_port
= 0;
723 struct sshbuf
*resp
= NULL
;
724 struct passwd
*pw
= the_authctxt
->pw
;
726 if (pw
== NULL
|| !the_authctxt
->valid
)
727 fatal("server_input_global_request: no/invalid user");
729 rtype
= packet_get_string(NULL
);
730 want_reply
= packet_get_char();
731 debug("server_input_global_request: rtype %s want_reply %d", rtype
, want_reply
);
733 /* -R style forwarding */
734 if (strcmp(rtype
, "tcpip-forward") == 0) {
737 memset(&fwd
, 0, sizeof(fwd
));
738 fwd
.listen_host
= packet_get_string(NULL
);
739 fwd
.listen_port
= (u_short
)packet_get_int();
740 debug("server_input_global_request: tcpip-forward listen %s port %d",
741 fwd
.listen_host
, fwd
.listen_port
);
743 /* check permissions */
744 if ((options
.allow_tcp_forwarding
& FORWARD_REMOTE
) == 0 ||
745 no_port_forwarding_flag
|| options
.disable_forwarding
||
746 (!want_reply
&& fwd
.listen_port
== 0) ||
747 (fwd
.listen_port
!= 0 &&
748 !bind_permitted(fwd
.listen_port
, pw
->pw_uid
))) {
750 packet_send_debug("Server has disabled port forwarding.");
752 /* Start listening on the port */
753 success
= channel_setup_remote_fwd_listener(ssh
, &fwd
,
754 &allocated_listen_port
, &options
.fwd_opts
);
756 free(fwd
.listen_host
);
757 if ((resp
= sshbuf_new()) == NULL
)
758 fatal("%s: sshbuf_new", __func__
);
759 if (allocated_listen_port
!= 0 &&
760 (r
= sshbuf_put_u32(resp
, allocated_listen_port
)) != 0)
761 fatal("%s: sshbuf_put_u32: %s", __func__
, ssh_err(r
));
762 } else if (strcmp(rtype
, "cancel-tcpip-forward") == 0) {
765 memset(&fwd
, 0, sizeof(fwd
));
766 fwd
.listen_host
= packet_get_string(NULL
);
767 fwd
.listen_port
= (u_short
)packet_get_int();
768 debug("%s: cancel-tcpip-forward addr %s port %d", __func__
,
769 fwd
.listen_host
, fwd
.listen_port
);
771 success
= channel_cancel_rport_listener(ssh
, &fwd
);
772 free(fwd
.listen_host
);
773 } else if (strcmp(rtype
, "streamlocal-forward@openssh.com") == 0) {
776 memset(&fwd
, 0, sizeof(fwd
));
777 fwd
.listen_path
= packet_get_string(NULL
);
778 debug("server_input_global_request: streamlocal-forward listen path %s",
781 /* check permissions */
782 if ((options
.allow_streamlocal_forwarding
& FORWARD_REMOTE
) == 0
783 || no_port_forwarding_flag
|| options
.disable_forwarding
||
784 (pw
->pw_uid
!= 0 && !use_privsep
)) {
786 packet_send_debug("Server has disabled "
787 "streamlocal forwarding.");
789 /* Start listening on the socket */
790 success
= channel_setup_remote_fwd_listener(ssh
,
791 &fwd
, NULL
, &options
.fwd_opts
);
793 free(fwd
.listen_path
);
794 } else if (strcmp(rtype
, "cancel-streamlocal-forward@openssh.com") == 0) {
797 memset(&fwd
, 0, sizeof(fwd
));
798 fwd
.listen_path
= packet_get_string(NULL
);
799 debug("%s: cancel-streamlocal-forward path %s", __func__
,
802 success
= channel_cancel_rport_listener(ssh
, &fwd
);
803 free(fwd
.listen_path
);
804 } else if (strcmp(rtype
, "no-more-sessions@openssh.com") == 0) {
805 no_more_sessions
= 1;
807 } else if (strcmp(rtype
, "hostkeys-prove-00@openssh.com") == 0) {
808 success
= server_input_hostkeys_prove(ssh
, &resp
);
811 packet_start(success
?
812 SSH2_MSG_REQUEST_SUCCESS
: SSH2_MSG_REQUEST_FAILURE
);
813 if (success
&& resp
!= NULL
)
814 ssh_packet_put_raw(ssh
, sshbuf_ptr(resp
),
825 server_input_channel_req(int type
, u_int32_t seq
, struct ssh
*ssh
)
828 int id
, reply
, success
= 0;
831 id
= packet_get_int();
832 rtype
= packet_get_string(NULL
);
833 reply
= packet_get_char();
835 debug("server_input_channel_req: channel %d request %s reply %d",
838 if ((c
= channel_lookup(ssh
, id
)) == NULL
)
839 packet_disconnect("server_input_channel_req: "
840 "unknown channel %d", id
);
841 if (!strcmp(rtype
, "eow@openssh.com")) {
843 chan_rcvd_eow(ssh
, c
);
844 } else if ((c
->type
== SSH_CHANNEL_LARVAL
||
845 c
->type
== SSH_CHANNEL_OPEN
) && strcmp(c
->ctype
, "session") == 0)
846 success
= session_input_channel_req(ssh
, c
, rtype
);
847 if (reply
&& !(c
->flags
& CHAN_CLOSE_SENT
)) {
848 if (!c
->have_remote_id
)
849 fatal("%s: channel %d: no remote_id",
851 packet_start(success
?
852 SSH2_MSG_CHANNEL_SUCCESS
: SSH2_MSG_CHANNEL_FAILURE
);
853 packet_put_int(c
->remote_id
);
861 server_init_dispatch(void)
863 debug("server_init_dispatch");
864 dispatch_init(&dispatch_protocol_error
);
865 dispatch_set(SSH2_MSG_CHANNEL_CLOSE
, &channel_input_oclose
);
866 dispatch_set(SSH2_MSG_CHANNEL_DATA
, &channel_input_data
);
867 dispatch_set(SSH2_MSG_CHANNEL_EOF
, &channel_input_ieof
);
868 dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA
, &channel_input_extended_data
);
869 dispatch_set(SSH2_MSG_CHANNEL_OPEN
, &server_input_channel_open
);
870 dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
, &channel_input_open_confirmation
);
871 dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE
, &channel_input_open_failure
);
872 dispatch_set(SSH2_MSG_CHANNEL_REQUEST
, &server_input_channel_req
);
873 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST
, &channel_input_window_adjust
);
874 dispatch_set(SSH2_MSG_GLOBAL_REQUEST
, &server_input_global_request
);
876 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS
, &server_input_keep_alive
);
877 dispatch_set(SSH2_MSG_CHANNEL_FAILURE
, &server_input_keep_alive
);
878 dispatch_set(SSH2_MSG_REQUEST_SUCCESS
, &server_input_keep_alive
);
879 dispatch_set(SSH2_MSG_REQUEST_FAILURE
, &server_input_keep_alive
);
881 dispatch_set(SSH2_MSG_KEXINIT
, &kex_input_kexinit
);