]> andersk Git - openssh.git/blobdiff - channels.c
- (tim) [configure.ac sshd.8] Enable locked account check (a "*LK*" string)
[openssh.git] / channels.c
index 3f6db60c6fc6408cf5033078ccec37f68d86cf27..9607717cc15dc44b59b37697816423414d11d77b 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.214 2005/03/14 11:46:56 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.227 2005/10/14 02:29:37 stevesk Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -111,6 +111,9 @@ static int all_opens_permitted = 0;
 /* Maximum number of fake X11 displays to try. */
 #define MAX_DISPLAYS  1000
 
+/* Saved X11 local (client) display. */
+static char *x11_saved_display = NULL;
+
 /* Saved X11 authentication protocol name. */
 static char *x11_saved_proto = NULL;
 
@@ -266,6 +269,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
        c->force_drain = 0;
        c->single_connection = 0;
        c->detach_user = NULL;
+       c->detach_close = 0;
        c->confirm = NULL;
        c->confirm_ctx = NULL;
        c->input_filter = NULL;
@@ -625,7 +629,7 @@ channel_register_confirm(int id, channel_callback_fn *fn, void *ctx)
        c->confirm_ctx = ctx;
 }
 void
-channel_register_cleanup(int id, channel_callback_fn *fn)
+channel_register_cleanup(int id, channel_callback_fn *fn, int do_close)
 {
        Channel *c = channel_lookup(id);
 
@@ -634,6 +638,7 @@ channel_register_cleanup(int id, channel_callback_fn *fn)
                return;
        }
        c->detach_user = fn;
+       c->detach_close = do_close;
 }
 void
 channel_cancel_cleanup(int id)
@@ -645,6 +650,7 @@ channel_cancel_cleanup(int id)
                return;
        }
        c->detach_user = NULL;
+       c->detach_close = 0;
 }
 void
 channel_register_filter(int id, channel_filter_fn *fn)
@@ -727,8 +733,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
                        FD_SET(c->wfd, writeset);
                } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                        if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
-                              debug2("channel %d: obuf_empty delayed efd %d/(%d)",
-                                  c->self, c->efd, buffer_len(&c->extended));
+                               debug2("channel %d: obuf_empty delayed efd %d/(%d)",
+                                   c->self, c->efd, buffer_len(&c->extended));
                        else
                                chan_obuf_empty(c);
                }
@@ -894,7 +900,7 @@ static int
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
 {
        char *p, *host;
-       int len, have, i, found;
+       u_int len, have, i, found;
        char username[256];
        struct {
                u_int8_t version;
@@ -979,7 +985,7 @@ channel_decode_socks5(Channel *c, fd_set * readset, fd_set * writeset)
        } s5_req, s5_rsp;
        u_int16_t dest_port;
        u_char *p, dest_addr[255+1];
-       int i, have, found, nmethods, addrlen, af;
+       u_int have, i, found, nmethods, addrlen, af;
 
        debug2("channel %d: decode socks5", c->self);
        p = buffer_ptr(&c->input);
@@ -1075,7 +1081,8 @@ static void
 channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset)
 {
        u_char *p;
-       int have, ret;
+       u_int have;
+       int ret;
 
        have = buffer_len(&c->input);
        c->delayed = 0;
@@ -1178,7 +1185,7 @@ port_open_helper(Channel *c, char *rtype)
        int direct;
        char buf[1024];
        char *remote_ipaddr = get_peer_ipaddr(c->sock);
-       u_short remote_port = get_peer_port(c->sock);
+       int remote_port = get_peer_port(c->sock);
 
        direct = (strcmp(rtype, "direct-tcpip") == 0);
 
@@ -1208,7 +1215,7 @@ port_open_helper(Channel *c, char *rtype)
                }
                /* originator host and port */
                packet_put_cstring(remote_ipaddr);
