]> andersk Git - openssh.git/blob - serverloop.c
- More large OpenBSD CVS updates:
[openssh.git] / serverloop.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Created: Sun Sep 10 00:30:37 1995 ylo
6  * Server main loop for handling the interactive session.
7  */
8 /*
9  * SSH2 support by Markus Friedl.
10  * Copyright (c) 2000 Markus Friedl. All rights reserved.
11  */
12
13 #include "includes.h"
14 #include "xmalloc.h"
15 #include "ssh.h"
16 #include "packet.h"
17 #include "buffer.h"
18 #include "servconf.h"
19 #include "pty.h"
20 #include "channels.h"
21
22 #include "compat.h"
23 #include "ssh2.h"
24 #include "session.h"
25 #include "dispatch.h"
26
27 static Buffer stdin_buffer;     /* Buffer for stdin data. */
28 static Buffer stdout_buffer;    /* Buffer for stdout data. */
29 static Buffer stderr_buffer;    /* Buffer for stderr data. */
30 static int fdin;                /* Descriptor for stdin (for writing) */
31 static int fdout;               /* Descriptor for stdout (for reading);
32                                    May be same number as fdin. */
33 static int fderr;               /* Descriptor for stderr.  May be -1. */
34 static long stdin_bytes = 0;    /* Number of bytes written to stdin. */
35 static long stdout_bytes = 0;   /* Number of stdout bytes sent to client. */
36 static long stderr_bytes = 0;   /* Number of stderr bytes sent to client. */
37 static long fdout_bytes = 0;    /* Number of stdout bytes read from program. */
38 static int stdin_eof = 0;       /* EOF message received from client. */
39 static int fdout_eof = 0;       /* EOF encountered reading from fdout. */
40 static int fderr_eof = 0;       /* EOF encountered readung from fderr. */
41 static int connection_in;       /* Connection to client (input). */
42 static int connection_out;      /* Connection to client (output). */
43 static unsigned int buffer_high;/* "Soft" max buffer size. */
44 static int max_fd;              /* Max file descriptor number for select(). */
45
46 /*
47  * This SIGCHLD kludge is used to detect when the child exits.  The server
48  * will exit after that, as soon as forwarded connections have terminated.
49  *
50  * After SIGCHLD child_has_selected is set to 1 after the first pass
51  * through the wait_until_can_do_something() select(). This ensures
52  * that the child's output gets a chance to drain before it is yanked.
53  */
54
55 static int child_pid;                   /* Pid of the child. */
56 static volatile int child_terminated;   /* The child has terminated. */
57 static volatile int child_has_selected; /* Child has had chance to drain. */
58 static volatile int child_wait_status;  /* Status from wait(). */
59
60 void    server_init_dispatch(void);
61
62 void 
63 sigchld_handler(int sig)
64 {
65         int save_errno = errno;
66         int wait_pid;
67         debug("Received SIGCHLD.");
68         wait_pid = wait((int *) &child_wait_status);
69         if (wait_pid != -1) {
70                 if (wait_pid != child_pid)
71                         error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
72                               wait_pid, child_pid);
73                 if (WIFEXITED(child_wait_status) ||
74                     WIFSIGNALED(child_wait_status))
75                         child_terminated = 1;
76                         child_has_selected = 0;
77         }
78         signal(SIGCHLD, sigchld_handler);
79         errno = save_errno;
80 }
81 void 
82 sigchld_handler2(int sig)
83 {
84         int save_errno = errno;
85         debug("Received SIGCHLD.");
86         child_terminated = 1;
87         signal(SIGCHLD, sigchld_handler2);
88         errno = save_errno;
89 }
90
91 /*
92  * Make packets from buffered stderr data, and buffer it for sending
93  * to the client.
94  */
95 void 
96 make_packets_from_stderr_data()
97 {
98         int len;
99
100         /* Send buffered stderr data to the client. */
101         while (buffer_len(&stderr_buffer) > 0 &&
102             packet_not_very_much_data_to_write()) {
103                 len = buffer_len(&stderr_buffer);
104                 if (packet_is_interactive()) {
105                         if (len > 512)
106                                 len = 512;
107                 } else {
108                         /* Keep the packets at reasonable size. */
109                         if (len > packet_get_maxsize())
110                                 len = packet_get_maxsize();
111                 }
112                 packet_start(SSH_SMSG_STDERR_DATA);
113                 packet_put_string(buffer_ptr(&stderr_buffer), len);
114                 packet_send();
115                 buffer_consume(&stderr_buffer, len);
116                 stderr_bytes += len;
117         }
118 }
119
120 /*
121  * Make packets from buffered stdout data, and buffer it for sending to the
122  * client.
123  */
124 void 
125 make_packets_from_stdout_data()
126 {
127         int len;
128
129         /* Send buffered stdout data to the client. */
130         while (buffer_len(&stdout_buffer) > 0 &&
131             packet_not_very_much_data_to_write()) {
132                 len = buffer_len(&stdout_buffer);
133                 if (packet_is_interactive()) {
134                         if (len > 512)
135                                 len = 512;
136                 } else {
137                         /* Keep the packets at reasonable size. */
138                         if (len > packet_get_maxsize())
139                                 len = packet_get_maxsize();     
140                 }
141                 packet_start(SSH_SMSG_STDOUT_DATA);
142                 packet_put_string(buffer_ptr(&stdout_buffer), len);
143                 packet_send();
144                 buffer_consume(&stdout_buffer, len);
145                 stdout_bytes += len;
146         }
147 }
148
149 /*
150  * Sleep in select() until we can do something.  This will initialize the
151  * select masks.  Upon return, the masks will indicate which descriptors
152  * have data or can accept data.  Optionally, a maximum time can be specified
153  * for the duration of the wait (0 = infinite).
154  */
155 void 
156 wait_until_can_do_something(fd_set * readset, fd_set * writeset,
157                             unsigned int max_time_milliseconds)
158 {
159         struct timeval tv, *tvp;
160         int ret;
161
162         /* When select fails we restart from here. */
163 retry_select:
164
165         /* Initialize select() masks. */
166         FD_ZERO(readset);
167
168         /*
169          * Read packets from the client unless we have too much buffered
170          * stdin or channel data.
171          */
172         if (compat20) {
173                 // wrong: bad conditionXXX
174                 if (channel_not_very_much_buffered_data())
175                         FD_SET(connection_in, readset);
176         } else {
177                 if (buffer_len(&stdin_buffer) < 4096 &&
178                     channel_not_very_much_buffered_data())
179                         FD_SET(connection_in, readset);
180         }
181
182         /*
183          * If there is not too much data already buffered going to the
184          * client, try to get some more data from the program.
185          */
186         if (!compat20 && packet_not_very_much_data_to_write()) {
187                 if (!fdout_eof)
188                         FD_SET(fdout, readset);
189                 if (!fderr_eof)
190                         FD_SET(fderr, readset);
191         }
192         FD_ZERO(writeset);
193
194         /* Set masks for channel descriptors. */
195         channel_prepare_select(readset, writeset);
196
197         /*
198          * If we have buffered packet data going to the client, mark that
199          * descriptor.
200          */
201         if (packet_have_data_to_write())
202                 FD_SET(connection_out, writeset);
203
204         /* If we have buffered data, try to write some of that data to the
205            program. */
206         if (!compat20 && fdin != -1 && buffer_len(&stdin_buffer) > 0)
207                 FD_SET(fdin, writeset);
208
209         /* Update the maximum descriptor number if appropriate. */
210         if (channel_max_fd() > max_fd)
211                 max_fd = channel_max_fd();
212
213         /*
214          * If child has terminated and there is enough buffer space to read
215          * from it, then read as much as is available and exit.
216          */
217         if (child_terminated && packet_not_very_much_data_to_write())
218                 if (max_time_milliseconds == 0)
219                         max_time_milliseconds = 100;
220
221         if (max_time_milliseconds == 0)
222                 tvp = NULL;
223         else {
224                 tv.tv_sec = max_time_milliseconds / 1000;
225                 tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
226                 tvp = &tv;
227         }
228         if (tvp!=NULL)
229                 debug("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
230
231         /* Wait for something to happen, or the timeout to expire. */
232         ret = select(max_fd + 1, readset, writeset, NULL, tvp);
233
234         if (ret < 0) {
235                 if (errno != EINTR)
236                         error("select: %.100s", strerror(errno));
237                 else
238                         goto retry_select;
239         }
240         
241         if (child_terminated)
242                 child_has_selected = 1;
243 }
244
245 /*
246  * Processes input from the client and the program.  Input data is stored
247  * in buffers and processed later.
248  */
249 void 
250 process_input(fd_set * readset)
251 {
252         int len;
253         char buf[16384];
254
255         /* Read and buffer any input data from the client. */
256         if (FD_ISSET(connection_in, readset)) {
257                 len = read(connection_in, buf, sizeof(buf));
258                 if (len == 0) {
259                         verbose("Connection closed by remote host.");
260                         fatal_cleanup();
261                 }
262                 /*
263                  * There is a kernel bug on Solaris that causes select to
264                  * sometimes wake up even though there is no data available.
265                  */
266                 if (len < 0 && errno == EAGAIN)
267                         len = 0;
268
269                 if (len < 0) {
270                         verbose("Read error from remote host: %.100s", strerror(errno));
271                         fatal_cleanup();
272                 }
273                 /* Buffer any received data. */
274                 packet_process_incoming(buf, len);
275         }
276         if (compat20)
277                 return;
278
279         /* Read and buffer any available stdout data from the program. */
280         if (!fdout_eof && FD_ISSET(fdout, readset)) {
281                 len = read(fdout, buf, sizeof(buf));
282                 if (len <= 0)
283                         fdout_eof = 1;
284                 else {
285                         buffer_append(&stdout_buffer, buf, len);
286                         fdout_bytes += len;
287                 }
288         }
289         /* Read and buffer any available stderr data from the program. */
290         if (!fderr_eof && FD_ISSET(fderr, readset)) {
291                 len = read(fderr, buf, sizeof(buf));
292                 if (len <= 0)
293                         fderr_eof = 1;
294                 else
295                         buffer_append(&stderr_buffer, buf, len);
296         }
297 }
298
299 /*
300  * Sends data from internal buffers to client program stdin.
301  */
302 void 
303 process_output(fd_set * writeset)
304 {
305         int len;
306
307         /* Write buffered data to program stdin. */
308         if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
309                 len = write(fdin, buffer_ptr(&stdin_buffer),
310                     buffer_len(&stdin_buffer));
311                 if (len <= 0) {
312 #ifdef USE_PIPES
313                         close(fdin);
314 #else
315                         if (fdin != fdout)
316                                 close(fdin);
317                         else
318                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
319 #endif
320                         fdin = -1;
321                 } else {
322                         /* Successful write.  Consume the data from the buffer. */
323                         buffer_consume(&stdin_buffer, len);
324                         /* Update the count of bytes written to the program. */
325                         stdin_bytes += len;
326                 }
327         }
328         /* Send any buffered packet data to the client. */
329         if (FD_ISSET(connection_out, writeset))
330                 packet_write_poll();
331 }
332
333 /*
334  * Wait until all buffered output has been sent to the client.
335  * This is used when the program terminates.
336  */
337 void 
338 drain_output()
339 {
340         /* Send any buffered stdout data to the client. */
341         if (buffer_len(&stdout_buffer) > 0) {
342                 packet_start(SSH_SMSG_STDOUT_DATA);
343                 packet_put_string(buffer_ptr(&stdout_buffer),
344                                   buffer_len(&stdout_buffer));
345                 packet_send();
346                 /* Update the count of sent bytes. */
347                 stdout_bytes += buffer_len(&stdout_buffer);
348         }
349         /* Send any buffered stderr data to the client. */
350         if (buffer_len(&stderr_buffer) > 0) {
351                 packet_start(SSH_SMSG_STDERR_DATA);
352                 packet_put_string(buffer_ptr(&stderr_buffer),
353                                   buffer_len(&stderr_buffer));
354                 packet_send();
355                 /* Update the count of sent bytes. */
356                 stderr_bytes += buffer_len(&stderr_buffer);
357         }
358         /* Wait until all buffered data has been written to the client. */
359         packet_write_wait();
360 }
361
362 void 
363 process_buffered_input_packets()
364 {
365         dispatch_run(DISPATCH_NONBLOCK, NULL);
366 }
367
368 /*
369  * Performs the interactive session.  This handles data transmission between
370  * the client and the program.  Note that the notion of stdin, stdout, and
371  * stderr in this function is sort of reversed: this function writes to
372  * stdin (of the child program), and reads from stdout and stderr (of the
373  * child program).
374  */
375 void 
376 server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
377 {
378         int wait_status, wait_pid;      /* Status and pid returned by wait(). */
379         int waiting_termination = 0;    /* Have displayed waiting close message. */
380         unsigned int max_time_milliseconds;
381         unsigned int previous_stdout_buffer_bytes;
382         unsigned int stdout_buffer_bytes;
383         int type;
384
385         debug("Entering interactive session.");
386
387         /* Initialize the SIGCHLD kludge. */
388         child_pid = pid;
389         child_terminated = 0;
390         child_has_selected = 0;
391         signal(SIGCHLD, sigchld_handler);
392
393         /* Initialize our global variables. */
394         fdin = fdin_arg;
395         fdout = fdout_arg;
396         fderr = fderr_arg;
397         connection_in = packet_get_connection_in();
398         connection_out = packet_get_connection_out();
399
400         previous_stdout_buffer_bytes = 0;
401
402         /* Set approximate I/O buffer size. */
403         if (packet_is_interactive())
404                 buffer_high = 4096;
405         else
406                 buffer_high = 64 * 1024;
407
408         /* Initialize max_fd to the maximum of the known file descriptors. */
409         max_fd = fdin;
410         if (fdout > max_fd)
411                 max_fd = fdout;
412         if (fderr != -1 && fderr > max_fd)
413                 max_fd = fderr;
414         if (connection_in > max_fd)
415                 max_fd = connection_in;
416         if (connection_out > max_fd)
417                 max_fd = connection_out;
418
419         /* Initialize Initialize buffers. */
420         buffer_init(&stdin_buffer);
421         buffer_init(&stdout_buffer);
422         buffer_init(&stderr_buffer);
423
424         /*
425          * If we have no separate fderr (which is the case when we have a pty
426          * - there we cannot make difference between data sent to stdout and
427          * stderr), indicate that we have seen an EOF from stderr.  This way
428          * we don\'t need to check the descriptor everywhere.
429          */
430         if (fderr == -1)
431                 fderr_eof = 1;
432
433         server_init_dispatch();
434
435         /* Main loop of the server for the interactive session mode. */
436         for (;;) {
437                 fd_set readset, writeset;
438
439                 /* Process buffered packets from the client. */
440                 process_buffered_input_packets();
441
442                 /*
443                  * If we have received eof, and there is no more pending
444                  * input data, cause a real eof by closing fdin.
445                  */
446                 if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
447 #ifdef USE_PIPES
448                         close(fdin);
449 #else
450                         if (fdin != fdout)
451                                 close(fdin);
452                         else
453                                 shutdown(fdin, SHUT_WR); /* We will no longer send. */
454 #endif
455                         fdin = -1;
456                 }
457                 /* Make packets from buffered stderr data to send to the client. */
458                 make_packets_from_stderr_data();
459
460                 /*
461                  * Make packets from buffered stdout data to send to the
462                  * client. If there is very little to send, this arranges to
463                  * not send them now, but to wait a short while to see if we
464                  * are getting more data. This is necessary, as some systems
465                  * wake up readers from a pty after each separate character.
466                  */
467                 max_time_milliseconds = 0;
468                 stdout_buffer_bytes = buffer_len(&stdout_buffer);
469                 if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
470                     stdout_buffer_bytes != previous_stdout_buffer_bytes) {
471                         /* try again after a while */
472                         max_time_milliseconds = 10;
473                 } else {
474                         /* Send it now. */
475                         make_packets_from_stdout_data();
476                 }
477                 previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
478
479                 /* Send channel data to the client. */
480                 if (packet_not_very_much_data_to_write())
481                         channel_output_poll();
482
483                 /*
484                  * Bail out of the loop if the program has closed its output
485                  * descriptors, and we have no more data to send to the
486                  * client, and there is no pending buffered data.
487                  */
488                 if (((fdout_eof && fderr_eof) || 
489                     (child_terminated && child_has_selected)) && 
490                     !packet_have_data_to_write() &&
491                     (buffer_len(&stdout_buffer) == 0) && 
492                          (buffer_len(&stderr_buffer) == 0)) {
493                         if (!channel_still_open())
494                                 break;
495                         if (!waiting_termination) {
496                                 const char *s = "Waiting for forwarded connections to terminate...\r\n";
497                                 char *cp;
498                                 waiting_termination = 1;
499                                 buffer_append(&stderr_buffer, s, strlen(s));
500
501                                 /* Display list of open channels. */
502                                 cp = channel_open_message();
503                                 buffer_append(&stderr_buffer, cp, strlen(cp));
504                                 xfree(cp);
505                         }
506                 }
507                 /* Sleep in select() until we can do something. */
508                 wait_until_can_do_something(&readset, &writeset,
509                                             max_time_milliseconds);
510
511                 /* Process any channel events. */
512                 channel_after_select(&readset, &writeset);
513
514                 /* Process input from the client and from program stdout/stderr. */
515                 process_input(&readset);
516
517                 /* Process output to the client and to program stdin. */
518                 process_output(&writeset);
519         }
520
521         /* Cleanup and termination code. */
522
523         /* Wait until all output has been sent to the client. */
524         drain_output();
525
526         debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
527               stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
528
529         /* Free and clear the buffers. */
530         buffer_free(&stdin_buffer);
531         buffer_free(&stdout_buffer);
532         buffer_free(&stderr_buffer);
533
534         /* Close the file descriptors. */
535         if (fdout != -1)
536                 close(fdout);
537         fdout = -1;
538         fdout_eof = 1;
539         if (fderr != -1)
540                 close(fderr);
541         fderr = -1;
542         fderr_eof = 1;
543         if (fdin != -1)
544                 close(fdin);
545         fdin = -1;
546
547         /* Stop listening for channels; this removes unix domain sockets. */
548         channel_stop_listening();
549
550         /* Wait for the child to exit.  Get its exit status. */
551         wait_pid = wait(&wait_status);
552         if (wait_pid < 0) {
553                 /*
554                  * It is possible that the wait was handled by SIGCHLD
555                  * handler.  This may result in either: this call
556                  * returning with EINTR, or: this call returning ECHILD.
557                  */
558                 if (child_terminated)
559                         wait_status = child_wait_status;
560                 else
561                         packet_disconnect("wait: %.100s", strerror(errno));
562         } else {
563                 /* Check if it matches the process we forked. */
564                 if (wait_pid != pid)
565                         error("Strange, wait returned pid %d, expected %d",
566                                wait_pid, pid);
567         }
568
569         /* We no longer want our SIGCHLD handler to be called. */
570         signal(SIGCHLD, SIG_DFL);
571
572         /* Check if it exited normally. */
573         if (WIFEXITED(wait_status)) {
574                 /* Yes, normal exit.  Get exit status and send it to the client. */
575                 debug("Command exited with status %d.", WEXITSTATUS(wait_status));
576                 packet_start(SSH_SMSG_EXITSTATUS);
577                 packet_put_int(WEXITSTATUS(wait_status));
578                 packet_send();
579                 packet_write_wait();
580
581                 /*
582                  * Wait for exit confirmation.  Note that there might be
583                  * other packets coming before it; however, the program has
584                  * already died so we just ignore them.  The client is
585                  * supposed to respond with the confirmation when it receives
586                  * the exit status.
587                  */
588                 do {
589                         int plen;
590                         type = packet_read(&plen);
591                 }
592                 while (type != SSH_CMSG_EXIT_CONFIRMATION);
593
594                 debug("Received exit confirmation.");
595                 return;
596         }
597         /* Check if the program terminated due to a signal. */
598         if (WIFSIGNALED(wait_status))
599                 packet_disconnect("Command terminated on signal %d.",
600                                   WTERMSIG(wait_status));
601
602         /* Some weird exit cause.  Just exit. */
603         packet_disconnect("wait returned status %04x.", wait_status);
604         /* NOTREACHED */
605 }
606
607 void 
608 server_loop2(void)
609 {
610         fd_set readset, writeset;
611         int had_channel = 0;
612         int status;
613         pid_t pid;
614
615         debug("Entering interactive session for SSH2.");
616
617         signal(SIGCHLD, sigchld_handler2);
618         child_terminated = 0;
619         connection_in = packet_get_connection_in();
620         connection_out = packet_get_connection_out();
621         max_fd = connection_in;
622         if (connection_out > max_fd)
623                 max_fd = connection_out;
624         server_init_dispatch();
625
626         for (;;) {
627                 process_buffered_input_packets();
628                 if (!had_channel && channel_still_open())
629                         had_channel = 1;
630                 if (had_channel && !channel_still_open()) {
631                         debug("!channel_still_open.");
632                         break;
633                 }
634                 if (packet_not_very_much_data_to_write())
635                         channel_output_poll();
636                 wait_until_can_do_something(&readset, &writeset, 0);
637                 if (child_terminated) {
638                         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
639                                 session_close_by_pid(pid, status);
640                         child_terminated = 0;
641                 }
642                 channel_after_select(&readset, &writeset);
643                 process_input(&readset);
644                 process_output(&writeset);
645         }
646         signal(SIGCHLD, SIG_DFL);
647         while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
648                 session_close_by_pid(pid, status);
649         channel_stop_listening();
650 }
651
652 void
653 server_input_stdin_data(int type, int plen)
654 {
655         char *data;
656         unsigned int data_len;
657
658         /* Stdin data from the client.  Append it to the buffer. */
659         /* Ignore any data if the client has closed stdin. */
660         if (fdin == -1)
661                 return;
662         data = packet_get_string(&data_len);
663         packet_integrity_check(plen, (4 + data_len), type);
664         buffer_append(&stdin_buffer, data, data_len);
665         memset(data, 0, data_len);
666         xfree(data);
667 }
668
669 void
670 server_input_eof(int type, int plen)
671 {
672         /*
673          * Eof from the client.  The stdin descriptor to the
674          * program will be closed when all buffered data has
675          * drained.
676          */
677         debug("EOF received for stdin.");
678         packet_integrity_check(plen, 0, type);
679         stdin_eof = 1;
680 }
681
682 void
683 server_input_window_size(int type, int plen)
684 {
685         int row = packet_get_int();
686         int col = packet_get_int();
687         int xpixel = packet_get_int();
688         int ypixel = packet_get_int();
689
690         debug("Window change received.");
691         packet_integrity_check(plen, 4 * 4, type);
692         if (fdin != -1)
693                 pty_change_window_size(fdin, row, col, xpixel, ypixel);
694 }
695
696 int
697 input_direct_tcpip(void)
698 {
699         int sock;
700         char *host, *originator;
701         int host_port, originator_port;
702
703         host = packet_get_string(NULL);
704         host_port = packet_get_int();
705         originator = packet_get_string(NULL);
706         originator_port = packet_get_int();
707         /* XXX check permission */
708         sock = channel_connect_to(host, host_port);
709         xfree(host);
710         xfree(originator);
711         if (sock < 0)
712                 return -1;
713         return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
714             sock, sock, -1, 4*1024, 32*1024, 0, xstrdup("direct-tcpip"));
715 }
716
717 void 
718 server_input_channel_open(int type, int plen)
719 {
720         Channel *c = NULL;
721         char *ctype;
722         int id;
723         unsigned int len;
724         int rchan;
725         int rmaxpack;
726         int rwindow;
727
728         ctype = packet_get_string(&len);
729         rchan = packet_get_int();
730         rwindow = packet_get_int();
731         rmaxpack = packet_get_int();
732
733         log("channel_input_open: ctype %s rchan %d win %d max %d",
734             ctype, rchan, rwindow, rmaxpack);
735
736         if (strcmp(ctype, "session") == 0) {
737                 debug("open session");
738                 /*
739                  * A server session has no fd to read or write
740                  * until a CHANNEL_REQUEST for a shell is made,
741                  * so we set the type to SSH_CHANNEL_LARVAL.
742                  * Additionally, a callback for handling all
743                  * CHANNEL_REQUEST messages is registered.
744                  */
745                 id = channel_new(ctype, SSH_CHANNEL_LARVAL,
746                     -1, -1, -1, 0, 32*1024, 0, xstrdup("server-session"));
747                 if (session_open(id) == 1) {
748                         channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
749                             session_input_channel_req, (void *)0);
750                         channel_register_cleanup(id, session_close_by_channel);
751                         c = channel_lookup(id);
752                 } else {
753                         debug("session open failed, free channel %d", id);
754                         channel_free(id);
755                 }
756         } else if (strcmp(ctype, "direct-tcpip") == 0) {
757                 debug("open direct-tcpip");
758                 id = input_direct_tcpip();
759                 if (id >= 0)
760                         c = channel_lookup(id);
761         }
762         if (c != NULL) {
763                 debug("confirm %s", ctype);
764                 c->remote_id = rchan;
765                 c->remote_window = rwindow;
766                 c->remote_maxpacket = rmaxpack;
767
768                 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
769                 packet_put_int(c->remote_id);
770                 packet_put_int(c->self);
771                 packet_put_int(c->local_window);
772                 packet_put_int(c->local_maxpacket);
773                 packet_send();
774         } else {
775                 debug("failure %s", ctype);
776                 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
777                 packet_put_int(rchan);
778                 packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
779                 packet_put_cstring("bla bla");
780                 packet_put_cstring("");
781                 packet_send();
782         }
783         xfree(ctype);
784 }
785
786 void 
787 server_init_dispatch_20()
788 {
789         debug("server_init_dispatch_20");
790         dispatch_init(&dispatch_protocol_error);
791         dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
792         dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
793         dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
794         dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
795         dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
796         dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
797         dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
798         dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
799         dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
800 }
801 void 
802 server_init_dispatch_13()
803 {
804         debug("server_init_dispatch_13");
805         dispatch_init(NULL);
806         dispatch_set(SSH_CMSG_EOF, &server_input_eof);
807         dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
808         dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
809         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
810         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
811         dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
812         dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
813         dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
814         dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
815 }
816 void 
817 server_init_dispatch_15()
818 {
819         server_init_dispatch_13();
820         debug("server_init_dispatch_15");
821         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
822         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
823 }
824 void 
825 server_init_dispatch()
826 {
827         if (compat20)
828                 server_init_dispatch_20();
829         else if (compat13)
830                 server_init_dispatch_13();
831         else
832                 server_init_dispatch_15();
833 }
This page took 0.102353 seconds and 5 git commands to generate.