serverloop.c revision 1.17 1 1.17 christos /* $NetBSD: serverloop.c,v 1.17 2017/04/18 18:41:46 christos Exp $ */
2 1.17 christos /* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker 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.12 christos __RCSID("$NetBSD: serverloop.c,v 1.17 2017/04/18 18:41:46 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.1 christos #include <signal.h>
55 1.1 christos #include <string.h>
56 1.1 christos #include <termios.h>
57 1.1 christos #include <unistd.h>
58 1.1 christos #include <stdarg.h>
59 1.1 christos
60 1.1 christos #include "xmalloc.h"
61 1.1 christos #include "packet.h"
62 1.1 christos #include "buffer.h"
63 1.1 christos #include "log.h"
64 1.9 christos #include "misc.h"
65 1.1 christos #include "servconf.h"
66 1.1 christos #include "canohost.h"
67 1.1 christos #include "sshpty.h"
68 1.1 christos #include "channels.h"
69 1.1 christos #include "compat.h"
70 1.1 christos #include "ssh2.h"
71 1.1 christos #include "key.h"
72 1.1 christos #include "cipher.h"
73 1.1 christos #include "kex.h"
74 1.1 christos #include "hostfile.h"
75 1.1 christos #include "auth.h"
76 1.1 christos #include "session.h"
77 1.1 christos #include "dispatch.h"
78 1.1 christos #include "auth-options.h"
79 1.1 christos #include "serverloop.h"
80 1.10 christos #include "ssherr.h"
81 1.1 christos
82 1.16 christos static u_long stdin_bytes = 0; /* Number of bytes written to stdin. */
83 1.16 christos static u_long fdout_bytes = 0; /* Number of stdout bytes read from program. */
84 1.16 christos
85 1.1 christos extern ServerOptions options;
86 1.1 christos
87 1.1 christos /* XXX */
88 1.1 christos extern Authctxt *the_authctxt;
89 1.1 christos extern int use_privsep;
90 1.1 christos
91 1.1 christos static int no_more_sessions = 0; /* Disallow further sessions. */
92 1.1 christos
93 1.1 christos /*
94 1.1 christos * This SIGCHLD kludge is used to detect when the child exits. The server
95 1.1 christos * will exit after that, as soon as forwarded connections have terminated.
96 1.1 christos */
97 1.1 christos
98 1.1 christos static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
99 1.1 christos
100 1.1 christos /* Cleanup on signals (!use_privsep case only) */
101 1.1 christos static volatile sig_atomic_t received_sigterm = 0;
102 1.1 christos
103 1.1 christos /* prototypes */
104 1.1 christos static void server_init_dispatch(void);
105 1.1 christos
106 1.1 christos /*
107 1.2 christos * Returns current time in seconds from Jan 1, 1970 with the maximum
108 1.2 christos * available resolution.
109 1.2 christos */
110 1.2 christos
111 1.2 christos static double
112 1.2 christos get_current_time(void)
113 1.2 christos {
114 1.2 christos struct timeval tv;
115 1.2 christos gettimeofday(&tv, NULL);
116 1.2 christos return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
117 1.2 christos }
118 1.2 christos
119 1.2 christos /*
120 1.1 christos * we write to this pipe if a SIGCHLD is caught in order to avoid
121 1.1 christos * the race between select() and child_terminated
122 1.1 christos */
123 1.1 christos static int notify_pipe[2];
124 1.1 christos static void
125 1.1 christos notify_setup(void)
126 1.1 christos {
127 1.1 christos if (pipe(notify_pipe) < 0) {
128 1.1 christos error("pipe(notify_pipe) failed %s", strerror(errno));
129 1.4 christos } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
130 1.4 christos (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
131 1.1 christos error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
132 1.1 christos close(notify_pipe[0]);
133 1.1 christos close(notify_pipe[1]);
134 1.1 christos } else {
135 1.1 christos set_nonblock(notify_pipe[0]);
136 1.1 christos set_nonblock(notify_pipe[1]);
137 1.1 christos return;
138 1.1 christos }
139 1.1 christos notify_pipe[0] = -1; /* read end */
140 1.1 christos notify_pipe[1] = -1; /* write end */
141 1.1 christos }
142 1.1 christos static void
143 1.1 christos notify_parent(void)
144 1.1 christos {
145 1.1 christos if (notify_pipe[1] != -1)
146 1.7 christos (void)write(notify_pipe[1], "", 1);
147 1.1 christos }
148 1.1 christos static void
149 1.1 christos notify_prepare(fd_set *readset)
150 1.1 christos {
151 1.1 christos if (notify_pipe[0] != -1)
152 1.1 christos FD_SET(notify_pipe[0], readset);
153 1.1 christos }
154 1.1 christos static void
155 1.1 christos notify_done(fd_set *readset)
156 1.1 christos {
157 1.1 christos char c;
158 1.1 christos
159 1.1 christos if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
160 1.1 christos while (read(notify_pipe[0], &c, 1) != -1)
161 1.1 christos debug2("notify_done: reading");
162 1.1 christos }
163 1.1 christos
164 1.1 christos /*ARGSUSED*/
165 1.1 christos static void
166 1.1 christos sigchld_handler(int sig)
167 1.1 christos {
168 1.1 christos int save_errno = errno;
169 1.1 christos child_terminated = 1;
170 1.1 christos signal(SIGCHLD, sigchld_handler);
171 1.1 christos notify_parent();
172 1.1 christos errno = save_errno;
173 1.1 christos }
174 1.1 christos
175 1.1 christos /*ARGSUSED*/
176 1.1 christos static void
177 1.1 christos sigterm_handler(int sig)
178 1.1 christos {
179 1.1 christos received_sigterm = sig;
180 1.1 christos }
181 1.1 christos
182 1.1 christos static void
183 1.1 christos client_alive_check(void)
184 1.1 christos {
185 1.1 christos int channel_id;
186 1.1 christos
187 1.1 christos /* timeout, check to see how many we have had */
188 1.3 christos if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
189 1.1 christos logit("Timeout, client not responding.");
190 1.1 christos cleanup_exit(255);
191 1.1 christos }
192 1.1 christos
193 1.1 christos /*
194 1.1 christos * send a bogus global/channel request with "wantreply",
195 1.1 christos * we should get back a failure
196 1.1 christos */
197 1.1 christos if ((channel_id = channel_find_open()) == -1) {
198 1.1 christos packet_start(SSH2_MSG_GLOBAL_REQUEST);
199 1.1 christos packet_put_cstring("keepalive (at) openssh.com");
200 1.1 christos packet_put_char(1); /* boolean: want reply */
201 1.1 christos } else {
202 1.1 christos channel_request_start(channel_id, "keepalive (at) openssh.com", 1);
203 1.1 christos }
204 1.1 christos packet_send();
205 1.1 christos }
206 1.1 christos
207 1.1 christos /*
208 1.1 christos * Sleep in select() until we can do something. This will initialize the
209 1.1 christos * select masks. Upon return, the masks will indicate which descriptors
210 1.1 christos * have data or can accept data. Optionally, a maximum time can be specified
211 1.1 christos * for the duration of the wait (0 = infinite).
212 1.1 christos */
213 1.1 christos static void
214 1.16 christos wait_until_can_do_something(int connection_in, int connection_out,
215 1.16 christos fd_set **readsetp, fd_set **writesetp, int *maxfdp,
216 1.15 christos u_int *nallocp, u_int64_t max_time_ms)
217 1.1 christos {
218 1.1 christos struct timeval tv, *tvp;
219 1.1 christos int ret;
220 1.5 christos time_t minwait_secs = 0;
221 1.1 christos int client_alive_scheduled = 0;
222 1.1 christos
223 1.5 christos /* Allocate and update select() masks for channel descriptors. */
224 1.5 christos channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
225 1.5 christos &minwait_secs, 0);
226 1.5 christos
227 1.15 christos /* XXX need proper deadline system for rekey/client alive */
228 1.5 christos if (minwait_secs != 0)
229 1.16 christos max_time_ms = MINIMUM(max_time_ms, (u_int)minwait_secs * 1000);
230 1.5 christos
231 1.1 christos /*
232 1.1 christos * if using client_alive, set the max timeout accordingly,
233 1.1 christos * and indicate that this particular timeout was for client
234 1.1 christos * alive by setting the client_alive_scheduled flag.
235 1.1 christos *
236 1.1 christos * this could be randomized somewhat to make traffic
237 1.1 christos * analysis more difficult, but we're not doing it yet.
238 1.1 christos */
239 1.16 christos if (options.client_alive_interval) {
240 1.15 christos uint64_t keepalive_ms =
241 1.15 christos (uint64_t)options.client_alive_interval * 1000;
242 1.15 christos
243 1.1 christos client_alive_scheduled = 1;
244 1.15 christos if (max_time_ms == 0 || max_time_ms > keepalive_ms)
245 1.15 christos max_time_ms = keepalive_ms;
246 1.1 christos }
247 1.1 christos
248 1.1 christos #if 0
249 1.16 christos /* wrong: bad condition XXX */
250 1.16 christos if (channel_not_very_much_buffered_data())
251 1.1 christos #endif
252 1.16 christos FD_SET(connection_in, *readsetp);
253 1.1 christos notify_prepare(*readsetp);
254 1.1 christos
255 1.1 christos /*
256 1.1 christos * If we have buffered packet data going to the client, mark that
257 1.1 christos * descriptor.
258 1.1 christos */
259 1.1 christos if (packet_have_data_to_write())
260 1.1 christos FD_SET(connection_out, *writesetp);
261 1.1 christos
262 1.1 christos /*
263 1.1 christos * If child has terminated and there is enough buffer space to read
264 1.1 christos * from it, then read as much as is available and exit.
265 1.1 christos */
266 1.1 christos if (child_terminated && packet_not_very_much_data_to_write())
267 1.15 christos if (max_time_ms == 0 || client_alive_scheduled)
268 1.15 christos max_time_ms = 100;
269 1.1 christos
270 1.15 christos if (max_time_ms == 0)
271 1.1 christos tvp = NULL;
272 1.1 christos else {
273 1.15 christos tv.tv_sec = max_time_ms / 1000;
274 1.15 christos tv.tv_usec = 1000 * (max_time_ms % 1000);
275 1.1 christos tvp = &tv;
276 1.1 christos }
277 1.1 christos
278 1.1 christos /* Wait for something to happen, or the timeout to expire. */
279 1.1 christos ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
280 1.1 christos
281 1.1 christos if (ret == -1) {
282 1.1 christos memset(*readsetp, 0, *nallocp);
283 1.1 christos memset(*writesetp, 0, *nallocp);
284 1.1 christos if (errno != EINTR)
285 1.1 christos error("select: %.100s", strerror(errno));
286 1.1 christos } else if (ret == 0 && client_alive_scheduled)
287 1.1 christos client_alive_check();
288 1.1 christos
289 1.1 christos notify_done(*readsetp);
290 1.1 christos }
291 1.1 christos
292 1.1 christos /*
293 1.1 christos * Processes input from the client and the program. Input data is stored
294 1.1 christos * in buffers and processed later.
295 1.1 christos */
296 1.16 christos static int
297 1.16 christos process_input(fd_set *readset, int connection_in)
298 1.1 christos {
299 1.15 christos struct ssh *ssh = active_state; /* XXX */
300 1.1 christos int len;
301 1.1 christos char buf[16384];
302 1.1 christos
303 1.1 christos /* Read and buffer any input data from the client. */
304 1.1 christos if (FD_ISSET(connection_in, readset)) {
305 1.13 christos len = read(connection_in, buf, sizeof(buf));
306 1.1 christos if (len == 0) {
307 1.15 christos verbose("Connection closed by %.100s port %d",
308 1.15 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
309 1.16 christos return -1;
310 1.1 christos } else if (len < 0) {
311 1.1 christos if (errno != EINTR && errno != EAGAIN) {
312 1.1 christos verbose("Read error from remote host "
313 1.15 christos "%.100s port %d: %.100s",
314 1.15 christos ssh_remote_ipaddr(ssh),
315 1.15 christos ssh_remote_port(ssh), strerror(errno));
316 1.1 christos cleanup_exit(255);
317 1.1 christos }
318 1.1 christos } else {
319 1.1 christos /* Buffer any received data. */
320 1.1 christos packet_process_incoming(buf, len);
321 1.2 christos fdout_bytes += len;
322 1.1 christos }
323 1.1 christos }
324 1.16 christos return 0;
325 1.1 christos }
326 1.1 christos
327 1.1 christos /*
328 1.1 christos * Sends data from internal buffers to client program stdin.
329 1.1 christos */
330 1.1 christos static void
331 1.16 christos process_output(fd_set *writeset, int connection_out)
332 1.1 christos {
333 1.1 christos /* Send any buffered packet data to the client. */
334 1.1 christos if (FD_ISSET(connection_out, writeset))
335 1.2 christos stdin_bytes += packet_write_poll();
336 1.1 christos }
337 1.1 christos
338 1.1 christos static void
339 1.1 christos process_buffered_input_packets(void)
340 1.1 christos {
341 1.10 christos dispatch_run(DISPATCH_NONBLOCK, NULL, active_state);
342 1.1 christos }
343 1.1 christos
344 1.1 christos static void
345 1.1 christos collect_children(void)
346 1.1 christos {
347 1.1 christos pid_t pid;
348 1.1 christos sigset_t oset, nset;
349 1.1 christos int status;
350 1.1 christos
351 1.1 christos /* block SIGCHLD while we check for dead children */
352 1.1 christos sigemptyset(&nset);
353 1.1 christos sigaddset(&nset, SIGCHLD);
354 1.1 christos sigprocmask(SIG_BLOCK, &nset, &oset);
355 1.1 christos if (child_terminated) {
356 1.1 christos debug("Received SIGCHLD.");
357 1.1 christos while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
358 1.1 christos (pid < 0 && errno == EINTR))
359 1.1 christos if (pid > 0)
360 1.1 christos session_close_by_pid(pid, status);
361 1.1 christos child_terminated = 0;
362 1.1 christos }
363 1.1 christos sigprocmask(SIG_SETMASK, &oset, NULL);
364 1.1 christos }
365 1.1 christos
366 1.1 christos void
367 1.1 christos server_loop2(Authctxt *authctxt)
368 1.1 christos {
369 1.1 christos fd_set *readset = NULL, *writeset = NULL;
370 1.14 christos int max_fd;
371 1.16 christos u_int nalloc = 0, connection_in, connection_out;
372 1.7 christos u_int64_t rekey_timeout_ms = 0;
373 1.2 christos double start_time, total_time;
374 1.15 christos struct ssh *ssh = active_state; /* XXX */
375 1.1 christos
376 1.1 christos debug("Entering interactive session for SSH2.");
377 1.2 christos start_time = get_current_time();
378 1.1 christos
379 1.1 christos signal(SIGCHLD, sigchld_handler);
380 1.1 christos child_terminated = 0;
381 1.1 christos connection_in = packet_get_connection_in();
382 1.1 christos connection_out = packet_get_connection_out();
383 1.1 christos
384 1.1 christos if (!use_privsep) {
385 1.1 christos signal(SIGTERM, sigterm_handler);
386 1.1 christos signal(SIGINT, sigterm_handler);
387 1.1 christos signal(SIGQUIT, sigterm_handler);
388 1.1 christos }
389 1.1 christos
390 1.1 christos notify_setup();
391 1.1 christos
392 1.16 christos max_fd = MAXIMUM(connection_in, connection_out);
393 1.16 christos max_fd = MAXIMUM(max_fd, notify_pipe[0]);
394 1.1 christos
395 1.1 christos server_init_dispatch();
396 1.1 christos
397 1.1 christos for (;;) {
398 1.1 christos process_buffered_input_packets();
399 1.1 christos
400 1.14 christos if (!ssh_packet_is_rekeying(active_state) &&
401 1.14 christos packet_not_very_much_data_to_write())
402 1.1 christos channel_output_poll();
403 1.16 christos if (options.rekey_interval > 0 &&
404 1.14 christos !ssh_packet_is_rekeying(active_state))
405 1.7 christos rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
406 1.7 christos else
407 1.7 christos rekey_timeout_ms = 0;
408 1.7 christos
409 1.16 christos wait_until_can_do_something(connection_in, connection_out,
410 1.16 christos &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
411 1.1 christos
412 1.1 christos if (received_sigterm) {
413 1.6 christos logit("Exiting on signal %d", (int)received_sigterm);
414 1.1 christos /* Clean up sessions, utmp, etc. */
415 1.1 christos cleanup_exit(255);
416 1.1 christos }
417 1.1 christos
418 1.1 christos collect_children();
419 1.14 christos if (!ssh_packet_is_rekeying(active_state))
420 1.1 christos channel_after_select(readset, writeset);
421 1.16 christos if (process_input(readset, connection_in) < 0)
422 1.1 christos break;
423 1.16 christos process_output(writeset, connection_out);
424 1.1 christos }
425 1.1 christos collect_children();
426 1.1 christos
427 1.7 christos free(readset);
428 1.7 christos free(writeset);
429 1.1 christos
430 1.1 christos /* free all channels, no more reads and writes */
431 1.1 christos channel_free_all();
432 1.1 christos
433 1.1 christos /* free remaining sessions, e.g. remove wtmp entries */
434 1.1 christos session_destroy_all(NULL);
435 1.2 christos total_time = get_current_time() - start_time;
436 1.2 christos logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
437 1.15 christos ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
438 1.2 christos stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time,
439 1.2 christos fdout_bytes / total_time);
440 1.1 christos }
441 1.1 christos
442 1.10 christos static int
443 1.1 christos server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
444 1.1 christos {
445 1.1 christos debug("Got %d/%u for keepalive", type, seq);
446 1.1 christos /*
447 1.1 christos * reset timeout, since we got a sane answer from the client.
448 1.1 christos * even if this was generated by something other than
449 1.1 christos * the bogus CHANNEL_REQUEST we send for keepalives.
450 1.1 christos */
451 1.3 christos packet_set_alive_timeouts(0);
452 1.10 christos return 0;
453 1.1 christos }
454 1.1 christos
455 1.1 christos static Channel *
456 1.17 christos server_request_direct_tcpip(int *reason, const char **errmsg)
457 1.1 christos {
458 1.6 christos Channel *c = NULL;
459 1.1 christos char *target, *originator;
460 1.1 christos u_short target_port, originator_port;
461 1.1 christos
462 1.1 christos target = packet_get_string(NULL);
463 1.1 christos target_port = packet_get_int();
464 1.1 christos originator = packet_get_string(NULL);
465 1.1 christos originator_port = packet_get_int();
466 1.1 christos packet_check_eom();
467 1.1 christos
468 1.1 christos debug("server_request_direct_tcpip: originator %s port %d, target %s "
469 1.1 christos "port %d", originator, originator_port, target, target_port);
470 1.1 christos
471 1.6 christos /* XXX fine grained permissions */
472 1.6 christos if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
473 1.16 christos !no_port_forwarding_flag && !options.disable_forwarding) {
474 1.9 christos c = channel_connect_to_port(target, target_port,
475 1.17 christos "direct-tcpip", "direct-tcpip", reason, errmsg);
476 1.6 christos } else {
477 1.6 christos logit("refused local port forward: "
478 1.6 christos "originator %s port %d, target %s port %d",
479 1.6 christos originator, originator_port, target, target_port);
480 1.17 christos if (reason != NULL)
481 1.17 christos *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
482 1.6 christos }
483 1.1 christos
484 1.7 christos free(originator);
485 1.7 christos free(target);
486 1.1 christos
487 1.1 christos return c;
488 1.1 christos }
489 1.1 christos
490 1.1 christos static Channel *
491 1.9 christos server_request_direct_streamlocal(void)
492 1.9 christos {
493 1.9 christos Channel *c = NULL;
494 1.9 christos char *target, *originator;
495 1.9 christos u_short originator_port;
496 1.17 christos struct passwd *pw = the_authctxt->pw;
497 1.17 christos
498 1.17 christos if (pw == NULL || !the_authctxt->valid)
499 1.17 christos fatal("server_input_global_request: no/invalid user");
500 1.9 christos
501 1.9 christos target = packet_get_string(NULL);
502 1.9 christos originator = packet_get_string(NULL);
503 1.9 christos originator_port = packet_get_int();
504 1.9 christos packet_check_eom();
505 1.9 christos
506 1.9 christos debug("server_request_direct_streamlocal: 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.16 christos !no_port_forwarding_flag && !options.disable_forwarding &&
512 1.17 christos (pw->pw_uid == 0 || use_privsep)) {
513 1.9 christos c = channel_connect_to_path(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.9 christos free(originator);
522 1.9 christos free(target);
523 1.9 christos
524 1.9 christos return c;
525 1.9 christos }
526 1.9 christos
527 1.9 christos static Channel *
528 1.1 christos server_request_tun(void)
529 1.1 christos {
530 1.1 christos Channel *c = NULL;
531 1.1 christos int mode, tun;
532 1.1 christos int sock;
533 1.1 christos
534 1.1 christos mode = packet_get_int();
535 1.1 christos switch (mode) {
536 1.1 christos case SSH_TUNMODE_POINTOPOINT:
537 1.1 christos case SSH_TUNMODE_ETHERNET:
538 1.1 christos break;
539 1.1 christos default:
540 1.1 christos packet_send_debug("Unsupported tunnel device mode.");
541 1.1 christos return NULL;
542 1.1 christos }
543 1.1 christos if ((options.permit_tun & mode) == 0) {
544 1.1 christos packet_send_debug("Server has rejected tunnel device "
545 1.1 christos "forwarding");
546 1.1 christos return NULL;
547 1.1 christos }
548 1.1 christos
549 1.1 christos tun = packet_get_int();
550 1.1 christos if (forced_tun_device != -1) {
551 1.1 christos if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
552 1.1 christos goto done;
553 1.1 christos tun = forced_tun_device;
554 1.1 christos }
555 1.1 christos sock = tun_open(tun, mode);
556 1.1 christos if (sock < 0)
557 1.1 christos goto done;
558 1.2 christos if (options.hpn_disabled)
559 1.1 christos c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
560 1.1 christos CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
561 1.2 christos else
562 1.2 christos c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
563 1.2 christos options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
564 1.1 christos c->datagram = 1;
565 1.1 christos
566 1.1 christos done:
567 1.1 christos if (c == NULL)
568 1.1 christos packet_send_debug("Failed to open the tunnel device.");
569 1.1 christos return c;
570 1.1 christos }
571 1.1 christos
572 1.1 christos static Channel *
573 1.1 christos server_request_session(void)
574 1.1 christos {
575 1.1 christos Channel *c;
576 1.1 christos
577 1.1 christos debug("input_session_request");
578 1.1 christos packet_check_eom();
579 1.1 christos
580 1.1 christos if (no_more_sessions) {
581 1.1 christos packet_disconnect("Possible attack: attempt to open a session "
582 1.1 christos "after additional sessions disabled");
583 1.1 christos }
584 1.1 christos
585 1.1 christos /*
586 1.1 christos * A server session has no fd to read or write until a
587 1.1 christos * CHANNEL_REQUEST for a shell is made, so we set the type to
588 1.1 christos * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
589 1.1 christos * CHANNEL_REQUEST messages is registered.
590 1.1 christos */
591 1.1 christos c = channel_new("session", SSH_CHANNEL_LARVAL,
592 1.1 christos -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
593 1.1 christos 0, "server-session", 1);
594 1.2 christos if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled))
595 1.2 christos c->dynamic_window = 1;
596 1.1 christos if (session_open(the_authctxt, c->self) != 1) {
597 1.1 christos debug("session open failed, free channel %d", c->self);
598 1.1 christos channel_free(c);
599 1.1 christos return NULL;
600 1.1 christos }
601 1.1 christos channel_register_cleanup(c->self, session_close_by_channel, 0);
602 1.1 christos return c;
603 1.1 christos }
604 1.1 christos
605 1.10 christos static int
606 1.1 christos server_input_channel_open(int type, u_int32_t seq, void *ctxt)
607 1.1 christos {
608 1.1 christos Channel *c = NULL;
609 1.1 christos char *ctype;
610 1.17 christos const char *errmsg = NULL;
611 1.17 christos int rchan, reason = SSH2_OPEN_CONNECT_FAILED;
612 1.1 christos u_int rmaxpack, rwindow, len;
613 1.1 christos
614 1.1 christos ctype = packet_get_string(&len);
615 1.1 christos rchan = packet_get_int();
616 1.1 christos rwindow = packet_get_int();
617 1.1 christos rmaxpack = packet_get_int();
618 1.1 christos
619 1.1 christos debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
620 1.1 christos ctype, rchan, rwindow, rmaxpack);
621 1.1 christos
622 1.1 christos if (strcmp(ctype, "session") == 0) {
623 1.1 christos c = server_request_session();
624 1.1 christos } else if (strcmp(ctype, "direct-tcpip") == 0) {
625 1.17 christos c = server_request_direct_tcpip(&reason, &errmsg);
626 1.9 christos } else if (strcmp(ctype, "direct-streamlocal (at) openssh.com") == 0) {
627 1.9 christos c = server_request_direct_streamlocal();
628 1.1 christos } else if (strcmp(ctype, "tun (at) openssh.com") == 0) {
629 1.1 christos c = server_request_tun();
630 1.1 christos }
631 1.1 christos if (c != NULL) {
632 1.1 christos debug("server_input_channel_open: confirm %s", ctype);
633 1.1 christos c->remote_id = rchan;
634 1.1 christos c->remote_window = rwindow;
635 1.1 christos c->remote_maxpacket = rmaxpack;
636 1.1 christos if (c->type != SSH_CHANNEL_CONNECTING) {
637 1.1 christos packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
638 1.1 christos packet_put_int(c->remote_id);
639 1.1 christos packet_put_int(c->self);
640 1.1 christos packet_put_int(c->local_window);
641 1.1 christos packet_put_int(c->local_maxpacket);
642 1.1 christos packet_send();
643 1.1 christos }
644 1.1 christos } else {
645 1.1 christos debug("server_input_channel_open: failure %s", ctype);
646 1.1 christos packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
647 1.1 christos packet_put_int(rchan);
648 1.17 christos packet_put_int(reason);
649 1.1 christos if (!(datafellows & SSH_BUG_OPENFAILURE)) {
650 1.17 christos packet_put_cstring(errmsg ? errmsg : "open failed");
651 1.1 christos packet_put_cstring("");
652 1.1 christos }
653 1.1 christos packet_send();
654 1.1 christos }
655 1.7 christos free(ctype);
656 1.10 christos return 0;
657 1.10 christos }
658 1.10 christos
659 1.10 christos static int
660 1.10 christos server_input_hostkeys_prove(struct sshbuf **respp)
661 1.10 christos {
662 1.10 christos struct ssh *ssh = active_state; /* XXX */
663 1.10 christos struct sshbuf *resp = NULL;
664 1.10 christos struct sshbuf *sigbuf = NULL;
665 1.10 christos struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
666 1.10 christos int r, ndx, success = 0;
667 1.10 christos const u_char *blob;
668 1.10 christos u_char *sig = 0;
669 1.10 christos size_t blen, slen;
670 1.10 christos
671 1.10 christos if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
672 1.10 christos fatal("%s: sshbuf_new", __func__);
673 1.10 christos
674 1.10 christos while (ssh_packet_remaining(ssh) > 0) {
675 1.10 christos sshkey_free(key);
676 1.10 christos key = NULL;
677 1.10 christos if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
678 1.10 christos (r = sshkey_from_blob(blob, blen, &key)) != 0) {
679 1.10 christos error("%s: couldn't parse key: %s",
680 1.10 christos __func__, ssh_err(r));
681 1.10 christos goto out;
682 1.10 christos }
683 1.10 christos /*
684 1.10 christos * Better check that this is actually one of our hostkeys
685 1.10 christos * before attempting to sign anything with it.
686 1.10 christos */
687 1.10 christos if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
688 1.10 christos error("%s: unknown host %s key",
689 1.10 christos __func__, sshkey_type(key));
690 1.10 christos goto out;
691 1.10 christos }
692 1.10 christos /*
693 1.10 christos * XXX refactor: make kex->sign just use an index rather
694 1.10 christos * than passing in public and private keys
695 1.10 christos */
696 1.10 christos if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
697 1.10 christos (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
698 1.10 christos error("%s: can't retrieve hostkey %d", __func__, ndx);
699 1.10 christos goto out;
700 1.10 christos }
701 1.10 christos sshbuf_reset(sigbuf);
702 1.10 christos free(sig);
703 1.10 christos sig = NULL;
704 1.10 christos if ((r = sshbuf_put_cstring(sigbuf,
705 1.10 christos "hostkeys-prove-00 (at) openssh.com")) != 0 ||
706 1.10 christos (r = sshbuf_put_string(sigbuf,
707 1.10 christos ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
708 1.10 christos (r = sshkey_puts(key, sigbuf)) != 0 ||
709 1.10 christos (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
710 1.14 christos sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), NULL, 0)) != 0 ||
711 1.10 christos (r = sshbuf_put_string(resp, sig, slen)) != 0) {
712 1.10 christos error("%s: couldn't prepare signature: %s",
713 1.10 christos __func__, ssh_err(r));
714 1.10 christos goto out;
715 1.10 christos }
716 1.10 christos }
717 1.10 christos /* Success */
718 1.10 christos *respp = resp;
719 1.10 christos resp = NULL; /* don't free it */
720 1.10 christos success = 1;
721 1.10 christos out:
722 1.10 christos free(sig);
723 1.10 christos sshbuf_free(resp);
724 1.10 christos sshbuf_free(sigbuf);
725 1.10 christos sshkey_free(key);
726 1.10 christos return success;
727 1.1 christos }
728 1.1 christos
729 1.10 christos static int
730 1.1 christos server_input_global_request(int type, u_int32_t seq, void *ctxt)
731 1.1 christos {
732 1.1 christos char *rtype;
733 1.1 christos int want_reply;
734 1.10 christos int r, success = 0, allocated_listen_port = 0;
735 1.10 christos struct sshbuf *resp = NULL;
736 1.17 christos struct passwd *pw = the_authctxt->pw;
737 1.17 christos
738 1.17 christos if (pw == NULL || !the_authctxt->valid)
739 1.17 christos fatal("server_input_global_request: no/invalid user");
740 1.1 christos
741 1.1 christos rtype = packet_get_string(NULL);
742 1.1 christos want_reply = packet_get_char();
743 1.1 christos debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
744 1.1 christos
745 1.1 christos /* -R style forwarding */
746 1.1 christos if (strcmp(rtype, "tcpip-forward") == 0) {
747 1.9 christos struct Forward fwd;
748 1.1 christos
749 1.9 christos memset(&fwd, 0, sizeof(fwd));
750 1.9 christos fwd.listen_host = packet_get_string(NULL);
751 1.9 christos fwd.listen_port = (u_short)packet_get_int();
752 1.1 christos debug("server_input_global_request: tcpip-forward listen %s port %d",
753 1.9 christos fwd.listen_host, fwd.listen_port);
754 1.1 christos
755 1.1 christos /* check permissions */
756 1.6 christos if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
757 1.16 christos no_port_forwarding_flag || options.disable_forwarding ||
758 1.9 christos (!want_reply && fwd.listen_port == 0) ||
759 1.16 christos (fwd.listen_port != 0 &&
760 1.16 christos !bind_permitted(fwd.listen_port, pw->pw_uid))) {
761 1.1 christos success = 0;
762 1.1 christos packet_send_debug("Server has disabled port forwarding.");
763 1.1 christos } else {
764 1.1 christos /* Start listening on the port */
765 1.9 christos success = channel_setup_remote_fwd_listener(&fwd,
766 1.9 christos &allocated_listen_port, &options.fwd_opts);
767 1.1 christos }
768 1.9 christos free(fwd.listen_host);
769 1.10 christos if ((resp = sshbuf_new()) == NULL)
770 1.10 christos fatal("%s: sshbuf_new", __func__);
771 1.14 christos if (allocated_listen_port != 0 &&
772 1.14 christos (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
773 1.10 christos fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
774 1.1 christos } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
775 1.9 christos struct Forward fwd;
776 1.1 christos
777 1.9 christos memset(&fwd, 0, sizeof(fwd));
778 1.9 christos fwd.listen_host = packet_get_string(NULL);
779 1.9 christos fwd.listen_port = (u_short)packet_get_int();
780 1.1 christos debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
781 1.9 christos fwd.listen_host, fwd.listen_port);
782 1.9 christos
783 1.9 christos success = channel_cancel_rport_listener(&fwd);
784 1.9 christos free(fwd.listen_host);
785 1.9 christos } else if (strcmp(rtype, "streamlocal-forward (at) openssh.com") == 0) {
786 1.9 christos struct Forward fwd;
787 1.9 christos
788 1.9 christos memset(&fwd, 0, sizeof(fwd));
789 1.9 christos fwd.listen_path = packet_get_string(NULL);
790 1.9 christos debug("server_input_global_request: streamlocal-forward listen path %s",
791 1.9 christos fwd.listen_path);
792 1.9 christos
793 1.9 christos /* check permissions */
794 1.9 christos if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
795 1.16 christos || no_port_forwarding_flag || options.disable_forwarding ||
796 1.17 christos (pw->pw_uid != 0 && !use_privsep)) {
797 1.9 christos success = 0;
798 1.17 christos packet_send_debug("Server has disabled "
799 1.17 christos "streamlocal forwarding.");
800 1.9 christos } else {
801 1.9 christos /* Start listening on the socket */
802 1.9 christos success = channel_setup_remote_fwd_listener(
803 1.9 christos &fwd, NULL, &options.fwd_opts);
804 1.9 christos }
805 1.9 christos free(fwd.listen_path);
806 1.9 christos } else if (strcmp(rtype, "cancel-streamlocal-forward (at) openssh.com") == 0) {
807 1.9 christos struct Forward fwd;
808 1.9 christos
809 1.9 christos memset(&fwd, 0, sizeof(fwd));
810 1.9 christos fwd.listen_path = packet_get_string(NULL);
811 1.9 christos debug("%s: cancel-streamlocal-forward path %s", __func__,
812 1.9 christos fwd.listen_path);
813 1.1 christos
814 1.9 christos success = channel_cancel_rport_listener(&fwd);
815 1.9 christos free(fwd.listen_path);
816 1.1 christos } else if (strcmp(rtype, "no-more-sessions (at) openssh.com") == 0) {
817 1.1 christos no_more_sessions = 1;
818 1.1 christos success = 1;
819 1.10 christos } else if (strcmp(rtype, "hostkeys-prove-00 (at) openssh.com") == 0) {
820 1.10 christos success = server_input_hostkeys_prove(&resp);
821 1.1 christos }
822 1.1 christos if (want_reply) {
823 1.1 christos packet_start(success ?
824 1.1 christos SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
825 1.10 christos if (success && resp != NULL)
826 1.10 christos ssh_packet_put_raw(active_state, sshbuf_ptr(resp),
827 1.10 christos sshbuf_len(resp));
828 1.1 christos packet_send();
829 1.1 christos packet_write_wait();
830 1.1 christos }
831 1.7 christos free(rtype);
832 1.10 christos sshbuf_free(resp);
833 1.10 christos return 0;
834 1.1 christos }
835 1.1 christos
836 1.10 christos static int
837 1.1 christos server_input_channel_req(int type, u_int32_t seq, void *ctxt)
838 1.1 christos {
839 1.1 christos Channel *c;
840 1.1 christos int id, reply, success = 0;
841 1.1 christos char *rtype;
842 1.1 christos
843 1.1 christos id = packet_get_int();
844 1.1 christos rtype = packet_get_string(NULL);
845 1.1 christos reply = packet_get_char();
846 1.1 christos
847 1.1 christos debug("server_input_channel_req: channel %d request %s reply %d",
848 1.1 christos id, rtype, reply);
849 1.1 christos
850 1.1 christos if ((c = channel_lookup(id)) == NULL)
851 1.1 christos packet_disconnect("server_input_channel_req: "
852 1.1 christos "unknown channel %d", id);
853 1.1 christos if (!strcmp(rtype, "eow (at) openssh.com")) {
854 1.1 christos packet_check_eom();
855 1.1 christos chan_rcvd_eow(c);
856 1.1 christos } else if ((c->type == SSH_CHANNEL_LARVAL ||
857 1.1 christos c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
858 1.1 christos success = session_input_channel_req(c, rtype);
859 1.9 christos if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
860 1.1 christos packet_start(success ?
861 1.1 christos SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
862 1.1 christos packet_put_int(c->remote_id);
863 1.1 christos packet_send();
864 1.1 christos }
865 1.7 christos free(rtype);
866 1.10 christos return 0;
867 1.1 christos }
868 1.1 christos
869 1.1 christos static void
870 1.16 christos server_init_dispatch(void)
871 1.1 christos {
872 1.16 christos debug("server_init_dispatch");
873 1.1 christos dispatch_init(&dispatch_protocol_error);
874 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
875 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
876 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
877 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
878 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
879 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
880 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
881 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
882 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
883 1.1 christos dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
884 1.1 christos /* client_alive */
885 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
886 1.1 christos dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
887 1.1 christos dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
888 1.1 christos dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
889 1.1 christos /* rekeying */
890 1.1 christos dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
891 1.1 christos }
892