-               packet_put_int(remote_port);
+               packet_put_int((u_int)remote_port);
                packet_send();
        } else {
                packet_start(SSH_MSG_PORT_OPEN);
@@ -1223,6 +1230,19 @@ port_open_helper(Channel *c, char *rtype)
        xfree(remote_ipaddr);
 }
 
+static void
+channel_set_reuseaddr(int fd)
+{
+       int on = 1;
+
+       /*
+        * Set socket options.
+        * Allow local port reuse in TIME_WAIT.
+        */
+       if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
+               error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
+}
+
 /*
  * This socket is listening for connections to a forwarded TCP/IP port.
  */
@@ -1662,7 +1682,7 @@ channel_garbage_collect(Channel *c)
        if (c == NULL)
                return;
        if (c->detach_user != NULL) {
-               if (!chan_is_dead(c, 0))
+               if (!chan_is_dead(c, c->detach_close))
                        return;
                debug2("channel %d: gc: notify user", c->self);
                c->detach_user(c->self, NULL);
@@ -1809,8 +1829,8 @@ channel_output_poll(void)
                         * hack for extended data: delay EOF if EFD still in use.
                         */
                        if (CHANNEL_EFD_INPUT_ACTIVE(c))
-                              debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
-                                  c->self, c->efd, buffer_len(&c->extended));
+                               debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
+                                   c->self, c->efd, buffer_len(&c->extended));
                        else
                                chan_ibuf_empty(c);
                }
@@ -2184,7 +2204,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
     const char *host_to_connect, u_short port_to_connect, int gateway_ports)
 {
        Channel *c;
-       int sock, r, success = 0, on = 1, wildcard = 0, is_client;
+       int sock, r, success = 0, wildcard = 0, is_client;
        struct addrinfo hints, *ai, *aitop;
        const char *host, *addr;
        char ntop[NI_MAXHOST], strport[NI_MAXSERV];
@@ -2195,11 +2215,11 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
 
        if (host == NULL) {
                error("No forward host name.");
-               return success;
+               return 0;
        }
        if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) {
                error("Forward host name too long.");
-               return success;
+               return 0;
        }
 
        /*
@@ -2250,12 +2270,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                        packet_disconnect("getaddrinfo: fatal error: %s",
                            gai_strerror(r));
                } else {
-                       verbose("channel_setup_fwd_listener: "
-                           "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
-                       packet_send_debug("channel_setup_fwd_listener: "
+                       error("channel_setup_fwd_listener: "
                            "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
                }
-               aitop = NULL;
+               return 0;
        }
 
        for (ai = aitop; ai; ai = ai->ai_next) {
@@ -2273,13 +2291,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
                        verbose("socket: %.100s", strerror(errno));
                        continue;
                }
-               /*
-                * Set socket options.
-                * Allow local port reuse in TIME_WAIT.
-                */
-               if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
-                   sizeof(on)) == -1)
-                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               channel_set_reuseaddr(sock);
 
                debug("Local forwarding listening on %s port %s.", ntop, strport);
 
@@ -2451,7 +2464,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
 
        permitted_opens[i].listen_port = 0;
        permitted_opens[i].port_to_connect = 0;
-       free(permitted_opens[i].host_to_connect);
+       xfree(permitted_opens[i].host_to_connect);
        permitted_opens[i].host_to_connect = NULL;
 }
 
@@ -2657,7 +2670,7 @@ channel_send_window_changes(void)
  */
 int
 x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
-    int single_connection, u_int *display_numberp)
+    int single_connection, u_int *display_numberp, int **chanids)
 {
        Channel *nc = NULL;
        int display_number, sock;
@@ -2666,6 +2679,9 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
        char strport[NI_MAXSERV];
        int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
 
+       if (chanids == NULL)
+               return -1;
+
        for (display_number = x11_display_offset;
            display_number < MAX_DISPLAYS;
            display_number++) {
@@ -2702,6 +2718,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
                                        error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
                        }
 #endif
+                       channel_set_reuseaddr(sock);
                        if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                                debug2("bind port %d: %.100s", port, strerror(errno));
                                close(sock);
@@ -2747,6 +2764,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
        }
 
        /* Allocate a channel for each socket. */
