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