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