+       *chanids = xmalloc(sizeof(**chanids) * (num_socks + 1));
        for (n = 0; n < num_socks; n++) {
                sock = socks[n];
                nc = channel_new("x11 listener",
@@ -2754,7 +2772,9 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
                    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
                    0, "X11 inet listener", 1);
                nc->single_connection = single_connection;
+               (*chanids)[n] = nc->self;
        }
+       (*chanids)[n] = -1;
 
        /* Return the display number for the DISPLAY environment variable. */
        *display_numberp = display_number;
@@ -2952,19 +2972,27 @@ deny_input_open(int type, u_int32_t seq, void *ctxt)
  * This should be called in the client only.
  */
 void
-x11_request_forwarding_with_spoofing(int client_session_id,
+x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
     const char *proto, const char *data)
 {
        u_int data_len = (u_int) strlen(data) / 2;
-       u_int i, value, len;
+       u_int i, value;
        char *new_data;
        int screen_number;
        const char *cp;
        u_int32_t rnd = 0;
 
-       cp = getenv("DISPLAY");
-       if (cp)
-               cp = strchr(cp, ':');
+       if (x11_saved_display == NULL)
+               x11_saved_display = xstrdup(disp);
+       else if (strcmp(disp, x11_saved_display) != 0) {
+               error("x11_request_forwarding_with_spoofing: different "
+                   "$DISPLAY already forwarded");
+               return;
+       }
+
+       cp = disp;
+       if (disp)
+               cp = strchr(disp, ':');
        if (cp)
                cp = strchr(cp, '.');
        if (cp)
@@ -2972,33 +3000,31 @@ x11_request_forwarding_with_spoofing(int client_session_id,
        else
                screen_number = 0;
 
-       /* Save protocol name. */
-       x11_saved_proto = xstrdup(proto);
-
-       /*
-        * Extract real authentication data and generate fake data of the
-        * same length.
-        */
-       x11_saved_data = xmalloc(data_len);
-       x11_fake_data = xmalloc(data_len);
-       for (i = 0; i < data_len; i++) {
-               if (sscanf(data + 2 * i, "%2x", &value) != 1)
-                       fatal("x11_request_forwarding: bad authentication data: %.100s", data);
-               if (i % 4 == 0)
-                       rnd = arc4random();
-               x11_saved_data[i] = value;
-               x11_fake_data[i] = rnd & 0xff;
-               rnd >>= 8;
-       }
-       x11_saved_data_len = data_len;
-       x11_fake_data_len = data_len;
+       if (x11_saved_proto == NULL) {
+               /* Save protocol name. */
+               x11_saved_proto = xstrdup(proto);
+               /*
+                * Extract real authentication data and generate fake data
+                * of the same length.
+                */
+               x11_saved_data = xmalloc(data_len);
+               x11_fake_data = xmalloc(data_len);
+               for (i = 0; i < data_len; i++) {
+                       if (sscanf(data + 2 * i, "%2x", &value) != 1)
+                               fatal("x11_request_forwarding: bad "
+                                   "authentication data: %.100s", data);
+                       if (i % 4 == 0)
+                               rnd = arc4random();
+                       x11_saved_data[i] = value;
+                       x11_fake_data[i] = rnd & 0xff;
+                       rnd >>= 8;
+               }
+               x11_saved_data_len = data_len;
+               x11_fake_data_len = data_len;
+       }
 
        /* Convert the fake data into hex. */
-       len = 2 * data_len + 1;
-       new_data = xmalloc(len);
-       for (i = 0; i < data_len; i++)
-               snprintf(new_data + 2 * i, len - 2 * i,
-                   "%02x", (u_char) x11_fake_data[i]);
+       new_data = tohex(x11_fake_data, data_len);
 
        /* Send the request packet. */
        if (compat20) {
This page took 0.046796 seconds and 4 git commands to generate.