diff options
author | Damien Miller <djm@mindrot.org> | 2000-04-12 18:45:05 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-04-12 18:45:05 +1000 |
commit | efb4afe0265333ce554f699c2a19ae249dd8d1b5 (patch) | |
tree | 8fe5e0bb9791e7fa3d1788084ae669f7a9dcd2e0 /serverloop.c | |
parent | 11e37f638d3cc064371521001eaeb2d75bfe4a8d (diff) |
- More large OpenBSD CVS updates:
- [auth.c auth.h servconf.c servconf.h serverloop.c session.c]
[session.h ssh.h sshd.c README.openssh2]
ssh2 server side, see README.openssh2; enable with 'sshd -2'
- [channels.c]
no adjust after close
- [sshd.c compat.c ]
interop w/ latest ssh.com windows client.
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 192 |
1 files changed, 185 insertions, 7 deletions
diff --git a/serverloop.c b/serverloop.c index 8bf448ceb..0ea57faa0 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -5,6 +5,10 @@ | |||
5 | * Created: Sun Sep 10 00:30:37 1995 ylo | 5 | * Created: Sun Sep 10 00:30:37 1995 ylo |
6 | * Server main loop for handling the interactive session. | 6 | * Server main loop for handling the interactive session. |
7 | */ | 7 | */ |
8 | /* | ||
9 | * SSH2 support by Markus Friedl. | ||
10 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
11 | */ | ||
8 | 12 | ||
9 | #include "includes.h" | 13 | #include "includes.h" |
10 | #include "xmalloc.h" | 14 | #include "xmalloc.h" |
@@ -16,6 +20,8 @@ | |||
16 | #include "channels.h" | 20 | #include "channels.h" |
17 | 21 | ||
18 | #include "compat.h" | 22 | #include "compat.h" |
23 | #include "ssh2.h" | ||
24 | #include "session.h" | ||
19 | #include "dispatch.h" | 25 | #include "dispatch.h" |
20 | 26 | ||
21 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 27 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
@@ -72,6 +78,15 @@ sigchld_handler(int sig) | |||
72 | signal(SIGCHLD, sigchld_handler); | 78 | signal(SIGCHLD, sigchld_handler); |
73 | errno = save_errno; | 79 | errno = save_errno; |
74 | } | 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 | } | ||
75 | 90 | ||
76 | /* | 91 | /* |
77 | * Make packets from buffered stderr data, and buffer it for sending | 92 | * Make packets from buffered stderr data, and buffer it for sending |
@@ -154,15 +169,21 @@ retry_select: | |||
154 | * Read packets from the client unless we have too much buffered | 169 | * Read packets from the client unless we have too much buffered |
155 | * stdin or channel data. | 170 | * stdin or channel data. |
156 | */ | 171 | */ |
157 | if (buffer_len(&stdin_buffer) < 4096 && | 172 | if (compat20) { |
158 | channel_not_very_much_buffered_data()) | 173 | // wrong: bad conditionXXX |
159 | FD_SET(connection_in, readset); | 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 | } | ||
160 | 181 | ||
161 | /* | 182 | /* |
162 | * If there is not too much data already buffered going to the | 183 | * If there is not too much data already buffered going to the |
163 | * client, try to get some more data from the program. | 184 | * client, try to get some more data from the program. |
164 | */ | 185 | */ |
165 | if (packet_not_very_much_data_to_write()) { | 186 | if (!compat20 && packet_not_very_much_data_to_write()) { |
166 | if (!fdout_eof) | 187 | if (!fdout_eof) |
167 | FD_SET(fdout, readset); | 188 | FD_SET(fdout, readset); |
168 | if (!fderr_eof) | 189 | if (!fderr_eof) |
@@ -182,7 +203,7 @@ retry_select: | |||
182 | 203 | ||
183 | /* If we have buffered data, try to write some of that data to the | 204 | /* If we have buffered data, try to write some of that data to the |
184 | program. */ | 205 | program. */ |
185 | if (fdin != -1 && buffer_len(&stdin_buffer) > 0) | 206 | if (!compat20 && fdin != -1 && buffer_len(&stdin_buffer) > 0) |
186 | FD_SET(fdin, writeset); | 207 | FD_SET(fdin, writeset); |
187 | 208 | ||
188 | /* Update the maximum descriptor number if appropriate. */ | 209 | /* Update the maximum descriptor number if appropriate. */ |
@@ -204,6 +225,8 @@ retry_select: | |||
204 | tv.tv_usec = 1000 * (max_time_milliseconds % 1000); | 225 | tv.tv_usec = 1000 * (max_time_milliseconds % 1000); |
205 | tvp = &tv; | 226 | tvp = &tv; |
206 | } | 227 | } |
228 | if (tvp!=NULL) | ||
229 | debug("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds); | ||
207 | 230 | ||
208 | /* Wait for something to happen, or the timeout to expire. */ | 231 | /* Wait for something to happen, or the timeout to expire. */ |
209 | ret = select(max_fd + 1, readset, writeset, NULL, tvp); | 232 | ret = select(max_fd + 1, readset, writeset, NULL, tvp); |
@@ -250,6 +273,9 @@ process_input(fd_set * readset) | |||
250 | /* Buffer any received data. */ | 273 | /* Buffer any received data. */ |
251 | packet_process_incoming(buf, len); | 274 | packet_process_incoming(buf, len); |
252 | } | 275 | } |
276 | if (compat20) | ||
277 | return; | ||
278 | |||
253 | /* Read and buffer any available stdout data from the program. */ | 279 | /* Read and buffer any available stdout data from the program. */ |
254 | if (!fdout_eof && FD_ISSET(fdout, readset)) { | 280 | if (!fdout_eof && FD_ISSET(fdout, readset)) { |
255 | len = read(fdout, buf, sizeof(buf)); | 281 | len = read(fdout, buf, sizeof(buf)); |
@@ -279,7 +305,7 @@ process_output(fd_set * writeset) | |||
279 | int len; | 305 | int len; |
280 | 306 | ||
281 | /* Write buffered data to program stdin. */ | 307 | /* Write buffered data to program stdin. */ |
282 | if (fdin != -1 && FD_ISSET(fdin, writeset)) { | 308 | if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { |
283 | len = write(fdin, buffer_ptr(&stdin_buffer), | 309 | len = write(fdin, buffer_ptr(&stdin_buffer), |
284 | buffer_len(&stdin_buffer)); | 310 | buffer_len(&stdin_buffer)); |
285 | if (len <= 0) { | 311 | if (len <= 0) { |
@@ -578,6 +604,51 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
578 | /* NOTREACHED */ | 604 | /* NOTREACHED */ |
579 | } | 605 | } |
580 | 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 | |||
581 | void | 652 | void |
582 | server_input_stdin_data(int type, int plen) | 653 | server_input_stdin_data(int type, int plen) |
583 | { | 654 | { |
@@ -622,6 +693,111 @@ server_input_window_size(int type, int plen) | |||
622 | pty_change_window_size(fdin, row, col, xpixel, ypixel); | 693 | pty_change_window_size(fdin, row, col, xpixel, ypixel); |
623 | } | 694 | } |
624 | 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 | } | ||
625 | void | 801 | void |
626 | server_init_dispatch_13() | 802 | server_init_dispatch_13() |
627 | { | 803 | { |
@@ -648,7 +824,9 @@ server_init_dispatch_15() | |||
648 | void | 824 | void |
649 | server_init_dispatch() | 825 | server_init_dispatch() |
650 | { | 826 | { |
651 | if (compat13) | 827 | if (compat20) |
828 | server_init_dispatch_20(); | ||
829 | else if (compat13) | ||
652 | server_init_dispatch_13(); | 830 | server_init_dispatch_13(); |
653 | else | 831 | else |
654 | server_init_dispatch_15(); | 832 | server_init_dispatch_15(); |