Branch data Line data Source code
1 : : /* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */
2 : : /*
3 : : * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 : : * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 : : * All rights reserved
6 : : * Server main loop for handling the interactive session.
7 : : *
8 : : * As far as I am concerned, the code I have written for this software
9 : : * can be used freely for any purpose. Any derived versions of this
10 : : * software must be clearly marked as such, and if the derived work is
11 : : * incompatible with the protocol description in the RFC file, it must be
12 : : * called by a name other than "ssh" or "Secure Shell".
13 : : *
14 : : * SSH2 support by Markus Friedl.
15 : : * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
16 : : *
17 : : * Redistribution and use in source and binary forms, with or without
18 : : * modification, are permitted provided that the following conditions
19 : : * are met:
20 : : * 1. Redistributions of source code must retain the above copyright
21 : : * notice, this list of conditions and the following disclaimer.
22 : : * 2. Redistributions in binary form must reproduce the above copyright
23 : : * notice, this list of conditions and the following disclaimer in the
24 : : * documentation and/or other materials provided with the distribution.
25 : : *
26 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 : : */
37 : :
38 : : #include "includes.h"
39 : :
40 : : #include <sys/types.h>
41 : : #include <sys/param.h>
42 : : #include <sys/wait.h>
43 : : #include <sys/socket.h>
44 : : #ifdef HAVE_SYS_TIME_H
45 : : # include <sys/time.h>
46 : : #endif
47 : :
48 : : #include <netinet/in.h>
49 : :
50 : : #include <errno.h>
51 : : #include <fcntl.h>
52 : : #include <pwd.h>
53 : : #include <signal.h>
54 : : #include <string.h>
55 : : #include <termios.h>
56 : : #include <unistd.h>
57 : : #include <stdarg.h>
58 : :
59 : : #include "openbsd-compat/sys-queue.h"
60 : : #include "xmalloc.h"
61 : : #include "packet.h"
62 : : #include "buffer.h"
63 : : #include "log.h"
64 : : #include "servconf.h"
65 : : #include "canohost.h"
66 : : #include "sshpty.h"
67 : : #include "channels.h"
68 : : #include "compat.h"
69 : : #include "ssh1.h"
70 : : #include "ssh2.h"
71 : : #include "key.h"
72 : : #include "cipher.h"
73 : : #include "kex.h"
74 : : #include "hostfile.h"
75 : : #include "auth.h"
76 : : #include "session.h"
77 : : #include "dispatch.h"
78 : : #include "auth-options.h"
79 : : #include "serverloop.h"
80 : : #include "misc.h"
81 : : #include "roaming.h"
82 : :
83 : : extern ServerOptions options;
84 : :
85 : : /* XXX */
86 : : extern Kex *xxx_kex;
87 : : extern Authctxt *the_authctxt;
88 : : extern int use_privsep;
89 : :
90 : : static Buffer stdin_buffer; /* Buffer for stdin data. */
91 : : static Buffer stdout_buffer; /* Buffer for stdout data. */
92 : : static Buffer stderr_buffer; /* Buffer for stderr data. */
93 : : static int fdin; /* Descriptor for stdin (for writing) */
94 : : static int fdout; /* Descriptor for stdout (for reading);
95 : : May be same number as fdin. */
96 : : static int fderr; /* Descriptor for stderr. May be -1. */
97 : : static long stdin_bytes = 0; /* Number of bytes written to stdin. */
98 : : static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
99 : : static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
100 : : static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
101 : : static int stdin_eof = 0; /* EOF message received from client. */
102 : : static int fdout_eof = 0; /* EOF encountered reading from fdout. */
103 : : static int fderr_eof = 0; /* EOF encountered readung from fderr. */
104 : : static int fdin_is_tty = 0; /* fdin points to a tty. */
105 : : static int connection_in; /* Connection to client (input). */
106 : : static int connection_out; /* Connection to client (output). */
107 : : static int connection_closed = 0; /* Connection to client closed. */
108 : : static u_int buffer_high; /* "Soft" max buffer size. */
109 : : static int no_more_sessions = 0; /* Disallow further sessions. */
110 : :
111 : : /*
112 : : * This SIGCHLD kludge is used to detect when the child exits. The server
113 : : * will exit after that, as soon as forwarded connections have terminated.
114 : : */
115 : :
116 : : static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
117 : :
118 : : /* Cleanup on signals (!use_privsep case only) */
119 : : static volatile sig_atomic_t received_sigterm = 0;
120 : :
121 : : /* prototypes */
122 : : static void server_init_dispatch(void);
123 : :
124 : : /*
125 : : * we write to this pipe if a SIGCHLD is caught in order to avoid
126 : : * the race between select() and child_terminated
127 : : */
128 : : static int notify_pipe[2];
129 : : static void
130 : 739 : notify_setup(void)
131 : : {
132 [ - + ]: 739 : if (pipe(notify_pipe) < 0) {
133 : 0 : error("pipe(notify_pipe) failed %s", strerror(errno));
134 [ + - - + ]: 1478 : } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
135 : 739 : (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
136 : 0 : error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
137 : 0 : close(notify_pipe[0]);
138 : 0 : close(notify_pipe[1]);
139 : : } else {
140 : 739 : set_nonblock(notify_pipe[0]);
141 : 739 : set_nonblock(notify_pipe[1]);
142 : 739 : return;
143 : : }
144 : 0 : notify_pipe[0] = -1; /* read end */
145 : 0 : notify_pipe[1] = -1; /* write end */
146 : : }
147 : : static void
148 : 37 : notify_parent(void)
149 : : {
150 [ + - ]: 37 : if (notify_pipe[1] != -1)
151 : 37 : (void)write(notify_pipe[1], "", 1);
152 : 37 : }
153 : : static void
154 : 4457 : notify_prepare(fd_set *readset)
155 : : {
156 [ + - ]: 4457 : if (notify_pipe[0] != -1)
157 [ - + ][ # # ]: 4457 : FD_SET(notify_pipe[0], readset);
158 : 4457 : }
159 : : static void
160 : 4457 : notify_done(fd_set *readset)
161 : : {
162 : : char c;
163 : :
164 [ + - ][ - + ]: 4457 : if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
[ # # ][ + + ]
165 [ + + ]: 52 : while (read(notify_pipe[0], &c, 1) != -1)
166 : 26 : debug2("notify_done: reading");
167 : 4457 : }
168 : :
169 : : /*ARGSUSED*/
170 : : static void
171 : 37 : sigchld_handler(int sig)
172 : : {
173 : 37 : int save_errno = errno;
174 : 37 : child_terminated = 1;
175 : : #ifndef _UNICOS
176 : 37 : mysignal(SIGCHLD, sigchld_handler);
177 : : #endif
178 : 37 : notify_parent();
179 : 37 : errno = save_errno;
180 : 37 : }
181 : :
182 : : /*ARGSUSED*/
183 : : static void
184 : 0 : sigterm_handler(int sig)
185 : : {
186 : 0 : received_sigterm = sig;
187 : 0 : }
188 : :
189 : : /*
190 : : * Make packets from buffered stderr data, and buffer it for sending
191 : : * to the client.
192 : : */
193 : : static void
194 : 1811 : make_packets_from_stderr_data(void)
195 : : {
196 : : u_int len;
197 : :
198 : : /* Send buffered stderr data to the client. */
199 [ + + + - ]: 2387 : while (buffer_len(&stderr_buffer) > 0 &&
200 : 288 : packet_not_very_much_data_to_write()) {
201 : 288 : len = buffer_len(&stderr_buffer);
202 [ - + ]: 288 : if (packet_is_interactive()) {
203 [ # # ]: 0 : if (len > 512)
204 : 0 : len = 512;
205 : : } else {
206 : : /* Keep the packets at reasonable size. */
207 [ - + ]: 288 : if (len > packet_get_maxsize())
208 : 0 : len = packet_get_maxsize();
209 : : }
210 : 288 : packet_start(SSH_SMSG_STDERR_DATA);
211 : 288 : packet_put_string(buffer_ptr(&stderr_buffer), len);
212 : 288 : packet_send();
213 : 288 : buffer_consume(&stderr_buffer, len);
214 : 288 : stderr_bytes += len;
215 : : }
216 : 1811 : }
217 : :
218 : : /*
219 : : * Make packets from buffered stdout data, and buffer it for sending to the
220 : : * client.
221 : : */
222 : : static void
223 : 1807 : make_packets_from_stdout_data(void)
224 : : {
225 : : u_int len;
226 : :
227 : : /* Send buffered stdout data to the client. */
228 [ + + + - ]: 2405 : while (buffer_len(&stdout_buffer) > 0 &&
229 : 299 : packet_not_very_much_data_to_write()) {
230 : 299 : len = buffer_len(&stdout_buffer);
231 [ - + ]: 299 : if (packet_is_interactive()) {
232 [ # # ]: 0 : if (len > 512)
233 : 0 : len = 512;
234 : : } else {
235 : : /* Keep the packets at reasonable size. */
236 [ - + ]: 299 : if (len > packet_get_maxsize())
237 : 0 : len = packet_get_maxsize();
238 : : }
239 : 299 : packet_start(SSH_SMSG_STDOUT_DATA);
240 : 299 : packet_put_string(buffer_ptr(&stdout_buffer), len);
241 : 299 : packet_send();
242 : 299 : buffer_consume(&stdout_buffer, len);
243 : 299 : stdout_bytes += len;
244 : : }
245 : 1807 : }
246 : :
247 : : static void
248 : 0 : client_alive_check(void)
249 : : {
250 : : int channel_id;
251 : :
252 : : /* timeout, check to see how many we have had */
253 [ # # ]: 0 : if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
254 : 0 : logit("Timeout, client not responding.");
255 : 0 : cleanup_exit(255);
256 : : }
257 : :
258 : : /*
259 : : * send a bogus global/channel request with "wantreply",
260 : : * we should get back a failure
261 : : */
262 [ # # ]: 0 : if ((channel_id = channel_find_open()) == -1) {
263 : 0 : packet_start(SSH2_MSG_GLOBAL_REQUEST);
264 : 0 : packet_put_cstring("keepalive@openssh.com");
265 : 0 : packet_put_char(1); /* boolean: want reply */
266 : : } else {
267 : 0 : channel_request_start(channel_id, "keepalive@openssh.com", 1);
268 : : }
269 : 0 : packet_send();
270 : 0 : }
271 : :
272 : : /*
273 : : * Sleep in select() until we can do something. This will initialize the
274 : : * select masks. Upon return, the masks will indicate which descriptors
275 : : * have data or can accept data. Optionally, a maximum time can be specified
276 : : * for the duration of the wait (0 = infinite).
277 : : */
278 : : static void
279 : 4457 : wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
280 : : u_int *nallocp, u_int64_t max_time_milliseconds)
281 : : {
282 : : struct timeval tv, *tvp;
283 : : int ret;
284 : 4457 : time_t minwait_secs = 0;
285 : 4457 : int client_alive_scheduled = 0;
286 : 4457 : int program_alive_scheduled = 0;
287 : :
288 : : /* Allocate and update select() masks for channel descriptors. */
289 : 4457 : channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
290 : : &minwait_secs, 0);
291 : :
292 [ - + ]: 4457 : if (minwait_secs != 0)
293 : 0 : max_time_milliseconds = MIN(max_time_milliseconds,
294 : : (u_int)minwait_secs * 1000);
295 : :
296 : : /*
297 : : * if using client_alive, set the max timeout accordingly,
298 : : * and indicate that this particular timeout was for client
299 : : * alive by setting the client_alive_scheduled flag.
300 : : *
301 : : * this could be randomized somewhat to make traffic
302 : : * analysis more difficult, but we're not doing it yet.
303 : : */
304 [ + + ][ + + ]: 4457 : if (compat20 &&
305 [ - + ]: 2663 : max_time_milliseconds == 0 && options.client_alive_interval) {
306 : 0 : client_alive_scheduled = 1;
307 : 0 : max_time_milliseconds =
308 : 0 : (u_int64_t)options.client_alive_interval * 1000;
309 : : }
310 : :
311 [ + + ]: 4457 : if (compat20) {
312 : : #if 0
313 : : /* wrong: bad condition XXX */
314 : : if (channel_not_very_much_buffered_data())
315 : : #endif
316 [ - + ][ # # ]: 2669 : FD_SET(connection_in, *readsetp);
317 : : } else {
318 : : /*
319 : : * Read packets from the client unless we have too much
320 : : * buffered stdin or channel data.
321 : : */
322 [ + - + - ]: 3576 : if (buffer_len(&stdin_buffer) < buffer_high &&
323 : 1788 : channel_not_very_much_buffered_data())
324 [ - + ][ # # ]: 1788 : FD_SET(connection_in, *readsetp);
325 : : /*
326 : : * If there is not too much data already buffered going to
327 : : * the client, try to get some more data from the program.
328 : : */
329 [ + - ]: 1788 : if (packet_not_very_much_data_to_write()) {
330 : 1788 : program_alive_scheduled = child_terminated;
331 [ + + ]: 1788 : if (!fdout_eof)
332 [ - + ][ # # ]: 1489 : FD_SET(fdout, *readsetp);
333 [ + + ]: 1788 : if (!fderr_eof)
334 [ - + ][ # # ]: 1762 : FD_SET(fderr, *readsetp);
335 : : }
336 : : /*
337 : : * If we have buffered data, try to write some of that data
338 : : * to the program.
339 : : */
340 [ + + ][ - + ]: 1788 : if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
341 [ # # ][ # # ]: 0 : FD_SET(fdin, *writesetp);
342 : : }
343 : 4457 : notify_prepare(*readsetp);
344 : :
345 : : /*
346 : : * If we have buffered packet data going to the client, mark that
347 : : * descriptor.
348 : : */
349 [ + + ]: 4457 : if (packet_have_data_to_write())
350 [ - + ][ # # ]: 2012 : FD_SET(connection_out, *writesetp);
351 : :
352 : : /*
353 : : * If child has terminated and there is enough buffer space to read
354 : : * from it, then read as much as is available and exit.
355 : : */
356 [ + + ][ + - ]: 4457 : if (child_terminated && packet_not_very_much_data_to_write())
357 [ + + ]: 54 : if (max_time_milliseconds == 0 || client_alive_scheduled)
358 : 52 : max_time_milliseconds = 100;
359 : :
360 [ + + ]: 4457 : if (max_time_milliseconds == 0)
361 : : tvp = NULL;
362 : : else {
363 : 62 : tv.tv_sec = max_time_milliseconds / 1000;
364 : 62 : tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
365 : 62 : tvp = &tv;
366 : : }
367 : :
368 : : /* Wait for something to happen, or the timeout to expire. */
369 : 4457 : ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
370 : :
371 [ + + ]: 4457 : if (ret == -1) {
372 : 4 : memset(*readsetp, 0, *nallocp);
373 : 4 : memset(*writesetp, 0, *nallocp);
374 [ - + ]: 4 : if (errno != EINTR)
375 : 0 : error("select: %.100s", strerror(errno));
376 : : } else {
377 [ - + ]: 4453 : if (ret == 0 && client_alive_scheduled)
378 : 0 : client_alive_check();
379 [ + + ][ + + ]: 4453 : if (!compat20 && program_alive_scheduled && fdin_is_tty) {
[ - + ]
380 [ # # ]: 0 : if (!fdout_eof)
381 [ # # ][ # # ]: 0 : FD_SET(fdout, *readsetp);
382 [ # # ]: 0 : if (!fderr_eof)
383 [ # # ][ # # ]: 0 : FD_SET(fderr, *readsetp);
384 : : }
385 : : }
386 : :
387 : 4457 : notify_done(*readsetp);
388 : 4457 : }
389 : :
390 : : /*
391 : : * Processes input from the client and the program. Input data is stored
392 : : * in buffers and processed later.
393 : : */
394 : : static void
395 : 4457 : process_input(fd_set *readset)
396 : : {
397 : : int len;
398 : : char buf[16384];
399 : :
400 : : /* Read and buffer any input data from the client. */
401 [ - + ][ # # ]: 4457 : if (FD_ISSET(connection_in, readset)) {
[ + + ]
402 : 1889 : int cont = 0;
403 : 1889 : len = roaming_read(connection_in, buf, sizeof(buf), &cont);
404 [ + + ]: 1889 : if (len == 0) {
405 [ + - ]: 3 : if (cont)
406 : 3 : return;
407 : 3 : verbose("Connection closed by %.100s",
408 : : get_remote_ipaddr());
409 : 3 : connection_closed = 1;
410 [ - + ]: 3 : if (compat20)
411 : : return;
412 : 0 : cleanup_exit(255);
413 [ - + ]: 1886 : } else if (len < 0) {
414 [ # # ][ # # ]: 0 : if (errno != EINTR && errno != EAGAIN &&
415 : : errno != EWOULDBLOCK) {
416 : 0 : verbose("Read error from remote host "
417 : : "%.100s: %.100s",
418 : : get_remote_ipaddr(), strerror(errno));
419 : 0 : cleanup_exit(255);
420 : : }
421 : : } else {
422 : : /* Buffer any received data. */
423 : 1886 : packet_process_incoming(buf, len);
424 : : }
425 : : }
426 [ + + ]: 4454 : if (compat20)
427 : : return;
428 : :
429 : : /* Read and buffer any available stdout data from the program. */
430 [ + + ][ - + ]: 1788 : if (!fdout_eof && FD_ISSET(fdout, readset)) {
[ # # ][ + + ]
431 : 322 : errno = 0;
432 : 644 : len = read(fdout, buf, sizeof(buf));
433 [ - + ][ # # ]: 322 : if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
[ # # ]
434 [ # # ]: 0 : errno == EWOULDBLOCK) && !child_terminated))) {
435 : : /* do nothing */
436 : : #ifndef PTY_ZEROREAD
437 [ + + ]: 322 : } else if (len <= 0) {
438 : : #else
439 : : } else if ((!isatty(fdout) && len <= 0) ||
440 : : (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) {
441 : : #endif
442 : 23 : fdout_eof = 1;
443 : : } else {
444 : 299 : buffer_append(&stdout_buffer, buf, len);
445 : 299 : fdout_bytes += len;
446 : : }
447 : : }
448 : : /* Read and buffer any available stderr data from the program. */
449 [ + + ][ - + ]: 1788 : if (!fderr_eof && FD_ISSET(fderr, readset)) {
[ # # ][ + + ]
450 : 311 : errno = 0;
451 : 622 : len = read(fderr, buf, sizeof(buf));
452 [ - + ][ # # ]: 311 : if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
[ # # ]
453 [ # # ]: 0 : errno == EWOULDBLOCK) && !child_terminated))) {
454 : : /* do nothing */
455 : : #ifndef PTY_ZEROREAD
456 [ + + ]: 311 : } else if (len <= 0) {
457 : : #else
458 : : } else if ((!isatty(fderr) && len <= 0) ||
459 : : (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) {
460 : : #endif
461 : 23 : fderr_eof = 1;
462 : : } else {
463 : 4457 : buffer_append(&stderr_buffer, buf, len);
464 : : }
465 : : }
466 : : }
467 : :
468 : : /*
469 : : * Sends data from internal buffers to client program stdin.
470 : : */
471 : : static void
472 : 4454 : process_output(fd_set *writeset)
473 : : {
474 : : struct termios tio;
475 : : u_char *data;
476 : : u_int dlen;
477 : : int len;
478 : :
479 : : /* Write buffered data to program stdin. */
480 [ + + ][ + + ]: 4454 : if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
[ - + ][ # # ]
[ - + ]
481 : 0 : data = buffer_ptr(&stdin_buffer);
482 : 0 : dlen = buffer_len(&stdin_buffer);
483 : 0 : len = write(fdin, data, dlen);
484 [ # # # # ]: 0 : if (len < 0 &&
485 [ # # ]: 0 : (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
486 : : /* do nothing */
487 [ # # ]: 0 : } else if (len <= 0) {
488 [ # # ]: 0 : if (fdin != fdout)
489 : 0 : close(fdin);
490 : : else
491 : 0 : shutdown(fdin, SHUT_WR); /* We will no longer send. */
492 : 0 : fdin = -1;
493 : : } else {
494 : : /* Successful write. */
495 [ # # ][ # # ]: 0 : if (fdin_is_tty && dlen >= 1 && data[0] != '\r' &&
[ # # # # ]
496 : 0 : tcgetattr(fdin, &tio) == 0 &&
497 [ # # ]: 0 : !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
498 : : /*
499 : : * Simulate echo to reduce the impact of
500 : : * traffic analysis
501 : : */
502 : 0 : packet_send_ignore(len);
503 : 0 : packet_send();
504 : : }
505 : : /* Consume the data from the buffer. */
506 : 0 : buffer_consume(&stdin_buffer, len);
507 : : /* Update the count of bytes written to the program. */
508 : 0 : stdin_bytes += len;
509 : : }
510 : : }
511 : : /* Send any buffered packet data to the client. */
512 [ - + ][ # # ]: 4454 : if (FD_ISSET(connection_out, writeset))
[ + + ]
513 : 2007 : packet_write_poll();
514 : 4454 : }
515 : :
516 : : /*
517 : : * Wait until all buffered output has been sent to the client.
518 : : * This is used when the program terminates.
519 : : */
520 : : static void
521 : 23 : drain_output(void)
522 : : {
523 : : /* Send any buffered stdout data to the client. */
524 [ - + ]: 23 : if (buffer_len(&stdout_buffer) > 0) {
525 : 0 : packet_start(SSH_SMSG_STDOUT_DATA);
526 : 0 : packet_put_string(buffer_ptr(&stdout_buffer),
527 : : buffer_len(&stdout_buffer));
528 : 0 : packet_send();
529 : : /* Update the count of sent bytes. */
530 : 0 : stdout_bytes += buffer_len(&stdout_buffer);
531 : : }
532 : : /* Send any buffered stderr data to the client. */
533 [ - + ]: 23 : if (buffer_len(&stderr_buffer) > 0) {
534 : 0 : packet_start(SSH_SMSG_STDERR_DATA);
535 : 0 : packet_put_string(buffer_ptr(&stderr_buffer),
536 : : buffer_len(&stderr_buffer));
537 : 0 : packet_send();
538 : : /* Update the count of sent bytes. */
539 : 0 : stderr_bytes += buffer_len(&stderr_buffer);
540 : : }
541 : : /* Wait until all buffered data has been written to the client. */
542 : 23 : packet_write_wait();
543 : 23 : }
544 : :
545 : : static void
546 : 5193 : process_buffered_input_packets(void)
547 : : {
548 [ + + ]: 5193 : dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
549 : 4480 : }
550 : :
551 : : /*
552 : : * Performs the interactive session. This handles data transmission between
553 : : * the client and the program. Note that the notion of stdin, stdout, and
554 : : * stderr in this function is sort of reversed: this function writes to
555 : : * stdin (of the child program), and reads from stdout and stderr (of the
556 : : * child program).
557 : : */
558 : : void
559 : 23 : server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
560 : : {
561 : 23 : fd_set *readset = NULL, *writeset = NULL;
562 : 23 : int max_fd = 0;
563 : 23 : u_int nalloc = 0;
564 : : int wait_status; /* Status returned by wait(). */
565 : : pid_t wait_pid; /* pid returned by wait(). */
566 : 23 : int waiting_termination = 0; /* Have displayed waiting close message. */
567 : : u_int64_t max_time_milliseconds;
568 : : u_int previous_stdout_buffer_bytes;
569 : : u_int stdout_buffer_bytes;
570 : : int type;
571 : :
572 : 23 : debug("Entering interactive session.");
573 : :
574 : : /* Initialize the SIGCHLD kludge. */
575 : 23 : child_terminated = 0;
576 : 23 : mysignal(SIGCHLD, sigchld_handler);
577 : :
578 [ + + ]: 23 : if (!use_privsep) {
579 : 1 : signal(SIGTERM, sigterm_handler);
580 : 1 : signal(SIGINT, sigterm_handler);
581 : 1 : signal(SIGQUIT, sigterm_handler);
582 : : }
583 : :
584 : : /* Initialize our global variables. */
585 : 23 : fdin = fdin_arg;
586 : 23 : fdout = fdout_arg;
587 : 23 : fderr = fderr_arg;
588 : :
589 : : /* nonblocking IO */
590 : 23 : set_nonblock(fdin);
591 : 23 : set_nonblock(fdout);
592 : : /* we don't have stderr for interactive terminal sessions, see below */
593 [ + - ]: 23 : if (fderr != -1)
594 : 23 : set_nonblock(fderr);
595 : :
596 [ + - ][ - + ]: 23 : if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
597 : 0 : fdin_is_tty = 1;
598 : :
599 : 23 : connection_in = packet_get_connection_in();
600 : 23 : connection_out = packet_get_connection_out();
601 : :
602 : 23 : notify_setup();
603 : :
604 : 23 : previous_stdout_buffer_bytes = 0;
605 : :
606 : : /* Set approximate I/O buffer size. */
607 [ - + ]: 23 : if (packet_is_interactive())
608 : 0 : buffer_high = 4096;
609 : : else
610 : 23 : buffer_high = 64 * 1024;
611 : :
612 : : #if 0
613 : : /* Initialize max_fd to the maximum of the known file descriptors. */
614 : : max_fd = MAX(connection_in, connection_out);
615 : : max_fd = MAX(max_fd, fdin);
616 : : max_fd = MAX(max_fd, fdout);
617 : : if (fderr != -1)
618 : : max_fd = MAX(max_fd, fderr);
619 : : #endif
620 : :
621 : : /* Initialize Initialize buffers. */
622 : 23 : buffer_init(&stdin_buffer);
623 : 23 : buffer_init(&stdout_buffer);
624 : 23 : buffer_init(&stderr_buffer);
625 : :
626 : : /*
627 : : * If we have no separate fderr (which is the case when we have a pty
628 : : * - there we cannot make difference between data sent to stdout and
629 : : * stderr), indicate that we have seen an EOF from stderr. This way
630 : : * we don't need to check the descriptor everywhere.
631 : : */
632 [ - + ]: 23 : if (fderr == -1)
633 : 0 : fderr_eof = 1;
634 : :
635 : 23 : server_init_dispatch();
636 : :
637 : : /* Main loop of the server for the interactive session mode. */
638 : : for (;;) {
639 : :
640 : : /* Process buffered packets from the client. */
641 : 1811 : process_buffered_input_packets();
642 : :
643 : : /*
644 : : * If we have received eof, and there is no more pending
645 : : * input data, cause a real eof by closing fdin.
646 : : */
647 [ + + ][ + + ]: 1811 : if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
[ + - ]
648 [ + - ]: 10 : if (fdin != fdout)
649 : 10 : close(fdin);
650 : : else
651 : 0 : shutdown(fdin, SHUT_WR); /* We will no longer send. */
652 : 10 : fdin = -1;
653 : : }
654 : : /* Make packets from buffered stderr data to send to the client. */
655 : 1811 : make_packets_from_stderr_data();
656 : :
657 : : /*
658 : : * Make packets from buffered stdout data to send to the
659 : : * client. If there is very little to send, this arranges to
660 : : * not send them now, but to wait a short while to see if we
661 : : * are getting more data. This is necessary, as some systems
662 : : * wake up readers from a pty after each separate character.
663 : : */
664 : 1811 : max_time_milliseconds = 0;
665 : 1811 : stdout_buffer_bytes = buffer_len(&stdout_buffer);
666 [ + + ][ + + ]: 1811 : if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
667 : : stdout_buffer_bytes != previous_stdout_buffer_bytes) {
668 : : /* try again after a while */
669 : : max_time_milliseconds = 10;
670 : : } else {
671 : : /* Send it now. */
672 : 1807 : make_packets_from_stdout_data();
673 : : }
674 : 1811 : previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
675 : :
676 : : /* Send channel data to the client. */
677 [ + - ]: 1811 : if (packet_not_very_much_data_to_write())
678 : 1811 : channel_output_poll();
679 : :
680 : : /*
681 : : * Bail out of the loop if the program has closed its output
682 : : * descriptors, and we have no more data to send to the
683 : : * client, and there is no pending buffered data.
684 : : */
685 [ + + ][ + + ]: 1834 : if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
[ + + + - ]
686 [ + - ]: 46 : buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
687 [ - + ]: 23 : if (!channel_still_open())
688 : : break;
689 [ # # ]: 0 : if (!waiting_termination) {
690 : 0 : const char *s = "Waiting for forwarded connections to terminate...\r\n";
691 : : char *cp;
692 : 0 : waiting_termination = 1;
693 : 0 : buffer_append(&stderr_buffer, s, strlen(s));
694 : :
695 : : /* Display list of open channels. */
696 : 0 : cp = channel_open_message();
697 : 0 : buffer_append(&stderr_buffer, cp, strlen(cp));
698 : 0 : free(cp);
699 : : }
700 : : }
701 : 1788 : max_fd = MAX(connection_in, connection_out);
702 : 1788 : max_fd = MAX(max_fd, fdin);
703 : 1788 : max_fd = MAX(max_fd, fdout);
704 : 1788 : max_fd = MAX(max_fd, fderr);
705 : 1788 : max_fd = MAX(max_fd, notify_pipe[0]);
706 : :
707 : : /* Sleep in select() until we can do something. */
708 : 1788 : wait_until_can_do_something(&readset, &writeset, &max_fd,
709 : : &nalloc, max_time_milliseconds);
710 : :
711 [ - + ]: 1788 : if (received_sigterm) {
712 : 0 : logit("Exiting on signal %d", (int)received_sigterm);
713 : : /* Clean up sessions, utmp, etc. */
714 : 0 : cleanup_exit(255);
715 : : }
716 : :
717 : : /* Process any channel events. */
718 : 1788 : channel_after_select(readset, writeset);
719 : :
720 : : /* Process input from the client and from program stdout/stderr. */
721 : 1788 : process_input(readset);
722 : :
723 : : /* Process output to the client and to program stdin. */
724 : 1788 : process_output(writeset);
725 : 1788 : }
726 : 23 : free(readset);
727 : 23 : free(writeset);
728 : :
729 : : /* Cleanup and termination code. */
730 : :
731 : : /* Wait until all output has been sent to the client. */
732 : 23 : drain_output();
733 : :
734 : 23 : debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
735 : : stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
736 : :
737 : : /* Free and clear the buffers. */
738 : 23 : buffer_free(&stdin_buffer);
739 : 23 : buffer_free(&stdout_buffer);
740 : 23 : buffer_free(&stderr_buffer);
741 : :
742 : : /* Close the file descriptors. */
743 [ + - ]: 23 : if (fdout != -1)
744 : 23 : close(fdout);
745 : 23 : fdout = -1;
746 : 23 : fdout_eof = 1;
747 [ + - ]: 23 : if (fderr != -1)
748 : 23 : close(fderr);
749 : 23 : fderr = -1;
750 : 23 : fderr_eof = 1;
751 [ + + ]: 23 : if (fdin != -1)
752 : 13 : close(fdin);
753 : 23 : fdin = -1;
754 : :
755 : 23 : channel_free_all();
756 : :
757 : : /* We no longer want our SIGCHLD handler to be called. */
758 : 23 : mysignal(SIGCHLD, SIG_DFL);
759 : :
760 [ - + ]: 23 : while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
761 [ # # ]: 0 : if (errno != EINTR)
762 : 0 : packet_disconnect("wait: %.100s", strerror(errno));
763 [ - + ]: 23 : if (wait_pid != pid)
764 : 0 : error("Strange, wait returned pid %ld, expected %ld",
765 : : (long)wait_pid, (long)pid);
766 : :
767 : : /* Check if it exited normally. */
768 [ + - ]: 23 : if (WIFEXITED(wait_status)) {
769 : : /* Yes, normal exit. Get exit status and send it to the client. */
770 : 23 : debug("Command exited with status %d.", WEXITSTATUS(wait_status));
771 : 23 : packet_start(SSH_SMSG_EXITSTATUS);
772 : 23 : packet_put_int(WEXITSTATUS(wait_status));
773 : 23 : packet_send();
774 : 23 : packet_write_wait();
775 : :
776 : : /*
777 : : * Wait for exit confirmation. Note that there might be
778 : : * other packets coming before it; however, the program has
779 : : * already died so we just ignore them. The client is
780 : : * supposed to respond with the confirmation when it receives
781 : : * the exit status.
782 : : */
783 : : do {
784 : 23 : type = packet_read();
785 : : }
786 [ - + ]: 23 : while (type != SSH_CMSG_EXIT_CONFIRMATION);
787 : :
788 : 23 : debug("Received exit confirmation.");
789 : 23 : return;
790 : : }
791 : : /* Check if the program terminated due to a signal. */
792 [ # # ]: 0 : if (WIFSIGNALED(wait_status))
793 : 0 : packet_disconnect("Command terminated on signal %d.",
794 : 0 : WTERMSIG(wait_status));
795 : :
796 : : /* Some weird exit cause. Just exit. */
797 : 0 : packet_disconnect("wait returned status %04x.", wait_status);
798 : : /* NOTREACHED */
799 : : }
800 : :
801 : : static void
802 : 2672 : collect_children(void)
803 : : {
804 : : pid_t pid;
805 : : sigset_t oset, nset;
806 : : int status;
807 : :
808 : : /* block SIGCHLD while we check for dead children */
809 : 2672 : sigemptyset(&nset);
810 : 2672 : sigaddset(&nset, SIGCHLD);
811 : 2672 : sigprocmask(SIG_BLOCK, &nset, &oset);
812 [ + + ]: 2672 : if (child_terminated) {
813 : 15 : debug("Received SIGCHLD.");
814 [ + + ][ + - ]: 45 : while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
815 [ - + ]: 15 : (pid < 0 && errno == EINTR))
816 [ + - ]: 15 : if (pid > 0)
817 : 30 : session_close_by_pid(pid, status);
818 : 15 : child_terminated = 0;
819 : : }
820 : 2672 : sigprocmask(SIG_SETMASK, &oset, NULL);
821 : 2672 : }
822 : :
823 : : void
824 : 716 : server_loop2(Authctxt *authctxt)
825 : : {
826 : 716 : fd_set *readset = NULL, *writeset = NULL;
827 : 716 : int rekeying = 0, max_fd;
828 : 716 : u_int nalloc = 0;
829 : 716 : u_int64_t rekey_timeout_ms = 0;
830 : :
831 : 716 : debug("Entering interactive session for SSH2.");
832 : :
833 : 716 : mysignal(SIGCHLD, sigchld_handler);
834 : 716 : child_terminated = 0;
835 : 716 : connection_in = packet_get_connection_in();
836 : 716 : connection_out = packet_get_connection_out();
837 : :
838 [ + + ]: 716 : if (!use_privsep) {
839 : 74 : signal(SIGTERM, sigterm_handler);
840 : 74 : signal(SIGINT, sigterm_handler);
841 : 74 : signal(SIGQUIT, sigterm_handler);
842 : : }
843 : :
844 : 716 : notify_setup();
845 : :
846 : 716 : max_fd = MAX(connection_in, connection_out);
847 : 716 : max_fd = MAX(max_fd, notify_pipe[0]);
848 : :
849 : 716 : server_init_dispatch();
850 : :
851 : : for (;;) {
852 : 3382 : process_buffered_input_packets();
853 : :
854 [ + - ][ + - ]: 2669 : rekeying = (xxx_kex != NULL && !xxx_kex->done);
855 : :
856 [ + - ][ + - ]: 2669 : if (!rekeying && packet_not_very_much_data_to_write())
857 : 2669 : channel_output_poll();
858 [ + + ][ + - ]: 2669 : if (options.rekey_interval > 0 && compat20 && !rekeying)
[ + - ]
859 : 6 : rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
860 : : else
861 : : rekey_timeout_ms = 0;
862 : :
863 : 2669 : wait_until_can_do_something(&readset, &writeset, &max_fd,
864 : : &nalloc, rekey_timeout_ms);
865 : :
866 [ - + ]: 2669 : if (received_sigterm) {
867 : 0 : logit("Exiting on signal %d", (int)received_sigterm);
868 : : /* Clean up sessions, utmp, etc. */
869 : 0 : cleanup_exit(255);
870 : : }
871 : :
872 : 2669 : collect_children();
873 [ + - ]: 2669 : if (!rekeying) {
874 : 2669 : channel_after_select(readset, writeset);
875 [ - + ]: 2669 : if (packet_need_rekeying()) {
876 : 0 : debug("need rekeying");
877 : 0 : xxx_kex->done = 0;
878 : 0 : kex_send_kexinit(xxx_kex);
879 : : }
880 : : }
881 : 2669 : process_input(readset);
882 [ + + ]: 2669 : if (connection_closed)
883 : : break;
884 : 2666 : process_output(writeset);
885 : 2666 : }
886 : 3 : collect_children();
887 : :
888 : 3 : free(readset);
889 : 3 : free(writeset);
890 : :
891 : : /* free all channels, no more reads and writes */
892 : 3 : channel_free_all();
893 : :
894 : : /* free remaining sessions, e.g. remove wtmp entries */
895 : 3 : session_destroy_all(NULL);
896 : 3 : }
897 : :
898 : : static void
899 : 0 : server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
900 : : {
901 : 0 : debug("Got %d/%u for keepalive", type, seq);
902 : : /*
903 : : * reset timeout, since we got a sane answer from the client.
904 : : * even if this was generated by something other than
905 : : * the bogus CHANNEL_REQUEST we send for keepalives.
906 : : */
907 : 0 : packet_set_alive_timeouts(0);
908 : 0 : }
909 : :
910 : : static void
911 : 0 : server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
912 : : {
913 : : char *data;
914 : : u_int data_len;
915 : :
916 : : /* Stdin data from the client. Append it to the buffer. */
917 : : /* Ignore any data if the client has closed stdin. */
918 [ # # ]: 0 : if (fdin == -1)
919 : 0 : return;
920 : 0 : data = packet_get_string(&data_len);
921 [ # # ]: 0 : packet_check_eom();
922 : 0 : buffer_append(&stdin_buffer, data, data_len);
923 : 0 : explicit_bzero(data, data_len);
924 : 0 : free(data);
925 : : }
926 : :
927 : : static void
928 : 10 : server_input_eof(int type, u_int32_t seq, void *ctxt)
929 : : {
930 : : /*
931 : : * Eof from the client. The stdin descriptor to the
932 : : * program will be closed when all buffered data has
933 : : * drained.
934 : : */
935 : 10 : debug("EOF received for stdin.");
936 [ - + ]: 10 : packet_check_eom();
937 : 10 : stdin_eof = 1;
938 : 10 : }
939 : :
940 : : static void
941 : 0 : server_input_window_size(int type, u_int32_t seq, void *ctxt)
942 : : {
943 : 0 : u_int row = packet_get_int();
944 : 0 : u_int col = packet_get_int();
945 : 0 : u_int xpixel = packet_get_int();
946 : 0 : u_int ypixel = packet_get_int();
947 : :
948 : 0 : debug("Window change received.");
949 [ # # ]: 0 : packet_check_eom();
950 [ # # ]: 0 : if (fdin != -1)
951 : 0 : pty_change_window_size(fdin, row, col, xpixel, ypixel);
952 : 0 : }
953 : :
954 : : static Channel *
955 : 1 : server_request_direct_tcpip(void)
956 : : {
957 : 1 : Channel *c = NULL;
958 : : char *target, *originator;
959 : : u_short target_port, originator_port;
960 : :
961 : 1 : target = packet_get_string(NULL);
962 : 1 : target_port = packet_get_int();
963 : 1 : originator = packet_get_string(NULL);
964 : 1 : originator_port = packet_get_int();
965 [ - + ]: 1 : packet_check_eom();
966 : :
967 : 1 : debug("server_request_direct_tcpip: originator %s port %d, target %s "
968 : : "port %d", originator, originator_port, target, target_port);
969 : :
970 : : /* XXX fine grained permissions */
971 [ + - ][ + - ]: 1 : if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
972 : 1 : !no_port_forwarding_flag) {
973 : 1 : c = channel_connect_to(target, target_port,
974 : : "direct-tcpip", "direct-tcpip");
975 : : } else {
976 : 0 : logit("refused local port forward: "
977 : : "originator %s port %d, target %s port %d",
978 : : originator, originator_port, target, target_port);
979 : : }
980 : :
981 : 1 : free(originator);
982 : 1 : free(target);
983 : :
984 : 1 : return c;
985 : : }
986 : :
987 : : static Channel *
988 : 0 : server_request_tun(void)
989 : : {
990 : 0 : Channel *c = NULL;
991 : : int mode, tun;
992 : : int sock;
993 : :
994 : 0 : mode = packet_get_int();
995 [ # # ]: 0 : switch (mode) {
996 : : case SSH_TUNMODE_POINTOPOINT:
997 : : case SSH_TUNMODE_ETHERNET:
998 : : break;
999 : : default:
1000 : 0 : packet_send_debug("Unsupported tunnel device mode.");
1001 : 0 : return NULL;
1002 : : }
1003 [ # # ]: 0 : if ((options.permit_tun & mode) == 0) {
1004 : 0 : packet_send_debug("Server has rejected tunnel device "
1005 : : "forwarding");
1006 : 0 : return NULL;
1007 : : }
1008 : :
1009 : 0 : tun = packet_get_int();
1010 [ # # ]: 0 : if (forced_tun_device != -1) {
1011 [ # # ][ # # ]: 0 : if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
1012 : : goto done;
1013 : : tun = forced_tun_device;
1014 : : }
1015 : 0 : sock = tun_open(tun, mode);
1016 [ # # ]: 0 : if (sock < 0)
1017 : : goto done;
1018 : 0 : c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
1019 : : CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
1020 : 0 : c->datagram = 1;
1021 : : #if defined(SSH_TUN_FILTER)
1022 [ # # ]: 0 : if (mode == SSH_TUNMODE_POINTOPOINT)
1023 : 0 : channel_register_filter(c->self, sys_tun_infilter,
1024 : : sys_tun_outfilter, NULL, NULL);
1025 : : #endif
1026 : :
1027 : : done:
1028 [ # # ]: 0 : if (c == NULL)
1029 : 0 : packet_send_debug("Failed to open the tunnel device.");
1030 : 0 : return c;
1031 : : }
1032 : :
1033 : : static Channel *
1034 : 729 : server_request_session(void)
1035 : : {
1036 : : Channel *c;
1037 : :
1038 : 729 : debug("input_session_request");
1039 [ - + ]: 729 : packet_check_eom();
1040 : :
1041 [ - + ]: 729 : if (no_more_sessions) {
1042 : 0 : packet_disconnect("Possible attack: attempt to open a session "
1043 : : "after additional sessions disabled");
1044 : : }
1045 : :
1046 : : /*
1047 : : * A server session has no fd to read or write until a
1048 : : * CHANNEL_REQUEST for a shell is made, so we set the type to
1049 : : * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
1050 : : * CHANNEL_REQUEST messages is registered.
1051 : : */
1052 : 729 : c = channel_new("session", SSH_CHANNEL_LARVAL,
1053 : : -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
1054 : : 0, "server-session", 1);
1055 [ - + ]: 729 : if (session_open(the_authctxt, c->self) != 1) {
1056 : 0 : debug("session open failed, free channel %d", c->self);
1057 : 0 : channel_free(c);
1058 : 0 : return NULL;
1059 : : }
1060 : 729 : channel_register_cleanup(c->self, session_close_by_channel, 0);
1061 : 729 : return c;
1062 : : }
1063 : :
1064 : : static void
1065 : 730 : server_input_channel_open(int type, u_int32_t seq, void *ctxt)
1066 : : {
1067 : 730 : Channel *c = NULL;
1068 : : char *ctype;
1069 : : int rchan;
1070 : : u_int rmaxpack, rwindow, len;
1071 : :
1072 : 730 : ctype = packet_get_string(&len);
1073 : 730 : rchan = packet_get_int();
1074 : 730 : rwindow = packet_get_int();
1075 : 730 : rmaxpack = packet_get_int();
1076 : :
1077 : 730 : debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
1078 : : ctype, rchan, rwindow, rmaxpack);
1079 : :
1080 [ + + ]: 730 : if (strcmp(ctype, "session") == 0) {
1081 : 729 : c = server_request_session();
1082 [ + - ]: 1 : } else if (strcmp(ctype, "direct-tcpip") == 0) {
1083 : 1 : c = server_request_direct_tcpip();
1084 [ # # ]: 0 : } else if (strcmp(ctype, "tun@openssh.com") == 0) {
1085 : 0 : c = server_request_tun();
1086 : : }
1087 [ + - ]: 730 : if (c != NULL) {
1088 : 730 : debug("server_input_channel_open: confirm %s", ctype);
1089 : 730 : c->remote_id = rchan;
1090 : 730 : c->remote_window = rwindow;
1091 : 730 : c->remote_maxpacket = rmaxpack;
1092 [ + + ]: 730 : if (c->type != SSH_CHANNEL_CONNECTING) {
1093 : 729 : packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1094 : 729 : packet_put_int(c->remote_id);
1095 : 729 : packet_put_int(c->self);
1096 : 729 : packet_put_int(c->local_window);
1097 : 729 : packet_put_int(c->local_maxpacket);
1098 : 729 : packet_send();
1099 : : }
1100 : : } else {
1101 : 0 : debug("server_input_channel_open: failure %s", ctype);
1102 : 0 : packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1103 : 0 : packet_put_int(rchan);
1104 : 0 : packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
1105 [ # # ]: 0 : if (!(datafellows & SSH_BUG_OPENFAILURE)) {
1106 : 0 : packet_put_cstring("open failed");
1107 : 0 : packet_put_cstring("");
1108 : : }
1109 : 0 : packet_send();
1110 : : }
1111 : 730 : free(ctype);
1112 : 730 : }
1113 : :
1114 : : static void
1115 : 746 : server_input_global_request(int type, u_int32_t seq, void *ctxt)
1116 : : {
1117 : : char *rtype;
1118 : : int want_reply;
1119 : 746 : int success = 0, allocated_listen_port = 0;
1120 : :
1121 : 746 : rtype = packet_get_string(NULL);
1122 : 746 : want_reply = packet_get_char();
1123 : 746 : debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
1124 : :
1125 : : /* -R style forwarding */
1126 [ + + ]: 746 : if (strcmp(rtype, "tcpip-forward") == 0) {
1127 : : struct passwd *pw;
1128 : : char *listen_address;
1129 : : u_short listen_port;
1130 : :
1131 : 33 : pw = the_authctxt->pw;
1132 [ + - ][ - + ]: 33 : if (pw == NULL || !the_authctxt->valid)
1133 : 0 : fatal("server_input_global_request: no/invalid user");
1134 : 33 : listen_address = packet_get_string(NULL);
1135 : 33 : listen_port = (u_short)packet_get_int();
1136 : 33 : debug("server_input_global_request: tcpip-forward listen %s port %d",
1137 : : listen_address, listen_port);
1138 : :
1139 : : /* check permissions */
1140 [ + - ][ + - ]: 33 : if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
1141 [ + - ]: 33 : no_port_forwarding_flag ||
1142 : 33 : (!want_reply && listen_port == 0)
1143 : : #ifndef NO_IPPORT_RESERVED_CONCEPT
1144 [ - + ][ # # ]: 33 : || (listen_port != 0 && listen_port < IPPORT_RESERVED &&
1145 : 0 : pw->pw_uid != 0)
1146 : : #endif
1147 : : ) {
1148 : 0 : success = 0;
1149 : 0 : packet_send_debug("Server has disabled port forwarding.");
1150 : : } else {
1151 : : /* Start listening on the port */
1152 : 33 : success = channel_setup_remote_fwd_listener(
1153 : : listen_address, listen_port,
1154 : : &allocated_listen_port, options.gateway_ports);
1155 : : }
1156 : 33 : free(listen_address);
1157 [ - + ]: 713 : } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
1158 : : char *cancel_address;
1159 : : u_short cancel_port;
1160 : :
1161 : 0 : cancel_address = packet_get_string(NULL);
1162 : 0 : cancel_port = (u_short)packet_get_int();
1163 : 0 : debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
1164 : : cancel_address, cancel_port);
1165 : :
1166 : 0 : success = channel_cancel_rport_listener(cancel_address,
1167 : : cancel_port);
1168 : 0 : free(cancel_address);
1169 [ + - ]: 713 : } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
1170 : 713 : no_more_sessions = 1;
1171 : 713 : success = 1;
1172 : : }
1173 [ + + ]: 746 : if (want_reply) {
1174 [ + + ]: 33 : packet_start(success ?
1175 : : SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1176 [ + + ][ - + ]: 33 : if (success && allocated_listen_port > 0)
1177 : 0 : packet_put_int(allocated_listen_port);
1178 : 33 : packet_send();
1179 : 33 : packet_write_wait();
1180 : : }
1181 : 746 : free(rtype);
1182 : 746 : }
1183 : :
1184 : : static void
1185 : 790 : server_input_channel_req(int type, u_int32_t seq, void *ctxt)
1186 : : {
1187 : : Channel *c;
1188 : 790 : int id, reply, success = 0;
1189 : : char *rtype;
1190 : :
1191 : 790 : id = packet_get_int();
1192 : 790 : rtype = packet_get_string(NULL);
1193 : 790 : reply = packet_get_char();
1194 : :
1195 : 790 : debug("server_input_channel_req: channel %d request %s reply %d",
1196 : : id, rtype, reply);
1197 : :
1198 [ - + ]: 790 : if ((c = channel_lookup(id)) == NULL)
1199 : 0 : packet_disconnect("server_input_channel_req: "
1200 : : "unknown channel %d", id);
1201 [ - + ]: 790 : if (!strcmp(rtype, "eow@openssh.com")) {
1202 [ # # ]: 0 : packet_check_eom();
1203 : 0 : chan_rcvd_eow(c);
1204 [ + - ]: 790 : } else if ((c->type == SSH_CHANNEL_LARVAL ||
1205 [ + - ]: 790 : c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
1206 : 790 : success = session_input_channel_req(c, rtype);
1207 [ + + ]: 77 : if (reply) {
1208 [ - + ]: 15 : packet_start(success ?
1209 : : SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1210 : 15 : packet_put_int(c->remote_id);
1211 : 15 : packet_send();
1212 : : }
1213 : 77 : free(rtype);
1214 : 77 : }
1215 : :
1216 : : static void
1217 : 716 : server_init_dispatch_20(void)
1218 : : {
1219 : 716 : debug("server_init_dispatch_20");
1220 : 716 : dispatch_init(&dispatch_protocol_error);
1221 : 716 : dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
1222 : 716 : dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
1223 : 716 : dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
1224 : 716 : dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
1225 : 716 : dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
1226 : 716 : dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1227 : 716 : dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1228 : 716 : dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
1229 : 716 : dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1230 : 716 : dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
1231 : : /* client_alive */
1232 : 716 : dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
1233 : 716 : dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
1234 : 716 : dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
1235 : 716 : dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
1236 : : /* rekeying */
1237 : 716 : dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
1238 : 716 : }
1239 : : static void
1240 : 23 : server_init_dispatch_13(void)
1241 : : {
1242 : 23 : debug("server_init_dispatch_13");
1243 : 23 : dispatch_init(NULL);
1244 : 23 : dispatch_set(SSH_CMSG_EOF, &server_input_eof);
1245 : 23 : dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
1246 : 23 : dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
1247 : 23 : dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
1248 : 23 : dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
1249 : 23 : dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
1250 : 23 : dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1251 : 23 : dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1252 : 23 : dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1253 : 23 : }
1254 : : static void
1255 : 23 : server_init_dispatch_15(void)
1256 : : {
1257 : 23 : server_init_dispatch_13();
1258 : 23 : debug("server_init_dispatch_15");
1259 : 23 : dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
1260 : 23 : dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
1261 : 23 : }
1262 : : static void
1263 : 739 : server_init_dispatch(void)
1264 : : {
1265 [ + + ]: 739 : if (compat20)
1266 : 716 : server_init_dispatch_20();
1267 [ - + ]: 23 : else if (compat13)
1268 : 0 : server_init_dispatch_13();
1269 : : else
1270 : 23 : server_init_dispatch_15();
1271 : 739 : }
|