]> andersk Git - openssh.git/blobdiff - channels.c
- (tim) [configure.ac] Autoconf didn't define HAVE_LIBIAF because we
[openssh.git] / channels.c
index 55506725550ac4a0c1514d71860163eec137d272..2006353d40e769e62d885f9b67973e6942eb4645 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.254 2006/07/11 20:07:25 stevesk Exp $ */
+/* $OpenBSD: channels.c,v 1.270 2007/06/25 08:20:03 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 
 #include "includes.h"
 
-#include <sys/ioctl.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #include <sys/un.h>
 #include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <termios.h>
+#include <unistd.h>
+#include <stdarg.h>
 
+#include "xmalloc.h"
 #include "ssh.h"
 #include "ssh1.h"
 #include "ssh2.h"
 #include "packet.h"
-#include "xmalloc.h"
 #include "log.h"
 #include "misc.h"
+#include "buffer.h"
 #include "channels.h"
 #include "compat.h"
 #include "canohost.h"
 #include "key.h"
 #include "authfd.h"
 #include "pathnames.h"
-#include "bufaux.h"
 
 /* -- channel core */
 
@@ -102,11 +111,18 @@ typedef struct {
        u_short listen_port;            /* Remote side should listen port number. */
 } ForwardPermission;
 
-/* List of all permitted host/port pairs to connect. */
+/* List of all permitted host/port pairs to connect by the user. */
 static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
 
-/* Number of permitted host/port pairs in the array. */
+/* List of all permitted host/port pairs to connect by the admin. */
+static ForwardPermission permitted_adm_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
+
+/* Number of permitted host/port pairs in the array permitted by the user. */
 static int num_permitted_opens = 0;
+
+/* Number of permitted host/port pair in the array permitted by the admin. */
+static int num_adm_permitted_opens = 0;
+
 /*
  * If this is true, all opens are permitted.  This is the case on the server
  * on which we have to trust the client anyway, and the user could do
@@ -725,12 +741,14 @@ typedef void chan_fn(Channel *c, fd_set *readset, fd_set *writeset);
 chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];
 chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];
 
+/* ARGSUSED */
 static void
 channel_pre_listener(Channel *c, fd_set *readset, fd_set *writeset)
 {
        FD_SET(c->sock, readset);
 }
 
+/* ARGSUSED */
 static void
 channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -785,6 +803,7 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
                FD_SET(c->ctl_fd, readset);
 }
 
+/* ARGSUSED */
 static void
 channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -797,6 +816,7 @@ channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset)
        }
 }
 
+/* ARGSUSED */
 static void
 channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -926,6 +946,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
 }
 
 /* try to decode a socks4 header */
+/* ARGSUSED */
 static int
 channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1004,6 +1025,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
 #define SSH_SOCKS5_CONNECT     0x01
 #define SSH_SOCKS5_SUCCESS     0x00
 
+/* ARGSUSED */
 static int
 channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1030,8 +1052,8 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
                if (have < nmethods + 2)
                        return 0;
                /* look for method: "NO AUTHENTICATION REQUIRED" */
-               for (found = 0, i = 2 ; i < nmethods + 2; i++) {
-                       if (p[i] == SSH_SOCKS5_NOAUTH ) {
+               for (found = 0, i = 2; i < nmethods + 2; i++) {
+                       if (p[i] == SSH_SOCKS5_NOAUTH) {
                                found = 1;
                                break;
                        }
@@ -1154,6 +1176,7 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
 }
 
 /* This is our fake X11 server socket. */
+/* ARGSUSED */
 static void
 channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1279,6 +1302,7 @@ channel_set_reuseaddr(int fd)
 /*
  * This socket is listening for connections to a forwarded TCP/IP port.
  */
+/* ARGSUSED */
 static void
 channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1336,6 +1360,7 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
  * This is the authentication agent socket listening for connections from
  * clients.
  */
+/* ARGSUSED */
 static void
 channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1369,6 +1394,7 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
        }
 }
 
+/* ARGSUSED */
 static void
 channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1415,17 +1441,18 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
        }
 }
 
