summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/serverloop.c b/serverloop.c
index 29ffcfee1..6a3e2af10 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.145 2006/10/11 12:38:03 markus Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.153 2008/06/30 12:15:39 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -56,6 +56,7 @@
56#include <unistd.h> 56#include <unistd.h>
57#include <stdarg.h> 57#include <stdarg.h>
58 58
59#include "openbsd-compat/sys-queue.h"
59#include "xmalloc.h" 60#include "xmalloc.h"
60#include "packet.h" 61#include "packet.h"
61#include "buffer.h" 62#include "buffer.h"
@@ -104,7 +105,7 @@ static int connection_in; /* Connection to client (input). */
104static int connection_out; /* Connection to client (output). */ 105static int connection_out; /* Connection to client (output). */
105static int connection_closed = 0; /* Connection to client closed. */ 106static int connection_closed = 0; /* Connection to client closed. */
106static u_int buffer_high; /* "Soft" max buffer size. */ 107static u_int buffer_high; /* "Soft" max buffer size. */
107static int client_alive_timeouts = 0; 108static int no_more_sessions = 0; /* Disallow further sessions. */
108 109
109/* 110/*
110 * This SIGCHLD kludge is used to detect when the child exits. The server 111 * This SIGCHLD kludge is used to detect when the child exits. The server
@@ -248,7 +249,7 @@ client_alive_check(void)
248 int channel_id; 249 int channel_id;
249 250
250 /* timeout, check to see how many we have had */ 251 /* timeout, check to see how many we have had */
251 if (++client_alive_timeouts > options.client_alive_count_max) { 252 if (++keep_alive_timeouts > options.client_alive_count_max) {
252 logit("Timeout, client not responding."); 253 logit("Timeout, client not responding.");
253 cleanup_exit(255); 254 cleanup_exit(255);
254 } 255 }
@@ -399,7 +400,8 @@ process_input(fd_set *readset)
399 return; 400 return;
400 cleanup_exit(255); 401 cleanup_exit(255);
401 } else if (len < 0) { 402 } else if (len < 0) {
402 if (errno != EINTR && errno != EAGAIN) { 403 if (errno != EINTR && errno != EAGAIN &&
404 errno != EWOULDBLOCK) {
403 verbose("Read error from remote host " 405 verbose("Read error from remote host "
404 "%.100s: %.100s", 406 "%.100s: %.100s",
405 get_remote_ipaddr(), strerror(errno)); 407 get_remote_ipaddr(), strerror(errno));
@@ -417,8 +419,8 @@ process_input(fd_set *readset)
417 if (!fdout_eof && FD_ISSET(fdout, readset)) { 419 if (!fdout_eof && FD_ISSET(fdout, readset)) {
418 errno = 0; 420 errno = 0;
419 len = read(fdout, buf, sizeof(buf)); 421 len = read(fdout, buf, sizeof(buf));
420 if (len < 0 && (errno == EINTR || 422 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
421 (errno == EAGAIN && !child_terminated))) { 423 errno == EWOULDBLOCK) && !child_terminated))) {
422 /* do nothing */ 424 /* do nothing */
423#ifndef PTY_ZEROREAD 425#ifndef PTY_ZEROREAD
424 } else if (len <= 0) { 426 } else if (len <= 0) {
@@ -436,8 +438,8 @@ process_input(fd_set *readset)
436 if (!fderr_eof && FD_ISSET(fderr, readset)) { 438 if (!fderr_eof && FD_ISSET(fderr, readset)) {
437 errno = 0; 439 errno = 0;
438 len = read(fderr, buf, sizeof(buf)); 440 len = read(fderr, buf, sizeof(buf));
439 if (len < 0 && (errno == EINTR || 441 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
440 (errno == EAGAIN && !child_terminated))) { 442 errno == EWOULDBLOCK) && !child_terminated))) {
441 /* do nothing */ 443 /* do nothing */
442#ifndef PTY_ZEROREAD 444#ifndef PTY_ZEROREAD
443 } else if (len <= 0) { 445 } else if (len <= 0) {
@@ -468,7 +470,8 @@ process_output(fd_set *writeset)
468 data = buffer_ptr(&stdin_buffer); 470 data = buffer_ptr(&stdin_buffer);
469 dlen = buffer_len(&stdin_buffer); 471 dlen = buffer_len(&stdin_buffer);
470 len = write(fdin, data, dlen); 472 len = write(fdin, data, dlen);
471 if (len < 0 && (errno == EINTR || errno == EAGAIN)) { 473 if (len < 0 &&
474 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
472 /* do nothing */ 475 /* do nothing */
473 } else if (len <= 0) { 476 } else if (len <= 0) {
474 if (fdin != fdout) 477 if (fdin != fdout)
@@ -887,7 +890,7 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
887 * even if this was generated by something other than 890 * even if this was generated by something other than
888 * the bogus CHANNEL_REQUEST we send for keepalives. 891 * the bogus CHANNEL_REQUEST we send for keepalives.
889 */ 892 */
890 client_alive_timeouts = 0; 893 keep_alive_timeouts = 0;
891} 894}
892 895
893static void 896static void
@@ -938,7 +941,6 @@ static Channel *
938server_request_direct_tcpip(void) 941server_request_direct_tcpip(void)
939{ 942{
940 Channel *c; 943 Channel *c;
941 int sock;
942 char *target, *originator; 944 char *target, *originator;
943 int target_port, originator_port; 945 int target_port, originator_port;
944 946
@@ -948,18 +950,16 @@ server_request_direct_tcpip(void)
948 originator_port = packet_get_int(); 950 originator_port = packet_get_int();
949 packet_check_eom(); 951 packet_check_eom();
950 952
951 debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", 953 debug("server_request_direct_tcpip: originator %s port %d, target %s "
952 originator, originator_port, target, target_port); 954 "port %d", originator, originator_port, target, target_port);
953 955
954 /* XXX check permission */ 956 /* XXX check permission */
955 sock = channel_connect_to(target, target_port); 957 c = channel_connect_to(target, target_port,
956 xfree(target); 958 "direct-tcpip", "direct-tcpip");
959
957 xfree(originator); 960 xfree(originator);
958 if (sock < 0) 961 xfree(target);
959 return NULL; 962
960 c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
961 sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
962 CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
963 return c; 963 return c;
964} 964}
965 965
@@ -1000,7 +1000,7 @@ server_request_tun(void)
1000#if defined(SSH_TUN_FILTER) 1000#if defined(SSH_TUN_FILTER)
1001 if (mode == SSH_TUNMODE_POINTOPOINT) 1001 if (mode == SSH_TUNMODE_POINTOPOINT)
1002 channel_register_filter(c->self, sys_tun_infilter, 1002 channel_register_filter(c->self, sys_tun_infilter,
1003 sys_tun_outfilter); 1003 sys_tun_outfilter, NULL, NULL);
1004#endif 1004#endif
1005 1005
1006 done: 1006 done:
@@ -1016,6 +1016,12 @@ server_request_session(void)
1016 1016
1017 debug("input_session_request"); 1017 debug("input_session_request");
1018 packet_check_eom(); 1018 packet_check_eom();
1019
1020 if (no_more_sessions) {
1021 packet_disconnect("Possible attack: attempt to open a session "
1022 "after additional sessions disabled");
1023 }
1024
1019 /* 1025 /*
1020 * A server session has no fd to read or write until a 1026 * A server session has no fd to read or write until a
1021 * CHANNEL_REQUEST for a shell is made, so we set the type to 1027 * CHANNEL_REQUEST for a shell is made, so we set the type to
@@ -1136,6 +1142,9 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1136 success = channel_cancel_rport_listener(cancel_address, 1142 success = channel_cancel_rport_listener(cancel_address,
1137 cancel_port); 1143 cancel_port);
1138 xfree(cancel_address); 1144 xfree(cancel_address);
1145 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
1146 no_more_sessions = 1;
1147 success = 1;
1139 } 1148 }
1140 if (want_reply) { 1149 if (want_reply) {
1141 packet_start(success ? 1150 packet_start(success ?
@@ -1163,7 +1172,11 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt)
1163 if ((c = channel_lookup(id)) == NULL) 1172 if ((c = channel_lookup(id)) == NULL)
1164 packet_disconnect("server_input_channel_req: " 1173 packet_disconnect("server_input_channel_req: "
1165 "unknown channel %d", id); 1174 "unknown channel %d", id);
1166 if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) 1175 if (!strcmp(rtype, "eow@openssh.com")) {
1176 packet_check_eom();
1177 chan_rcvd_eow(c);
1178 } else if ((c->type == SSH_CHANNEL_LARVAL ||
1179 c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
1167 success = session_input_channel_req(c, rtype); 1180 success = session_input_channel_req(c, rtype);
1168 if (reply) { 1181 if (reply) {
1169 packet_start(success ? 1182 packet_start(success ?
@@ -1189,8 +1202,9 @@ server_init_dispatch_20(void)
1189 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req); 1202 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
1190 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); 1203 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1191 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); 1204 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
1205 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
1206 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
1192 /* client_alive */ 1207 /* client_alive */
1193 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
1194 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive); 1208 dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
1195 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive); 1209 dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
1196 /* rekeying */ 1210 /* rekeying */