serverloop.c revision 1.28 1 1.26 christos /* $NetBSD: serverloop.c,v 1.28 2020/12/04 18:42:50 christos Exp $ */
2 1.28 christos /* $OpenBSD: serverloop.c,v 1.223 2020/07/03 06:29:57 djm Exp $ */
3 1.28 christos
4 1.1 christos /*
5 1.1 christos * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
6 1.1 christos * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
7 1.1 christos * All rights reserved
8 1.1 christos * Server main loop for handling the interactive session.
9 1.1 christos *
10 1.1 christos * As far as I am concerned, the code I have written for this software
11 1.1 christos * can be used freely for any purpose. Any derived versions of this
12 1.1 christos * software must be clearly marked as such, and if the derived work is
13 1.1 christos * incompatible with the protocol description in the RFC file, it must be
14 1.1 christos * called by a name other than "ssh" or "Secure Shell".
15 1.1 christos *
16 1.1 christos * SSH2 support by Markus Friedl.
17 1.1 christos * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
18 1.1 christos *
19 1.1 christos * Redistribution and use in source and binary forms, with or without
20 1.1 christos * modification, are permitted provided that the following conditions
21 1.1 christos * are met:
22 1.1 christos * 1. Redistributions of source code must retain the above copyright
23 1.1 christos * notice, this list of conditions and the following disclaimer.
24 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
25 1.1 christos * notice, this list of conditions and the following disclaimer in the
26 1.1 christos * documentation and/or other materials provided with the distribution.
27 1.1 christos *
28 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29 1.1 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30 1.1 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 1.1 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32 1.1 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33 1.1 christos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37 1.1 christos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 1.1 christos */
39 1.1 christos
40 1.2 christos #include "includes.h"
41 1.26 christos __RCSID("$NetBSD: serverloop.c,v 1.28 2020/12/04 18:42:50 christos Exp $");
42 1.16 christos
43 1.10 christos #include <sys/param.h> /* MIN MAX */
44 1.1 christos #include <sys/types.h>
45 1.1 christos #include <sys/wait.h>
46 1.1 christos #include <sys/socket.h>
47 1.1 christos #include <sys/time.h>
48 1.1 christos #include <sys/queue.h>
49 1.1 christos
50 1.1 christos #include <netinet/in.h>
51 1.1 christos
52 1.1 christos #include <errno.h>
53 1.1 christos #include <fcntl.h>
54 1.1 christos #include <pwd.h>
55 1.25 christos #include <limits.h>
56 1.1 christos #include <signal.h>
57 1.1 christos #include <string.h>
58 1.1 christos #include <termios.h>
59 1.1 christos #include <unistd.h>
60 1.1 christos #include <stdarg.h>
61 1.1 christos
62 1.1 christos #include "xmalloc.h"
63 1.1 christos #include "packet.h"
64 1.21 christos #include "sshbuf.h"
65 1.1 christos #include "log.h"
66 1.9 christos #include "misc.h"
67 1.1 christos #include "servconf.h"
68 1.1 christos #include "canohost.h"
69 1.1 christos #include "sshpty.h"
70 1.1 christos #include "channels.h"
71 1.1 christos #include "compat.h"
72 1.1 christos #include "ssh2.h"
73 1.21 christos #include "sshkey.h"
74 1.1 christos #include "cipher.h"
75 1.1 christos #include "kex.h"
76 1.1 christos #include "hostfile.h"
77 1.1 christos #include "auth.h"
78 1.1 christos #include "session.h"
79 1.1 christos #include "dispatch.h"
80 1.1 christos #include "auth-options.h"
81 1.1 christos #include "serverloop.h"
82 1.10 christos #include "ssherr.h"
83 1.1 christos
84 1.16 christos static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */
85 1.16 christos static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */
86 1.16 christos
87 1.1 christos extern ServerOptions options;
88 1.1 christos
89 1.1 christos /* XXX */
90 1.1 christos extern Authctxt *the_authctxt;
91 1.19 christos extern struct sshauthopt *auth_opts;
92 1.1 christos extern int use_privsep;
93 1.1 christos
94 1.1 christos static int no_more_sessions = 0; /* Disallow further sessions. */
95 1.1 christos
96 1.1 christos /*
97 1.1 christos * This SIGCHLD kludge is used to detect when the child exits. The server
98 1.1 christos * will exit after that, as soon as forwarded connections have terminated.
99 1.1 christos */
100 1.1 christos
101 1.1 christos static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
102 1.1 christos
103 1.1 christos /* Cleanup on signals (!use_privsep case only) */
104 1.1 christos static volatile sig_atomic_t received_sigterm = 0;
105 1.1 christos
106 1.1 christos /* prototypes */
107 1.25 christos static void server_init_dispatch(struct ssh *);
108 1.1 christos
109 1.19 christos /* requested tunnel forwarding interface(s), shared with session.c */
110 1.19 christos char *tun_fwd_ifnames = NULL;
111 1.19 christos
112 1.21 christos /* returns 1 if bind to specified port by specified user is permitted */
113 1.21 christos static int
114 1.21 christos bind_permitted(int port, uid_t uid)
115 1.21 christos {
116 1.21 christos if (use_privsep)
117 1.21 christos return 1; /* allow system to decide */
118 1.21 christos if (port < IPPORT_RESERVED && uid != 0)
119 1.21 christos return 0;
120 1.21 christos return 1;
121 1.21 christos }
122 1.21 christos
123 1.1 christos /*
124 1.2 christos * Returns current time in seconds from Jan 1, 1970 with the maximum
125 1.2 christos * available resolution.
126 1.2 christos */
127 1.2 christos
128 1.2 christos static double
129 1.2 christos get_current_time(void)
130 1.2 christos {
131 1.2 christos struct timeval tv;
132 1.2 christos gettimeofday(&tv, NULL);
133 1.2 christos return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
134 1.2 christos }
135 1.2 christos
136 1.2 christos /*
137 1.1 christos * we write to this pipe if a SIGCHLD is caught in order to avoid
138 1.1 christos * the race between select() and child_terminated
139 1.1 christos */
140 1.1 christos static int notify_pipe[2];
141 1.1 christos static void
142 1.1 christos notify_setup(void)
143 1.1 christos {
144 1.26 christos if (pipe(notify_pipe) == -1) {
145 1.1 christos error("pipe(notify_pipe) failed %s", strerror(errno));
146 1.4 christos } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
147 1.4 christos (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
148 1.1 christos error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
149 1.1 christos close(notify_pipe[0]);
150 1.1 christos close(notify_pipe[1]);
151 1.1 christos } else {
152 1.1 christos set_nonblock(notify_pipe[0]);
153 1.1 christos set_nonblock(notify_pipe[1]);
154 1.1 christos return;
155 1.1 christos }
156 1.1 christos notify_pipe[0] = -1; /* read end */
157 1.1 christos notify_pipe[1] = -1; /* write end */
158 1.1 christos }
159 1.1 christos static void
160 1.1 christos notify_parent(void)
161 1.1 christos {
162 1.1 christos if (notify_pipe[1] != -1)
163 1.7 christos (void)write(notify_pipe[1], "", 1);
164 1.1 christos }
165 1.1 christos static void
166 1.1 christos notify_prepare(fd_set *readset)
167 1.1 christos {
168 1.1 christos if (notify_pipe[0] != -1)
169 1.1 christos FD_SET(notify_pipe[0], readset);
170 1.1 christos }
171 1.1 christos static void
172 1.1 christos notify_done(fd_set *readset)
173 1.1 christos {
174 1.1 christos char c;
175 1.1 christos
176 1.1 christos if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
177 1.1 christos while (read(notify_pipe[0], &c, 1) != -1)
178 1.21 christos debug2("%s: reading", __func__);
179 1.1 christos }
180 1.1 christos
181 1.1 christos /*ARGSUSED*/
182 1.1 christos static void
183 1.1 christos sigchld_handler(int sig)
184 1.1 christos {
185 1.1 christos int save_errno = errno;
186 1.1 christos child_terminated = 1;
187 1.1 christos notify_parent();
188 1.1 christos errno = save_errno;
189 1.1 christos }
190 1.1 christos
191 1.1 christos /*ARGSUSED*/
192 1.1 christos static void
193 1.1 christos sigterm_handler(int sig)
194 1.1 christos {
195 1.1 christos received_sigterm = sig;
196 1.1 christos }
197 1.1 christos
198 1.1 christos static void
199 1.18 christos client_alive_check(struct ssh *ssh)
200 1.1 christos {
201 1.19 christos char remote_id[512];
202 1.25 christos int r, channel_id;
203 1.1 christos
204 1.1 christos /* timeout, check to see how many we have had */
205 1.27 christos if (options.client_alive_count_max > 0 &&
206 1.27 christos ssh_packet_inc_alive_timeouts(ssh) >
207 1.25 christos options.client_alive_count_max) {
208 1.19 christos sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
209 1.19 christos logit("Timeout, client not responding from %s", remote_id);
210 1.1 christos cleanup_exit(255);
211 1.1 christos }
212 1.1 christos
213 1.1 christos /*
214 1.1 christos * send a bogus global/channel request with "wantreply",
215 1.1 christos * we should get back a failure
216 1.1 christos */
217 1.18 christos if ((channel_id = channel_find_open(ssh)) == -1) {
218 1.25 christos if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
219 1.25 christos (r = sshpkt_put_cstring(ssh, "keepalive (at) openssh.com"))
220 1.25 christos != 0 ||
221 1.25 christos (r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */
222 1.25 christos fatal("%s: %s", __func__, ssh_err(r));
223 1.1 christos } else {
224 1.18 christos channel_request_start(ssh, channel_id,
225 1.18 christos "keepalive (at) openssh.com", 1);
226 1.1 christos }
227 1.25 christos if ((r = sshpkt_send(ssh)) != 0)
228 1.25 christos fatal("%s: %s", __func__, ssh_err(r));
229 1.1 christos }
230 1.1 christos
231 1.1 christos /*
232 1.1 christos * Sleep in select() until we can do something. This will initialize the
233 1.1 christos * select masks. Upon return, the masks will indicate which descriptors
234 1.1 christos * have data or can accept data. Optionally, a maximum time can be specified
235 1.1 christos * for the duration of the wait (0 = infinite).
236 1.1 christos */
237 1.1 christos static void
238 1.18 christos wait_until_can_do_something(struct ssh *ssh,
239 1.18 christos int connection_in, int connection_out,
240 1.16 christos fd_set **readsetp, fd_set **writesetp, int *maxfdp,
241 1.15 christos u_int *nallocp, u_int64_t max_time_ms)
242 1.1 christos {
243 1.1 christos struct timeval tv, *tvp;
244 1.1 christos int ret;
245 1.5 christos time_t minwait_secs = 0;
246 1.1 christos int client_alive_scheduled = 0;
247 1.25 christos /* time we last heard from the client OR sent a keepalive */
248 1.18 christos static time_t last_client_time;
249 1.1 christos
250 1.5 christos /* Allocate and update select() masks for channel descriptors. */
251 1.18 christos channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
252 1.18 christos nallocp, &minwait_secs);
253 1.5 christos
254 1.15 christos /* XXX need proper deadline system for rekey/client alive */
255 1.5 christos if (minwait_secs != 0)
256 1.16 christos max_time_ms = MINIMUM(max_time_ms, (u_int)minwait_secs * 1000);
257 1.5 christos
258 1.1 christos /*
259 1.1 christos * if using client_alive, set the max timeout accordingly,
260 1.1 christos * and indicate that this particular timeout was for client
261 1.1 christos * alive by setting the client_alive_scheduled flag.
262 1.1 christos *
263 1.1 christos * this could be randomized somewhat to make traffic
264 1.1 christos * analysis more difficult, but we're not doing it yet.
265 1.1 christos */
266 1.16 christos if (options.client_alive_interval) {
267 1.15 christos uint64_t keepalive_ms =
268 1.15 christos (uint64_t)options.client_alive_interval * 1000;
269 1.15 christos
270 1.25 christos if (max_time_ms == 0 || max_time_ms > keepalive_ms) {
271 1.15 christos max_time_ms = keepalive_ms;
272 1.25 christos client_alive_scheduled = 1;
273 1.25 christos }
274 1.28 christos if (last_client_time == 0)
275 1.28 christos last_client_time = monotime();
276 1.1 christos }
277 1.1 christos
278 1.1 christos #if 0
279 1.16 christos /* wrong: bad condition XXX */
280 1.16 christos if (channel_not_very_much_buffered_data())
281 1.1 christos #endif
282 1.16 christos FD_SET(connection_in, *readsetp);
283 1.1 christos notify_prepare(*readsetp);
284 1.1 christos
285 1.1 christos /*
286 1.1 christos * If we have buffered packet data going to the client, mark that
287 1.1 christos * descriptor.
288 1.1 christos */
289 1.25 christos if (ssh_packet_have_data_to_write(ssh))
290 1.1 christos FD_SET(connection_out, *writesetp);
291 1.1 christos
292 1.1 christos /*
293 1.1 christos * If child has terminated and there is enough buffer space to read
294 1.1 christos * from it, then read as much as is available and exit.
295 1.1 christos */
296 1.25 christos if (child_terminated && ssh_packet_not_very_much_data_to_write(ssh))
297 1.15 christos if (max_time_ms == 0 || client_alive_scheduled)
298 1.15 christos max_time_ms = 100;
299 1.1 christos
300 1.15 christos if (max_time_ms == 0)
301 1.1 christos tvp = NULL;
302 1.1 christos else {
303 1.15 christos tv.tv_sec = max_time_ms / 1000;
304 1.15 christos tv.tv_usec = 1000 * (max_time_ms % 1000);
305 1.1 christos tvp = &tv;
306 1.1 christos }
307 1.1 christos
308 1.1 christos /* Wait for something to happen, or the timeout to expire. */
309 1.1 christos ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
310 1.1 christos
311 1.1 christos if (ret == -1) {
312 1.1 christos memset(*readsetp, 0, *nallocp);
313 1.1 christos memset(*writesetp, 0, *nallocp);
314 1.1 christos if (errno != EINTR)
315 1.1 christos error("select: %.100s", strerror(errno));
316 1.18 christos } else if (client_alive_scheduled) {
317 1.18 christos time_t now = monotime();
318 1.18 christos
319 1.25 christos /*
320 1.25 christos * If the select timed out, or returned for some other reason
321 1.25 christos * but we haven't heard from the client in time, send keepalive.
322 1.25 christos */
323 1.25 christos if (ret == 0 || (last_client_time != 0 && last_client_time +
324 1.25 christos options.client_alive_interval <= now)) {
325 1.18 christos client_alive_check(ssh);
326 1.25 christos last_client_time = now;
327 1.18 christos } else if (FD_ISSET(connection_in, *readsetp)) {
328 1.18 christos last_client_time = now;
329 1.18 christos }
330 1.18 christos }
331 1.1 christos
332 1.1 christos notify_done(*readsetp);
333 1.1 christos }
334 1.1 christos
335 1.1 christos /*
336 1.1 christos * Processes input from the client and the program. Input data is stored
337 1.1 christos * in buffers and processed later.
338 1.1 christos */
339 1.16 christos static int
340 1.18 christos process_input(struct ssh *ssh, fd_set *readset, int connection_in)
341 1.1 christos {
342 1.25 christos int r, len;
343 1.1 christos char buf[16384];
344 1.1 christos
345 1.1 christos /* Read and buffer any input data from the client. */
346 1.1 christos if (FD_ISSET(connection_in, readset)) {
347 1.13 christos len = read(connection_in, buf, sizeof(buf));
348 1.1 christos if (len == 0) {
349 1.15 christos verbose("Connection closed by %.100s port %d",
350 1.15 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
351 1.16 christos return -1;
352 1.26 christos } else if (len == -1) {
353 1.1 christos if (errno != EINTR && errno != EAGAIN) {
354 1.1 christos verbose("Read error from remote host "
355 1.15 christos "%.100s port %d: %.100s",
356 1.15 christos ssh_remote_ipaddr(ssh),
357 1.15 christos ssh_remote_port(ssh), strerror(errno));
358 1.23 christos cleanup_exit(254);
359 1.1 christos }
360 1.1 christos } else {
361 1.1 christos /* Buffer any received data. */
362 1.25 christos if ((r = ssh_packet_process_incoming(ssh, buf, len))
363 1.25 christos != 0)
364 1.25 christos fatal("%s: ssh_packet_process_incoming: %s",
365 1.25 christos __func__, ssh_err(r));
366 1.1 christos }
367 1.1 christos }
368 1.16 christos return 0;
369 1.1 christos }
370 1.1 christos
371 1.1 christos /*
372 1.1 christos * Sends data from internal buffers to client program stdin.
373 1.1 christos */
374 1.1 christos static void
375 1.25 christos process_output(struct ssh *ssh, fd_set *writeset, int connection_out)
376 1.1 christos {
377 1.25 christos int r;
378 1.25 christos
379 1.1 christos /* Send any buffered packet data to the client. */
380 1.25 christos if (FD_ISSET(connection_out, writeset)) {
381 1.25 christos if ((r = ssh_packet_write_poll(ssh)) < 0)
382 1.27 christos sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll",
383 1.27 christos __func__);
384 1.25 christos }
385 1.1 christos }
386 1.1 christos
387 1.1 christos static void
388 1.18 christos process_buffered_input_packets(struct ssh *ssh)
389 1.1 christos {
390 1.18 christos ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
391 1.1 christos }
392 1.1 christos
393 1.1 christos static void
394 1.18 christos collect_children(struct ssh *ssh)
395 1.1 christos {
396 1.1 christos pid_t pid;
397 1.1 christos sigset_t oset, nset;
398 1.1 christos int status;
399 1.1 christos
400 1.1 christos /* block SIGCHLD while we check for dead children */
401 1.1 christos sigemptyset(&nset);
402 1.1 christos sigaddset(&nset, SIGCHLD);
403 1.1 christos sigprocmask(SIG_BLOCK, &nset, &oset);
404 1.1 christos if (child_terminated) {
405 1.1 christos debug("Received SIGCHLD.");
406 1.1 christos while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
407 1.26 christos (pid == -1 && errno == EINTR))
408 1.1 christos if (pid > 0)
409 1.18 christos session_close_by_pid(ssh, pid, status);
410 1.1 christos child_terminated = 0;
411 1.1 christos }
412 1.1 christos sigprocmask(SIG_SETMASK, &oset, NULL);
413 1.1 christos }
414 1.1 christos
415 1.1 christos void
416 1.18 christos server_loop2(struct ssh *ssh, Authctxt *authctxt)
417 1.1 christos {
418 1.1 christos fd_set *readset = NULL, *writeset = NULL;
419 1.14 christos int max_fd;
420 1.16 christos u_int nalloc = 0, connection_in, connection_out;
421 1.7 christos u_int64_t rekey_timeout_ms = 0;
422 1.2 christos double start_time, total_time;
423 1.1 christos
424 1.1 christos debug("Entering interactive session for SSH2.");
425 1.2 christos start_time = get_current_time();
426 1.1 christos
427 1.27 christos ssh_signal(SIGCHLD, sigchld_handler);
428 1.1 christos child_terminated = 0;
429 1.25 christos connection_in = ssh_packet_get_connection_in(ssh);
430 1.25 christos connection_out = ssh_packet_get_connection_out(ssh);
431 1.1 christos
432 1.1 christos if (!use_privsep) {
433 1.27 christos ssh_signal(SIGTERM, sigterm_handler);
434 1.27 christos ssh_signal(SIGINT, sigterm_handler);
435 1.27 christos ssh_signal(SIGQUIT, sigterm_handler);
436 1.1 christos }
437 1.1 christos
438 1.1 christos notify_setup();
439 1.1 christos
440 1.16 christos max_fd = MAXIMUM(connection_in, connection_out);
441 1.16 christos max_fd = MAXIMUM(max_fd, notify_pipe[0]);
442 1.1 christos
443 1.25 christos server_init_dispatch(ssh);
444 1.1 christos
445 1.1 christos for (;;) {
446 1.18 christos process_buffered_input_packets(ssh);
447 1.1 christos
448 1.18 christos if (!ssh_packet_is_rekeying(ssh) &&
449 1.25 christos ssh_packet_not_very_much_data_to_write(ssh))
450 1.18 christos channel_output_poll(ssh);
451 1.25 christos if (options.rekey_interval > 0 &&
452 1.25 christos !ssh_packet_is_rekeying(ssh)) {
453 1.25 christos rekey_timeout_ms = ssh_packet_get_rekey_timeout(ssh) *
454 1.25 christos 1000;
455 1.25 christos } else {
456 1.7 christos rekey_timeout_ms = 0;
457 1.25 christos }
458 1.7 christos
459 1.18 christos wait_until_can_do_something(ssh, connection_in, connection_out,
460 1.16 christos &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
461 1.1 christos
462 1.1 christos if (received_sigterm) {
463 1.6 christos logit("Exiting on signal %d", (int)received_sigterm);
464 1.1 christos /* Clean up sessions, utmp, etc. */
465 1.23 christos cleanup_exit(254);
466 1.1 christos }
467 1.1 christos
468 1.18 christos collect_children(ssh);
469 1.18 christos if (!ssh_packet_is_rekeying(ssh))
470 1.18 christos channel_after_select(ssh, readset, writeset);
471 1.18 christos if (process_input(ssh, readset, connection_in) < 0)
472 1.1 christos break;
473 1.25 christos process_output(ssh, writeset, connection_out);
474 1.1 christos }
475 1.18 christos collect_children(ssh);
476 1.1 christos
477 1.7 christos free(readset);
478 1.7 christos free(writeset);
479 1.1 christos
480 1.1 christos /* free all channels, no more reads and writes */
481 1.18 christos channel_free_all(ssh);
482 1.1 christos
483 1.1 christos /* free remaining sessions, e.g. remove wtmp entries */
484 1.18 christos session_destroy_all(ssh, NULL);
485 1.2 christos total_time = get_current_time() - start_time;
486 1.2 christos logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
487 1.15 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
488 1.2 christos stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time,
489 1.2 christos fdout_bytes / total_time);
490 1.1 christos }
491 1.1 christos
492 1.10 christos static int
493 1.18 christos server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
494 1.1 christos {
495 1.1 christos debug("Got %d/%u for keepalive", type, seq);
496 1.1 christos /*
497 1.1 christos * reset timeout, since we got a sane answer from the client.
498 1.1 christos * even if this was generated by something other than
499 1.1 christos * the bogus CHANNEL_REQUEST we send for keepalives.
500 1.1 christos */
501 1.25 christos ssh_packet_set_alive_timeouts(ssh, 0);
502 1.10 christos return 0;
503 1.1 christos }
504 1.1 christos
505 1.1 christos static Channel *
506 1.18 christos server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
507 1.1 christos {
508 1.6 christos Channel *c = NULL;
509 1.25 christos char *target = NULL, *originator = NULL;
510 1.25 christos u_int target_port = 0, originator_port = 0;
511 1.25 christos int r;
512 1.25 christos
513 1.25 christos if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
514 1.25 christos (r = sshpkt_get_u32(ssh, &target_port)) != 0 ||
515 1.25 christos (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
516 1.25 christos (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
517 1.25 christos (r = sshpkt_get_end(ssh)) != 0)
518 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
519 1.25 christos if (target_port > 0xFFFF) {
520 1.25 christos error("%s: invalid target port", __func__);
521 1.25 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
522 1.25 christos goto out;
523 1.25 christos }
524 1.25 christos if (originator_port > 0xFFFF) {
525 1.25 christos error("%s: invalid originator port", __func__);
526 1.25 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
527 1.25 christos goto out;
528 1.25 christos }
529 1.1 christos
530 1.25 christos debug("%s: originator %s port %u, target %s port %u", __func__,
531 1.19 christos originator, originator_port, target, target_port);
532 1.1 christos
533 1.6 christos /* XXX fine grained permissions */
534 1.6 christos if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
535 1.19 christos auth_opts->permit_port_forwarding_flag &&
536 1.19 christos !options.disable_forwarding) {
537 1.18 christos c = channel_connect_to_port(ssh, target, target_port,
538 1.17 christos "direct-tcpip", "direct-tcpip", reason, errmsg);
539 1.6 christos } else {
540 1.6 christos logit("refused local port forward: "
541 1.6 christos "originator %s port %d, target %s port %d",
542 1.6 christos originator, originator_port, target, target_port);
543 1.17 christos if (reason != NULL)
544 1.17 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
545 1.6 christos }
546 1.1 christos
547 1.25 christos out:
548 1.7 christos free(originator);
549 1.7 christos free(target);
550 1.1 christos return c;
551 1.1 christos }
552 1.1 christos
553 1.1 christos static Channel *
554 1.18 christos server_request_direct_streamlocal(struct ssh *ssh)
555 1.9 christos {
556 1.9 christos Channel *c = NULL;
557 1.25 christos char *target = NULL, *originator = NULL;
558 1.25 christos u_int originator_port = 0;
559 1.17 christos struct passwd *pw = the_authctxt->pw;
560 1.25 christos int r;
561 1.17 christos
562 1.17 christos if (pw == NULL || !the_authctxt->valid)
563 1.19 christos fatal("%s: no/invalid user", __func__);
564 1.9 christos
565 1.25 christos if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
566 1.25 christos (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
567 1.25 christos (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
568 1.25 christos (r = sshpkt_get_end(ssh)) != 0)
569 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
570 1.25 christos if (originator_port > 0xFFFF) {
571 1.25 christos error("%s: invalid originator port", __func__);
572 1.25 christos goto out;
573 1.25 christos }
574 1.9 christos
575 1.19 christos debug("%s: originator %s port %d, target %s", __func__,
576 1.9 christos originator, originator_port, target);
577 1.9 christos
578 1.9 christos /* XXX fine grained permissions */
579 1.9 christos if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
580 1.19 christos auth_opts->permit_port_forwarding_flag &&
581 1.19 christos !options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) {
582 1.18 christos c = channel_connect_to_path(ssh, target,
583 1.9 christos "direct-streamlocal (at) openssh.com", "direct-streamlocal");
584 1.9 christos } else {
585 1.9 christos logit("refused streamlocal port forward: "
586 1.9 christos "originator %s port %d, target %s",
587 1.9 christos originator, originator_port, target);
588 1.9 christos }
589 1.9 christos
590 1.25 christos out:
591 1.9 christos free(originator);
592 1.9 christos free(target);
593 1.9 christos return c;
594 1.9 christos }
595 1.9 christos
596 1.9 christos static Channel *
597 1.18 christos server_request_tun(struct ssh *ssh)
598 1.1 christos {
599 1.1 christos Channel *c = NULL;
600 1.25 christos u_int mode, tun;
601 1.25 christos int r, sock;
602 1.19 christos char *tmp, *ifname = NULL;
603 1.1 christos
604 1.25 christos if ((r = sshpkt_get_u32(ssh, &mode)) != 0)
605 1.25 christos sshpkt_fatal(ssh, r, "%s: parse mode", __func__);
606 1.1 christos switch (mode) {
607 1.1 christos case SSH_TUNMODE_POINTOPOINT:
608 1.1 christos case SSH_TUNMODE_ETHERNET:
609 1.1 christos break;
610 1.1 christos default:
611 1.25 christos ssh_packet_send_debug(ssh, "Unsupported tunnel device mode.");
612 1.1 christos return NULL;
613 1.1 christos }
614 1.1 christos if ((options.permit_tun & mode) == 0) {
615 1.25 christos ssh_packet_send_debug(ssh, "Server has rejected tunnel device "
616 1.1 christos "forwarding");
617 1.1 christos return NULL;
618 1.1 christos }
619 1.1 christos
620 1.25 christos if ((r = sshpkt_get_u32(ssh, &tun)) != 0)
621 1.25 christos sshpkt_fatal(ssh, r, "%s: parse device", __func__);
622 1.25 christos if (tun > INT_MAX) {
623 1.25 christos debug("%s: invalid tun", __func__);
624 1.25 christos goto done;
625 1.25 christos }
626 1.19 christos if (auth_opts->force_tun_device != -1) {
627 1.25 christos if (tun != SSH_TUNID_ANY &&
628 1.25 christos auth_opts->force_tun_device != (int)tun)
629 1.1 christos goto done;
630 1.19 christos tun = auth_opts->force_tun_device;
631 1.1 christos }
632 1.19 christos sock = tun_open(tun, mode, &ifname);
633 1.1 christos if (sock < 0)
634 1.1 christos goto done;
635 1.19 christos debug("Tunnel forwarding using interface %s", ifname);
636 1.19 christos
637 1.2 christos if (options.hpn_disabled)
638 1.18 christos c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
639 1.1 christos CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
640 1.2 christos else
641 1.18 christos c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
642 1.2 christos options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
643 1.1 christos c->datagram = 1;
644 1.1 christos
645 1.19 christos /*
646 1.19 christos * Update the list of names exposed to the session
647 1.19 christos * XXX remove these if the tunnels are closed (won't matter
648 1.19 christos * much if they are already in the environment though)
649 1.19 christos */
650 1.19 christos tmp = tun_fwd_ifnames;
651 1.19 christos xasprintf(&tun_fwd_ifnames, "%s%s%s",
652 1.19 christos tun_fwd_ifnames == NULL ? "" : tun_fwd_ifnames,
653 1.19 christos tun_fwd_ifnames == NULL ? "" : ",",
654 1.19 christos ifname);
655 1.19 christos free(tmp);
656 1.19 christos free(ifname);
657 1.19 christos
658 1.1 christos done:
659 1.1 christos if (c == NULL)
660 1.25 christos ssh_packet_send_debug(ssh, "Failed to open the tunnel device.");
661 1.1 christos return c;
662 1.1 christos }
663 1.1 christos
664 1.1 christos static Channel *
665 1.18 christos server_request_session(struct ssh *ssh)
666 1.1 christos {
667 1.1 christos Channel *c;
668 1.25 christos int r;
669 1.1 christos
670 1.1 christos debug("input_session_request");
671 1.25 christos if ((r = sshpkt_get_end(ssh)) != 0)
672 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
673 1.1 christos
674 1.1 christos if (no_more_sessions) {
675 1.25 christos ssh_packet_disconnect(ssh, "Possible attack: attempt to open a "
676 1.25 christos "session after additional sessions disabled");
677 1.1 christos }
678 1.1 christos
679 1.1 christos /*
680 1.1 christos * A server session has no fd to read or write until a
681 1.1 christos * CHANNEL_REQUEST for a shell is made, so we set the type to
682 1.1 christos * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
683 1.1 christos * CHANNEL_REQUEST messages is registered.
684 1.1 christos */
685 1.18 christos c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
686 1.1 christos -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
687 1.1 christos 0, "server-session", 1);
688 1.2 christos if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled))
689 1.2 christos c->dynamic_window = 1;
690 1.1 christos if (session_open(the_authctxt, c->self) != 1) {
691 1.1 christos debug("session open failed, free channel %d", c->self);
692 1.18 christos channel_free(ssh, c);
693 1.1 christos return NULL;
694 1.1 christos }
695 1.18 christos channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
696 1.1 christos return c;
697 1.1 christos }
698 1.1 christos
699 1.10 christos static int
700 1.18 christos server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
701 1.1 christos {
702 1.1 christos Channel *c = NULL;
703 1.25 christos char *ctype = NULL;
704 1.17 christos const char *errmsg = NULL;
705 1.25 christos int r, reason = SSH2_OPEN_CONNECT_FAILED;
706 1.25 christos u_int rchan = 0, rmaxpack = 0, rwindow = 0;
707 1.1 christos
708 1.25 christos if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 ||
709 1.25 christos (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
710 1.25 christos (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
711 1.25 christos (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
712 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
713 1.25 christos debug("%s: ctype %s rchan %u win %u max %u", __func__,
714 1.1 christos ctype, rchan, rwindow, rmaxpack);
715 1.1 christos
716 1.27 christos if (strcmp(ctype, "session") == 0) {
717 1.18 christos c = server_request_session(ssh);
718 1.1 christos } else if (strcmp(ctype, "direct-tcpip") == 0) {
719 1.18 christos c = server_request_direct_tcpip(ssh, &reason, &errmsg);
720 1.9 christos } else if (strcmp(ctype, "direct-streamlocal (at) openssh.com") == 0) {
721 1.18 christos c = server_request_direct_streamlocal(ssh);
722 1.1 christos } else if (strcmp(ctype, "tun (at) openssh.com") == 0) {
723 1.18 christos c = server_request_tun(ssh);
724 1.1 christos }
725 1.1 christos if (c != NULL) {
726 1.21 christos debug("%s: confirm %s", __func__, ctype);
727 1.27 christos c->remote_id = rchan;
728 1.18 christos c->have_remote_id = 1;
729 1.1 christos c->remote_window = rwindow;
730 1.1 christos c->remote_maxpacket = rmaxpack;
731 1.1 christos if (c->type != SSH_CHANNEL_CONNECTING) {
732 1.25 christos if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
733 1.25 christos (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
734 1.25 christos (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
735 1.25 christos (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
736 1.25 christos (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
737 1.25 christos (r = sshpkt_send(ssh)) != 0) {
738 1.25 christos sshpkt_fatal(ssh, r,
739 1.25 christos "%s: send open confirm", __func__);
740 1.25 christos }
741 1.1 christos }
742 1.1 christos } else {
743 1.21 christos debug("%s: failure %s", __func__, ctype);
744 1.25 christos if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
745 1.25 christos (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
746 1.25 christos (r = sshpkt_put_u32(ssh, reason)) != 0 ||
747 1.25 christos (r = sshpkt_put_cstring(ssh, errmsg ? errmsg : "open failed")) != 0 ||
748 1.25 christos (r = sshpkt_put_cstring(ssh, "")) != 0 ||
749 1.25 christos (r = sshpkt_send(ssh)) != 0) {
750 1.25 christos sshpkt_fatal(ssh, r,
751 1.25 christos "%s: send open failure", __func__);
752 1.25 christos }
753 1.1 christos }
754 1.7 christos free(ctype);
755 1.10 christos return 0;
756 1.10 christos }
757 1.10 christos
758 1.10 christos static int
759 1.18 christos server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
760 1.10 christos {
761 1.10 christos struct sshbuf *resp = NULL;
762 1.10 christos struct sshbuf *sigbuf = NULL;
763 1.10 christos struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
764 1.19 christos int r, ndx, kexsigtype, use_kexsigtype, success = 0;
765 1.10 christos const u_char *blob;
766 1.10 christos u_char *sig = 0;
767 1.10 christos size_t blen, slen;
768 1.10 christos
769 1.10 christos if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
770 1.10 christos fatal("%s: sshbuf_new", __func__);
771 1.10 christos
772 1.19 christos kexsigtype = sshkey_type_plain(
773 1.19 christos sshkey_type_from_name(ssh->kex->hostkey_alg));
774 1.10 christos while (ssh_packet_remaining(ssh) > 0) {
775 1.10 christos sshkey_free(key);
776 1.10 christos key = NULL;
777 1.10 christos if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
778 1.10 christos (r = sshkey_from_blob(blob, blen, &key)) != 0) {
779 1.10 christos error("%s: couldn't parse key: %s",
780 1.10 christos __func__, ssh_err(r));
781 1.10 christos goto out;
782 1.10 christos }
783 1.10 christos /*
784 1.10 christos * Better check that this is actually one of our hostkeys
785 1.10 christos * before attempting to sign anything with it.
786 1.10 christos */
787 1.10 christos if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
788 1.10 christos error("%s: unknown host %s key",
789 1.10 christos __func__, sshkey_type(key));
790 1.10 christos goto out;
791 1.10 christos }
792 1.10 christos /*
793 1.10 christos * XXX refactor: make kex->sign just use an index rather
794 1.10 christos * than passing in public and private keys
795 1.10 christos */
796 1.10 christos if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
797 1.10 christos (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
798 1.10 christos error("%s: can't retrieve hostkey %d", __func__, ndx);
799 1.10 christos goto out;
800 1.10 christos }
801 1.10 christos sshbuf_reset(sigbuf);
802 1.10 christos free(sig);
803 1.10 christos sig = NULL;
804 1.19 christos /*
805 1.19 christos * For RSA keys, prefer to use the signature type negotiated
806 1.19 christos * during KEX to the default (SHA1).
807 1.19 christos */
808 1.19 christos use_kexsigtype = kexsigtype == KEY_RSA &&
809 1.19 christos sshkey_type_plain(key->type) == KEY_RSA;
810 1.10 christos if ((r = sshbuf_put_cstring(sigbuf,
811 1.10 christos "hostkeys-prove-00 (at) openssh.com")) != 0 ||
812 1.10 christos (r = sshbuf_put_string(sigbuf,
813 1.10 christos ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
814 1.10 christos (r = sshkey_puts(key, sigbuf)) != 0 ||
815 1.25 christos (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen,
816 1.19 christos sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
817 1.25 christos use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 ||
818 1.10 christos (r = sshbuf_put_string(resp, sig, slen)) != 0) {
819 1.10 christos error("%s: couldn't prepare signature: %s",
820 1.10 christos __func__, ssh_err(r));
821 1.10 christos goto out;
822 1.10 christos }
823 1.10 christos }
824 1.10 christos /* Success */
825 1.10 christos *respp = resp;
826 1.10 christos resp = NULL; /* don't free it */
827 1.10 christos success = 1;
828 1.10 christos out:
829 1.10 christos free(sig);
830 1.10 christos sshbuf_free(resp);
831 1.10 christos sshbuf_free(sigbuf);
832 1.10 christos sshkey_free(key);
833 1.10 christos return success;
834 1.1 christos }
835 1.1 christos
836 1.10 christos static int
837 1.18 christos server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
838 1.1 christos {
839 1.25 christos char *rtype = NULL;
840 1.25 christos u_char want_reply = 0;
841 1.10 christos int r, success = 0, allocated_listen_port = 0;
842 1.25 christos u_int port = 0;
843 1.10 christos struct sshbuf *resp = NULL;
844 1.17 christos struct passwd *pw = the_authctxt->pw;
845 1.25 christos struct Forward fwd;
846 1.17 christos
847 1.25 christos memset(&fwd, 0, sizeof(fwd));
848 1.17 christos if (pw == NULL || !the_authctxt->valid)
849 1.21 christos fatal("%s: no/invalid user", __func__);
850 1.1 christos
851 1.25 christos if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
852 1.25 christos (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
853 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
854 1.21 christos debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply);
855 1.1 christos
856 1.1 christos /* -R style forwarding */
857 1.1 christos if (strcmp(rtype, "tcpip-forward") == 0) {
858 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
859 1.25 christos (r = sshpkt_get_u32(ssh, &port)) != 0)
860 1.25 christos sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__);
861 1.25 christos debug("%s: tcpip-forward listen %s port %u", __func__,
862 1.25 christos fwd.listen_host, port);
863 1.25 christos if (port <= INT_MAX)
864 1.25 christos fwd.listen_port = (int)port;
865 1.1 christos /* check permissions */
866 1.25 christos if (port > INT_MAX ||
867 1.25 christos (options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
868 1.19 christos !auth_opts->permit_port_forwarding_flag ||
869 1.19 christos options.disable_forwarding ||
870 1.9 christos (!want_reply && fwd.listen_port == 0) ||
871 1.16 christos (fwd.listen_port != 0 &&
872 1.16 christos !bind_permitted(fwd.listen_port, pw->pw_uid))) {
873 1.1 christos success = 0;
874 1.25 christos ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
875 1.1 christos } else {
876 1.1 christos /* Start listening on the port */
877 1.18 christos success = channel_setup_remote_fwd_listener(ssh, &fwd,
878 1.9 christos &allocated_listen_port, &options.fwd_opts);
879 1.1 christos }
880 1.10 christos if ((resp = sshbuf_new()) == NULL)
881 1.10 christos fatal("%s: sshbuf_new", __func__);
882 1.14 christos if (allocated_listen_port != 0 &&
883 1.14 christos (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
884 1.10 christos fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
885 1.1 christos } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
886 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
887 1.25 christos (r = sshpkt_get_u32(ssh, &port)) != 0)
888 1.25 christos sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__);
889 1.1 christos
890 1.1 christos debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
891 1.25 christos fwd.listen_host, port);
892 1.25 christos if (port <= INT_MAX) {
893 1.25 christos fwd.listen_port = (int)port;
894 1.25 christos success = channel_cancel_rport_listener(ssh, &fwd);
895 1.25 christos }
896 1.9 christos } else if (strcmp(rtype, "streamlocal-forward (at) openssh.com") == 0) {
897 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
898 1.25 christos sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward (at) openssh.com", __func__);
899 1.21 christos debug("%s: streamlocal-forward listen path %s", __func__,
900 1.9 christos fwd.listen_path);
901 1.9 christos
902 1.9 christos /* check permissions */
903 1.9 christos if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
904 1.19 christos || !auth_opts->permit_port_forwarding_flag ||
905 1.19 christos options.disable_forwarding ||
906 1.17 christos (pw->pw_uid != 0 && !use_privsep)) {
907 1.9 christos success = 0;
908 1.25 christos ssh_packet_send_debug(ssh, "Server has disabled "
909 1.17 christos "streamlocal forwarding.");
910 1.9 christos } else {
911 1.9 christos /* Start listening on the socket */
912 1.18 christos success = channel_setup_remote_fwd_listener(ssh,
913 1.9 christos &fwd, NULL, &options.fwd_opts);
914 1.9 christos }
915 1.9 christos } else if (strcmp(rtype, "cancel-streamlocal-forward (at) openssh.com") == 0) {
916 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
917 1.25 christos sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward (at) openssh.com", __func__);
918 1.9 christos debug("%s: cancel-streamlocal-forward path %s", __func__,
919 1.9 christos fwd.listen_path);
920 1.1 christos
921 1.18 christos success = channel_cancel_rport_listener(ssh, &fwd);
922 1.1 christos } else if (strcmp(rtype, "no-more-sessions (at) openssh.com") == 0) {
923 1.1 christos no_more_sessions = 1;
924 1.1 christos success = 1;
925 1.10 christos } else if (strcmp(rtype, "hostkeys-prove-00 (at) openssh.com") == 0) {
926 1.18 christos success = server_input_hostkeys_prove(ssh, &resp);
927 1.1 christos }
928 1.25 christos /* XXX sshpkt_get_end() */
929 1.1 christos if (want_reply) {
930 1.25 christos if ((r = sshpkt_start(ssh, success ?
931 1.25 christos SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 ||
932 1.25 christos (success && resp != NULL && (r = sshpkt_putb(ssh, resp)) != 0) ||
933 1.25 christos (r = sshpkt_send(ssh)) != 0 ||
934 1.25 christos (r = ssh_packet_write_wait(ssh)) < 0)
935 1.25 christos sshpkt_fatal(ssh, r, "%s: send reply", __func__);
936 1.1 christos }
937 1.25 christos free(fwd.listen_host);
938 1.25 christos free(fwd.listen_path);
939 1.7 christos free(rtype);
940 1.10 christos sshbuf_free(resp);
941 1.10 christos return 0;
942 1.1 christos }
943 1.1 christos
944 1.10 christos static int
945 1.18 christos server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
946 1.1 christos {
947 1.1 christos Channel *c;
948 1.25 christos int r, success = 0;
949 1.25 christos char *rtype = NULL;
950 1.25 christos u_char want_reply = 0;
951 1.25 christos u_int id = 0;
952 1.25 christos
953 1.25 christos if ((r = sshpkt_get_u32(ssh, &id)) != 0 ||
954 1.25 christos (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
955 1.25 christos (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
956 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
957 1.25 christos
958 1.25 christos debug("server_input_channel_req: channel %u request %s reply %d",
959 1.25 christos id, rtype, want_reply);
960 1.25 christos
961 1.25 christos if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) {
962 1.25 christos ssh_packet_disconnect(ssh, "%s: unknown channel %d",
963 1.25 christos __func__, id);
964 1.25 christos }
965 1.1 christos if (!strcmp(rtype, "eow (at) openssh.com")) {
966 1.25 christos if ((r = sshpkt_get_end(ssh)) != 0)
967 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
968 1.18 christos chan_rcvd_eow(ssh, c);
969 1.1 christos } else if ((c->type == SSH_CHANNEL_LARVAL ||
970 1.1 christos c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
971 1.18 christos success = session_input_channel_req(ssh, c, rtype);
972 1.25 christos if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) {
973 1.18 christos if (!c->have_remote_id)
974 1.18 christos fatal("%s: channel %d: no remote_id",
975 1.18 christos __func__, c->self);
976 1.25 christos if ((r = sshpkt_start(ssh, success ?
977 1.25 christos SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
978 1.25 christos (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
979 1.25 christos (r = sshpkt_send(ssh)) != 0)
980 1.25 christos sshpkt_fatal(ssh, r, "%s: send reply", __func__);
981 1.1 christos }
982 1.7 christos free(rtype);
983 1.10 christos return 0;
984 1.1 christos }
985 1.1 christos
986 1.1 christos static void
987 1.25 christos server_init_dispatch(struct ssh *ssh)
988 1.1 christos {
989 1.16 christos debug("server_init_dispatch");
990 1.25 christos ssh_dispatch_init(ssh, &dispatch_protocol_error);
991 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
992 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
993 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
994 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
995 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
996 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
997 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
998 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
999 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1000 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
1001 1.1 christos /* client_alive */
1002 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
1003 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
1004 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
1005 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
1006 1.1 christos /* rekeying */
1007 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
1008 1.1 christos }
1009