+/* ARGSUSED */
 static int
 channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
 {
        char buf[CHAN_RBUF];
-       int len;
+       int len, force;
 
-       if (c->rfd != -1 &&
-           FD_ISSET(c->rfd, readset)) {
+       force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
+       if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
                errno = 0;
                len = read(c->rfd, buf, sizeof(buf));
-               if (len < 0 && (errno == EINTR || errno == EAGAIN))
+               if (len < 0 && (errno == EINTR || (errno == EAGAIN && !force)))
                        return 1;
 #ifndef PTY_ZEROREAD
                if (len <= 0) {
@@ -1462,6 +1489,7 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
        return 1;
 }
 
+/* ARGSUSED */
 static int
 channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1576,11 +1604,12 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
                                c->local_consumed += len;
                        }
                } else if (c->extended_usage == CHAN_EXTENDED_READ &&
-                   FD_ISSET(c->efd, readset)) {
+                   (c->detach_close || FD_ISSET(c->efd, readset))) {
                        len = read(c->efd, buf, sizeof(buf));
                        debug2("channel %d: read %d from efd %d",
                            c->self, len, c->efd);
-                       if (len < 0 && (errno == EINTR || errno == EAGAIN))
+                       if (len < 0 && (errno == EINTR ||
+                           (errno == EAGAIN && !c->detach_close)))
                                return 1;
                        if (len <= 0) {
                                debug2("channel %d: closing read-efd %d",
@@ -1594,6 +1623,7 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
        return 1;
 }
 
+/* ARGSUSED */
 static int
 channel_handle_ctl(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -1627,7 +1657,9 @@ channel_check_window(Channel *c)
 {
        if (c->type == SSH_CHANNEL_OPEN &&
            !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
-           c->local_window < c->local_window_max/2 &&
+           ((c->local_window_max - c->local_window >
+           c->local_maxpacket*3) ||
+           c->local_window < c->local_window_max/2) &&
            c->local_consumed > 0) {
                packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
                packet_put_int(c->remote_id);
@@ -1656,6 +1688,7 @@ channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
        channel_check_window(c);
 }
 
+/* ARGSUSED */
 static void
 channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
 {
@@ -2495,11 +2528,18 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
        /* Send the forward request to the remote side. */
        if (compat20) {
                const char *address_to_bind;
-               if (listen_host == NULL)
-                       address_to_bind = "localhost";
-               else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0)
-                       address_to_bind = "";
-               else
+               if (listen_host == NULL) {
+                       if (datafellows & SSH_BUG_RFWD_ADDR)
+                               address_to_bind = "127.0.0.1";
+                       else
+                               address_to_bind = "localhost";
+               } else if (*listen_host == '\0' ||
+                          strcmp(listen_host, "*") == 0) {
+                       if (datafellows & SSH_BUG_RFWD_ADDR)
+                               address_to_bind = "0.0.0.0";
+                       else
+                               address_to_bind = "";
+               } else
                        address_to_bind = listen_host;
 
                packet_start(SSH2_MSG_GLOBAL_REQUEST);
@@ -2642,6 +2682,19 @@ channel_add_permitted_opens(char *host, int port)
        all_opens_permitted = 0;
 }
 
+int
+channel_add_adm_permitted_opens(char *host, int port)
+{
+       if (num_adm_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
+               fatal("channel_add_adm_permitted_opens: too many forwards");
+       debug("config allows port forwarding to host %s port %d", host, port);
+
+       permitted_adm_opens[num_adm_permitted_opens].host_to_connect
+            = xstrdup(host);
+       permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
+       return ++num_adm_permitted_opens;
+}
+
 void
 channel_clear_permitted_opens(void)
 {
@@ -2651,7 +2704,17 @@ channel_clear_permitted_opens(void)
                if (permitted_opens[i].host_to_connect != NULL)
                        xfree(permitted_opens[i].host_to_connect);
        num_permitted_opens = 0;
+}
+
+void
+channel_clear_adm_permitted_opens(void)
+{
+       int i;
 
+       for (i = 0; i < num_adm_permitted_opens; i++)
+               if (permitted_adm_opens[i].host_to_connect != NULL)
+                       xfree(permitted_adm_opens[i].host_to_connect);
+       num_adm_permitted_opens = 0;
 }
 
 /* return socket to remote host, port */
@@ -2730,7 +2793,7 @@ channel_connect_by_listen_address(u_short listen_port)
 int
 channel_connect_to(const char *host, u_short port)
 {
-       int i, permit;
+       int i, permit, permit_adm = 1;
 
        permit = all_opens_permitted;
        if (!permit) {
@@ -2739,9 +2802,19 @@ channel_connect_to(const char *host, u_short port)
                            permitted_opens[i].port_to_connect == port &&
                            strcmp(permitted_opens[i].host_to_connect, host) == 0)
                                permit = 1;
+       }
 
+       if (num_adm_permitted_opens > 0) {
+               permit_adm = 0;
+               for (i = 0; i < num_adm_permitted_opens; i++)
+                       if (permitted_adm_opens[i].host_to_connect != NULL &&
+                           permitted_adm_opens[i].port_to_connect == port &&
+                           strcmp(permitted_adm_opens[i].host_to_connect, host)
+                           == 0)
+                               permit_adm = 1;
        }
-       if (!permit) {
+
+       if (!permit || !permit_adm) {
                logit("Received request to connect to host %.100s port %d, "
                    "but the request was denied.", host, port);
                return -1;
@@ -3010,6 +3083,7 @@ x11_connect_display(void)
  * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
  */
 
+/* ARGSUSED */
 void
 x11_input_open(int type, u_int32_t seq, void *ctxt)
 {
@@ -3053,6 +3127,7 @@ x11_input_open(int type, u_int32_t seq, void *ctxt)
 }
 
 /* dummy protocol handler that denies SSH-1 requests (agent/x11) */
+/* ARGSUSED */
 void
 deny_input_open(int type, u_int32_t seq, void *ctxt)
 {
@@ -3099,9 +3174,7 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
                return;
        }
 
-       cp = disp;
-       if (disp)
-               cp = strchr(disp, ':');
+       cp = strchr(disp, ':');
        if (cp)
                cp = strchr(cp, '.');
        if (cp)
This page took 0.048902 seconds and 4 git commands to generate.