serverloop.c revision 1.29 1 1.26 christos /* $NetBSD: serverloop.c,v 1.29 2021/03/05 17:47:16 christos Exp $ */
2 1.29 christos /* $OpenBSD: serverloop.c,v 1.225 2021/01/27 10:05:28 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.29 2021/03/05 17:47:16 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.29 christos debug2_f("reading");
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.29 christos fatal_fr(r, "compose");
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.29 christos fatal_fr(r, "send");
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.29 christos if (errno == EINTR || errno == EAGAIN)
354 1.29 christos return 0;
355 1.29 christos verbose("Read error from remote host %s port %d: %s",
356 1.29 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
357 1.29 christos strerror(errno));
358 1.29 christos cleanup_exit(254);
359 1.1 christos }
360 1.29 christos /* Buffer any received data. */
361 1.29 christos if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
362 1.29 christos fatal_fr(r, "ssh_packet_process_incoming");
363 1.1 christos }
364 1.16 christos return 0;
365 1.1 christos }
366 1.1 christos
367 1.1 christos /*
368 1.1 christos * Sends data from internal buffers to client program stdin.
369 1.1 christos */
370 1.1 christos static void
371 1.25 christos process_output(struct ssh *ssh, fd_set *writeset, int connection_out)
372 1.1 christos {
373 1.25 christos int r;
374 1.25 christos
375 1.1 christos /* Send any buffered packet data to the client. */
376 1.25 christos if (FD_ISSET(connection_out, writeset)) {
377 1.25 christos if ((r = ssh_packet_write_poll(ssh)) < 0)
378 1.27 christos sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll",
379 1.27 christos __func__);
380 1.25 christos }
381 1.1 christos }
382 1.1 christos
383 1.1 christos static void
384 1.18 christos process_buffered_input_packets(struct ssh *ssh)
385 1.1 christos {
386 1.18 christos ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
387 1.1 christos }
388 1.1 christos
389 1.1 christos static void
390 1.18 christos collect_children(struct ssh *ssh)
391 1.1 christos {
392 1.1 christos pid_t pid;
393 1.1 christos sigset_t oset, nset;
394 1.1 christos int status;
395 1.1 christos
396 1.1 christos /* block SIGCHLD while we check for dead children */
397 1.1 christos sigemptyset(&nset);
398 1.1 christos sigaddset(&nset, SIGCHLD);
399 1.1 christos sigprocmask(SIG_BLOCK, &nset, &oset);
400 1.1 christos if (child_terminated) {
401 1.1 christos debug("Received SIGCHLD.");
402 1.1 christos while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
403 1.26 christos (pid == -1 && errno == EINTR))
404 1.1 christos if (pid > 0)
405 1.18 christos session_close_by_pid(ssh, pid, status);
406 1.1 christos child_terminated = 0;
407 1.1 christos }
408 1.1 christos sigprocmask(SIG_SETMASK, &oset, NULL);
409 1.1 christos }
410 1.1 christos
411 1.1 christos void
412 1.18 christos server_loop2(struct ssh *ssh, Authctxt *authctxt)
413 1.1 christos {
414 1.1 christos fd_set *readset = NULL, *writeset = NULL;
415 1.14 christos int max_fd;
416 1.16 christos u_int nalloc = 0, connection_in, connection_out;
417 1.7 christos u_int64_t rekey_timeout_ms = 0;
418 1.2 christos double start_time, total_time;
419 1.1 christos
420 1.1 christos debug("Entering interactive session for SSH2.");
421 1.2 christos start_time = get_current_time();
422 1.1 christos
423 1.27 christos ssh_signal(SIGCHLD, sigchld_handler);
424 1.1 christos child_terminated = 0;
425 1.25 christos connection_in = ssh_packet_get_connection_in(ssh);
426 1.25 christos connection_out = ssh_packet_get_connection_out(ssh);
427 1.1 christos
428 1.1 christos if (!use_privsep) {
429 1.27 christos ssh_signal(SIGTERM, sigterm_handler);
430 1.27 christos ssh_signal(SIGINT, sigterm_handler);
431 1.27 christos ssh_signal(SIGQUIT, sigterm_handler);
432 1.1 christos }
433 1.1 christos
434 1.1 christos notify_setup();
435 1.1 christos
436 1.16 christos max_fd = MAXIMUM(connection_in, connection_out);
437 1.16 christos max_fd = MAXIMUM(max_fd, notify_pipe[0]);
438 1.1 christos
439 1.25 christos server_init_dispatch(ssh);
440 1.1 christos
441 1.1 christos for (;;) {
442 1.18 christos process_buffered_input_packets(ssh);
443 1.1 christos
444 1.18 christos if (!ssh_packet_is_rekeying(ssh) &&
445 1.25 christos ssh_packet_not_very_much_data_to_write(ssh))
446 1.18 christos channel_output_poll(ssh);
447 1.25 christos if (options.rekey_interval > 0 &&
448 1.25 christos !ssh_packet_is_rekeying(ssh)) {
449 1.25 christos rekey_timeout_ms = ssh_packet_get_rekey_timeout(ssh) *
450 1.25 christos 1000;
451 1.25 christos } else {
452 1.7 christos rekey_timeout_ms = 0;
453 1.25 christos }
454 1.7 christos
455 1.18 christos wait_until_can_do_something(ssh, connection_in, connection_out,
456 1.16 christos &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
457 1.1 christos
458 1.1 christos if (received_sigterm) {
459 1.6 christos logit("Exiting on signal %d", (int)received_sigterm);
460 1.1 christos /* Clean up sessions, utmp, etc. */
461 1.23 christos cleanup_exit(254);
462 1.1 christos }
463 1.1 christos
464 1.18 christos collect_children(ssh);
465 1.18 christos if (!ssh_packet_is_rekeying(ssh))
466 1.18 christos channel_after_select(ssh, readset, writeset);
467 1.18 christos if (process_input(ssh, readset, connection_in) < 0)
468 1.1 christos break;
469 1.25 christos process_output(ssh, writeset, connection_out);
470 1.1 christos }
471 1.18 christos collect_children(ssh);
472 1.1 christos
473 1.7 christos free(readset);
474 1.7 christos free(writeset);
475 1.1 christos
476 1.1 christos /* free all channels, no more reads and writes */
477 1.18 christos channel_free_all(ssh);
478 1.1 christos
479 1.1 christos /* free remaining sessions, e.g. remove wtmp entries */
480 1.18 christos session_destroy_all(ssh, NULL);
481 1.2 christos total_time = get_current_time() - start_time;
482 1.2 christos logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
483 1.15 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
484 1.2 christos stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time,
485 1.2 christos fdout_bytes / total_time);
486 1.1 christos }
487 1.1 christos
488 1.10 christos static int
489 1.18 christos server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
490 1.1 christos {
491 1.1 christos debug("Got %d/%u for keepalive", type, seq);
492 1.1 christos /*
493 1.1 christos * reset timeout, since we got a sane answer from the client.
494 1.1 christos * even if this was generated by something other than
495 1.1 christos * the bogus CHANNEL_REQUEST we send for keepalives.
496 1.1 christos */
497 1.25 christos ssh_packet_set_alive_timeouts(ssh, 0);
498 1.10 christos return 0;
499 1.1 christos }
500 1.1 christos
501 1.1 christos static Channel *
502 1.18 christos server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
503 1.1 christos {
504 1.6 christos Channel *c = NULL;
505 1.25 christos char *target = NULL, *originator = NULL;
506 1.25 christos u_int target_port = 0, originator_port = 0;
507 1.25 christos int r;
508 1.25 christos
509 1.25 christos if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
510 1.25 christos (r = sshpkt_get_u32(ssh, &target_port)) != 0 ||
511 1.25 christos (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
512 1.25 christos (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
513 1.25 christos (r = sshpkt_get_end(ssh)) != 0)
514 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
515 1.25 christos if (target_port > 0xFFFF) {
516 1.29 christos error_f("invalid target port");
517 1.25 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
518 1.25 christos goto out;
519 1.25 christos }
520 1.25 christos if (originator_port > 0xFFFF) {
521 1.29 christos error_f("invalid originator port");
522 1.25 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
523 1.25 christos goto out;
524 1.25 christos }
525 1.1 christos
526 1.29 christos debug_f("originator %s port %u, target %s port %u",
527 1.19 christos originator, originator_port, target, target_port);
528 1.1 christos
529 1.6 christos /* XXX fine grained permissions */
530 1.6 christos if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
531 1.19 christos auth_opts->permit_port_forwarding_flag &&
532 1.19 christos !options.disable_forwarding) {
533 1.18 christos c = channel_connect_to_port(ssh, target, target_port,
534 1.17 christos "direct-tcpip", "direct-tcpip", reason, errmsg);
535 1.6 christos } else {
536 1.6 christos logit("refused local port forward: "
537 1.6 christos "originator %s port %d, target %s port %d",
538 1.6 christos originator, originator_port, target, target_port);
539 1.17 christos if (reason != NULL)
540 1.17 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
541 1.6 christos }
542 1.1 christos
543 1.25 christos out:
544 1.7 christos free(originator);
545 1.7 christos free(target);
546 1.1 christos return c;
547 1.1 christos }
548 1.1 christos
549 1.1 christos static Channel *
550 1.18 christos server_request_direct_streamlocal(struct ssh *ssh)
551 1.9 christos {
552 1.9 christos Channel *c = NULL;
553 1.25 christos char *target = NULL, *originator = NULL;
554 1.25 christos u_int originator_port = 0;
555 1.17 christos struct passwd *pw = the_authctxt->pw;
556 1.25 christos int r;
557 1.17 christos
558 1.17 christos if (pw == NULL || !the_authctxt->valid)
559 1.29 christos fatal_f("no/invalid user");
560 1.9 christos
561 1.25 christos if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
562 1.25 christos (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
563 1.25 christos (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
564 1.25 christos (r = sshpkt_get_end(ssh)) != 0)
565 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
566 1.25 christos if (originator_port > 0xFFFF) {
567 1.29 christos error_f("invalid originator port");
568 1.25 christos goto out;
569 1.25 christos }
570 1.9 christos
571 1.29 christos debug_f("originator %s port %d, target %s",
572 1.9 christos originator, originator_port, target);
573 1.9 christos
574 1.9 christos /* XXX fine grained permissions */
575 1.9 christos if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
576 1.19 christos auth_opts->permit_port_forwarding_flag &&
577 1.19 christos !options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) {
578 1.18 christos c = channel_connect_to_path(ssh, target,
579 1.9 christos "direct-streamlocal (at) openssh.com", "direct-streamlocal");
580 1.9 christos } else {
581 1.9 christos logit("refused streamlocal port forward: "
582 1.9 christos "originator %s port %d, target %s",
583 1.9 christos originator, originator_port, target);
584 1.9 christos }
585 1.9 christos
586 1.25 christos out:
587 1.9 christos free(originator);
588 1.9 christos free(target);
589 1.9 christos return c;
590 1.9 christos }
591 1.9 christos
592 1.9 christos static Channel *
593 1.18 christos server_request_tun(struct ssh *ssh)
594 1.1 christos {
595 1.1 christos Channel *c = NULL;
596 1.25 christos u_int mode, tun;
597 1.25 christos int r, sock;
598 1.19 christos char *tmp, *ifname = NULL;
599 1.1 christos
600 1.25 christos if ((r = sshpkt_get_u32(ssh, &mode)) != 0)
601 1.25 christos sshpkt_fatal(ssh, r, "%s: parse mode", __func__);
602 1.1 christos switch (mode) {
603 1.1 christos case SSH_TUNMODE_POINTOPOINT:
604 1.1 christos case SSH_TUNMODE_ETHERNET:
605 1.1 christos break;
606 1.1 christos default:
607 1.25 christos ssh_packet_send_debug(ssh, "Unsupported tunnel device mode.");
608 1.1 christos return NULL;
609 1.1 christos }
610 1.1 christos if ((options.permit_tun & mode) == 0) {
611 1.25 christos ssh_packet_send_debug(ssh, "Server has rejected tunnel device "
612 1.1 christos "forwarding");
613 1.1 christos return NULL;
614 1.1 christos }
615 1.1 christos
616 1.25 christos if ((r = sshpkt_get_u32(ssh, &tun)) != 0)
617 1.25 christos sshpkt_fatal(ssh, r, "%s: parse device", __func__);
618 1.25 christos if (tun > INT_MAX) {
619 1.29 christos debug_f("invalid tun");
620 1.25 christos goto done;
621 1.25 christos }
622 1.19 christos if (auth_opts->force_tun_device != -1) {
623 1.25 christos if (tun != SSH_TUNID_ANY &&
624 1.25 christos auth_opts->force_tun_device != (int)tun)
625 1.1 christos goto done;
626 1.19 christos tun = auth_opts->force_tun_device;
627 1.1 christos }
628 1.19 christos sock = tun_open(tun, mode, &ifname);
629 1.1 christos if (sock < 0)
630 1.1 christos goto done;
631 1.19 christos debug("Tunnel forwarding using interface %s", ifname);
632 1.19 christos
633 1.2 christos if (options.hpn_disabled)
634 1.18 christos c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
635 1.1 christos CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
636 1.2 christos else
637 1.18 christos c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
638 1.2 christos options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
639 1.1 christos c->datagram = 1;
640 1.1 christos
641 1.19 christos /*
642 1.19 christos * Update the list of names exposed to the session
643 1.19 christos * XXX remove these if the tunnels are closed (won't matter
644 1.19 christos * much if they are already in the environment though)
645 1.19 christos */
646 1.19 christos tmp = tun_fwd_ifnames;
647 1.19 christos xasprintf(&tun_fwd_ifnames, "%s%s%s",
648 1.19 christos tun_fwd_ifnames == NULL ? "" : tun_fwd_ifnames,
649 1.19 christos tun_fwd_ifnames == NULL ? "" : ",",
650 1.19 christos ifname);
651 1.19 christos free(tmp);
652 1.19 christos free(ifname);
653 1.19 christos
654 1.1 christos done:
655 1.1 christos if (c == NULL)
656 1.25 christos ssh_packet_send_debug(ssh, "Failed to open the tunnel device.");
657 1.1 christos return c;
658 1.1 christos }
659 1.1 christos
660 1.1 christos static Channel *
661 1.18 christos server_request_session(struct ssh *ssh)
662 1.1 christos {
663 1.1 christos Channel *c;
664 1.25 christos int r;
665 1.1 christos
666 1.1 christos debug("input_session_request");
667 1.25 christos if ((r = sshpkt_get_end(ssh)) != 0)
668 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
669 1.1 christos
670 1.1 christos if (no_more_sessions) {
671 1.25 christos ssh_packet_disconnect(ssh, "Possible attack: attempt to open a "
672 1.25 christos "session after additional sessions disabled");
673 1.1 christos }
674 1.1 christos
675 1.1 christos /*
676 1.1 christos * A server session has no fd to read or write until a
677 1.1 christos * CHANNEL_REQUEST for a shell is made, so we set the type to
678 1.1 christos * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
679 1.1 christos * CHANNEL_REQUEST messages is registered.
680 1.1 christos */
681 1.18 christos c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
682 1.1 christos -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
683 1.1 christos 0, "server-session", 1);
684 1.2 christos if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled))
685 1.2 christos c->dynamic_window = 1;
686 1.1 christos if (session_open(the_authctxt, c->self) != 1) {
687 1.1 christos debug("session open failed, free channel %d", c->self);
688 1.18 christos channel_free(ssh, c);
689 1.1 christos return NULL;
690 1.1 christos }
691 1.18 christos channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
692 1.1 christos return c;
693 1.1 christos }
694 1.1 christos
695 1.10 christos static int
696 1.18 christos server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
697 1.1 christos {
698 1.1 christos Channel *c = NULL;
699 1.25 christos char *ctype = NULL;
700 1.17 christos const char *errmsg = NULL;
701 1.25 christos int r, reason = SSH2_OPEN_CONNECT_FAILED;
702 1.25 christos u_int rchan = 0, rmaxpack = 0, rwindow = 0;
703 1.1 christos
704 1.25 christos if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 ||
705 1.25 christos (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
706 1.25 christos (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
707 1.25 christos (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
708 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
709 1.29 christos debug_f("ctype %s rchan %u win %u max %u",
710 1.1 christos ctype, rchan, rwindow, rmaxpack);
711 1.1 christos
712 1.27 christos if (strcmp(ctype, "session") == 0) {
713 1.18 christos c = server_request_session(ssh);
714 1.1 christos } else if (strcmp(ctype, "direct-tcpip") == 0) {
715 1.18 christos c = server_request_direct_tcpip(ssh, &reason, &errmsg);
716 1.9 christos } else if (strcmp(ctype, "direct-streamlocal (at) openssh.com") == 0) {
717 1.18 christos c = server_request_direct_streamlocal(ssh);
718 1.1 christos } else if (strcmp(ctype, "tun (at) openssh.com") == 0) {
719 1.18 christos c = server_request_tun(ssh);
720 1.1 christos }
721 1.1 christos if (c != NULL) {
722 1.29 christos debug_f("confirm %s", ctype);
723 1.27 christos c->remote_id = rchan;
724 1.18 christos c->have_remote_id = 1;
725 1.1 christos c->remote_window = rwindow;
726 1.1 christos c->remote_maxpacket = rmaxpack;
727 1.1 christos if (c->type != SSH_CHANNEL_CONNECTING) {
728 1.25 christos if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
729 1.25 christos (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
730 1.25 christos (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
731 1.25 christos (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
732 1.25 christos (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
733 1.25 christos (r = sshpkt_send(ssh)) != 0) {
734 1.25 christos sshpkt_fatal(ssh, r,
735 1.25 christos "%s: send open confirm", __func__);
736 1.25 christos }
737 1.1 christos }
738 1.1 christos } else {
739 1.29 christos debug_f("failure %s", ctype);
740 1.25 christos if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
741 1.25 christos (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
742 1.25 christos (r = sshpkt_put_u32(ssh, reason)) != 0 ||
743 1.25 christos (r = sshpkt_put_cstring(ssh, errmsg ? errmsg : "open failed")) != 0 ||
744 1.25 christos (r = sshpkt_put_cstring(ssh, "")) != 0 ||
745 1.25 christos (r = sshpkt_send(ssh)) != 0) {
746 1.25 christos sshpkt_fatal(ssh, r,
747 1.25 christos "%s: send open failure", __func__);
748 1.25 christos }
749 1.1 christos }
750 1.7 christos free(ctype);
751 1.10 christos return 0;
752 1.10 christos }
753 1.10 christos
754 1.10 christos static int
755 1.18 christos server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
756 1.10 christos {
757 1.10 christos struct sshbuf *resp = NULL;
758 1.10 christos struct sshbuf *sigbuf = NULL;
759 1.10 christos struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
760 1.19 christos int r, ndx, kexsigtype, use_kexsigtype, success = 0;
761 1.10 christos const u_char *blob;
762 1.10 christos u_char *sig = 0;
763 1.10 christos size_t blen, slen;
764 1.10 christos
765 1.10 christos if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
766 1.29 christos fatal_f("sshbuf_new");
767 1.10 christos
768 1.19 christos kexsigtype = sshkey_type_plain(
769 1.19 christos sshkey_type_from_name(ssh->kex->hostkey_alg));
770 1.10 christos while (ssh_packet_remaining(ssh) > 0) {
771 1.10 christos sshkey_free(key);
772 1.10 christos key = NULL;
773 1.10 christos if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
774 1.10 christos (r = sshkey_from_blob(blob, blen, &key)) != 0) {
775 1.29 christos error_fr(r, "parse key");
776 1.10 christos goto out;
777 1.10 christos }
778 1.10 christos /*
779 1.10 christos * Better check that this is actually one of our hostkeys
780 1.10 christos * before attempting to sign anything with it.
781 1.10 christos */
782 1.10 christos if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
783 1.29 christos error_f("unknown host %s key", sshkey_type(key));
784 1.10 christos goto out;
785 1.10 christos }
786 1.10 christos /*
787 1.10 christos * XXX refactor: make kex->sign just use an index rather
788 1.10 christos * than passing in public and private keys
789 1.10 christos */
790 1.10 christos if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
791 1.10 christos (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
792 1.29 christos error_f("can't retrieve hostkey %d", ndx);
793 1.10 christos goto out;
794 1.10 christos }
795 1.10 christos sshbuf_reset(sigbuf);
796 1.10 christos free(sig);
797 1.10 christos sig = NULL;
798 1.19 christos /*
799 1.19 christos * For RSA keys, prefer to use the signature type negotiated
800 1.19 christos * during KEX to the default (SHA1).
801 1.19 christos */
802 1.19 christos use_kexsigtype = kexsigtype == KEY_RSA &&
803 1.19 christos sshkey_type_plain(key->type) == KEY_RSA;
804 1.10 christos if ((r = sshbuf_put_cstring(sigbuf,
805 1.10 christos "hostkeys-prove-00 (at) openssh.com")) != 0 ||
806 1.29 christos (r = sshbuf_put_stringb(sigbuf,
807 1.29 christos ssh->kex->session_id)) != 0 ||
808 1.10 christos (r = sshkey_puts(key, sigbuf)) != 0 ||
809 1.25 christos (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen,
810 1.19 christos sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
811 1.25 christos use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 ||
812 1.10 christos (r = sshbuf_put_string(resp, sig, slen)) != 0) {
813 1.29 christos error_fr(r, "assemble signature");
814 1.10 christos goto out;
815 1.10 christos }
816 1.10 christos }
817 1.10 christos /* Success */
818 1.10 christos *respp = resp;
819 1.10 christos resp = NULL; /* don't free it */
820 1.10 christos success = 1;
821 1.10 christos out:
822 1.10 christos free(sig);
823 1.10 christos sshbuf_free(resp);
824 1.10 christos sshbuf_free(sigbuf);
825 1.10 christos sshkey_free(key);
826 1.10 christos return success;
827 1.1 christos }
828 1.1 christos
829 1.10 christos static int
830 1.18 christos server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
831 1.1 christos {
832 1.25 christos char *rtype = NULL;
833 1.25 christos u_char want_reply = 0;
834 1.10 christos int r, success = 0, allocated_listen_port = 0;
835 1.25 christos u_int port = 0;
836 1.10 christos struct sshbuf *resp = NULL;
837 1.17 christos struct passwd *pw = the_authctxt->pw;
838 1.25 christos struct Forward fwd;
839 1.17 christos
840 1.25 christos memset(&fwd, 0, sizeof(fwd));
841 1.17 christos if (pw == NULL || !the_authctxt->valid)
842 1.29 christos fatal_f("no/invalid user");
843 1.1 christos
844 1.25 christos if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
845 1.25 christos (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
846 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
847 1.29 christos debug_f("rtype %s want_reply %d", rtype, want_reply);
848 1.1 christos
849 1.1 christos /* -R style forwarding */
850 1.1 christos if (strcmp(rtype, "tcpip-forward") == 0) {
851 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
852 1.25 christos (r = sshpkt_get_u32(ssh, &port)) != 0)
853 1.25 christos sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__);
854 1.29 christos debug_f("tcpip-forward listen %s port %u",
855 1.25 christos fwd.listen_host, port);
856 1.25 christos if (port <= INT_MAX)
857 1.25 christos fwd.listen_port = (int)port;
858 1.1 christos /* check permissions */
859 1.25 christos if (port > INT_MAX ||
860 1.25 christos (options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
861 1.19 christos !auth_opts->permit_port_forwarding_flag ||
862 1.19 christos options.disable_forwarding ||
863 1.9 christos (!want_reply && fwd.listen_port == 0) ||
864 1.16 christos (fwd.listen_port != 0 &&
865 1.16 christos !bind_permitted(fwd.listen_port, pw->pw_uid))) {
866 1.1 christos success = 0;
867 1.25 christos ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
868 1.1 christos } else {
869 1.1 christos /* Start listening on the port */
870 1.18 christos success = channel_setup_remote_fwd_listener(ssh, &fwd,
871 1.9 christos &allocated_listen_port, &options.fwd_opts);
872 1.1 christos }
873 1.10 christos if ((resp = sshbuf_new()) == NULL)
874 1.29 christos fatal_f("sshbuf_new");
875 1.14 christos if (allocated_listen_port != 0 &&
876 1.14 christos (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
877 1.29 christos fatal_fr(r, "sshbuf_put_u32");
878 1.1 christos } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
879 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
880 1.25 christos (r = sshpkt_get_u32(ssh, &port)) != 0)
881 1.25 christos sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__);
882 1.1 christos
883 1.29 christos debug_f("cancel-tcpip-forward addr %s port %d",
884 1.25 christos fwd.listen_host, port);
885 1.25 christos if (port <= INT_MAX) {
886 1.25 christos fwd.listen_port = (int)port;
887 1.25 christos success = channel_cancel_rport_listener(ssh, &fwd);
888 1.25 christos }
889 1.9 christos } else if (strcmp(rtype, "streamlocal-forward (at) openssh.com") == 0) {
890 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
891 1.25 christos sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward (at) openssh.com", __func__);
892 1.29 christos debug_f("streamlocal-forward listen path %s",
893 1.9 christos fwd.listen_path);
894 1.9 christos
895 1.9 christos /* check permissions */
896 1.9 christos if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
897 1.19 christos || !auth_opts->permit_port_forwarding_flag ||
898 1.19 christos options.disable_forwarding ||
899 1.17 christos (pw->pw_uid != 0 && !use_privsep)) {
900 1.9 christos success = 0;
901 1.25 christos ssh_packet_send_debug(ssh, "Server has disabled "
902 1.17 christos "streamlocal forwarding.");
903 1.9 christos } else {
904 1.9 christos /* Start listening on the socket */
905 1.18 christos success = channel_setup_remote_fwd_listener(ssh,
906 1.9 christos &fwd, NULL, &options.fwd_opts);
907 1.9 christos }
908 1.9 christos } else if (strcmp(rtype, "cancel-streamlocal-forward (at) openssh.com") == 0) {
909 1.25 christos if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
910 1.25 christos sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward (at) openssh.com", __func__);
911 1.29 christos debug_f("cancel-streamlocal-forward path %s",
912 1.9 christos fwd.listen_path);
913 1.1 christos
914 1.18 christos success = channel_cancel_rport_listener(ssh, &fwd);
915 1.1 christos } else if (strcmp(rtype, "no-more-sessions (at) openssh.com") == 0) {
916 1.1 christos no_more_sessions = 1;
917 1.1 christos success = 1;
918 1.10 christos } else if (strcmp(rtype, "hostkeys-prove-00 (at) openssh.com") == 0) {
919 1.18 christos success = server_input_hostkeys_prove(ssh, &resp);
920 1.1 christos }
921 1.25 christos /* XXX sshpkt_get_end() */
922 1.1 christos if (want_reply) {
923 1.25 christos if ((r = sshpkt_start(ssh, success ?
924 1.25 christos SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 ||
925 1.25 christos (success && resp != NULL && (r = sshpkt_putb(ssh, resp)) != 0) ||
926 1.25 christos (r = sshpkt_send(ssh)) != 0 ||
927 1.25 christos (r = ssh_packet_write_wait(ssh)) < 0)
928 1.25 christos sshpkt_fatal(ssh, r, "%s: send reply", __func__);
929 1.1 christos }
930 1.25 christos free(fwd.listen_host);
931 1.25 christos free(fwd.listen_path);
932 1.7 christos free(rtype);
933 1.10 christos sshbuf_free(resp);
934 1.10 christos return 0;
935 1.1 christos }
936 1.1 christos
937 1.10 christos static int
938 1.18 christos server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
939 1.1 christos {
940 1.1 christos Channel *c;
941 1.25 christos int r, success = 0;
942 1.25 christos char *rtype = NULL;
943 1.25 christos u_char want_reply = 0;
944 1.25 christos u_int id = 0;
945 1.25 christos
946 1.25 christos if ((r = sshpkt_get_u32(ssh, &id)) != 0 ||
947 1.25 christos (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
948 1.25 christos (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
949 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
950 1.25 christos
951 1.25 christos debug("server_input_channel_req: channel %u request %s reply %d",
952 1.25 christos id, rtype, want_reply);
953 1.25 christos
954 1.25 christos if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) {
955 1.25 christos ssh_packet_disconnect(ssh, "%s: unknown channel %d",
956 1.25 christos __func__, id);
957 1.25 christos }
958 1.1 christos if (!strcmp(rtype, "eow (at) openssh.com")) {
959 1.25 christos if ((r = sshpkt_get_end(ssh)) != 0)
960 1.25 christos sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
961 1.18 christos chan_rcvd_eow(ssh, c);
962 1.1 christos } else if ((c->type == SSH_CHANNEL_LARVAL ||
963 1.1 christos c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
964 1.18 christos success = session_input_channel_req(ssh, c, rtype);
965 1.25 christos if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) {
966 1.18 christos if (!c->have_remote_id)
967 1.29 christos fatal_f("channel %d: no remote_id", c->self);
968 1.25 christos if ((r = sshpkt_start(ssh, success ?
969 1.25 christos SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
970 1.25 christos (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
971 1.25 christos (r = sshpkt_send(ssh)) != 0)
972 1.25 christos sshpkt_fatal(ssh, r, "%s: send reply", __func__);
973 1.1 christos }
974 1.7 christos free(rtype);
975 1.10 christos return 0;
976 1.1 christos }
977 1.1 christos
978 1.1 christos static void
979 1.25 christos server_init_dispatch(struct ssh *ssh)
980 1.1 christos {
981 1.16 christos debug("server_init_dispatch");
982 1.25 christos ssh_dispatch_init(ssh, &dispatch_protocol_error);
983 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
984 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
985 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
986 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
987 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
988 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
989 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
990 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
991 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
992 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
993 1.1 christos /* client_alive */
994 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
995 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
996 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
997 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
998 1.1 christos /* rekeying */
999 1.25 christos ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
1000 1.1 christos }
1001