diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 133 |
1 files changed, 76 insertions, 57 deletions
diff --git a/channels.c b/channels.c index 1be213bce..8c7b2b369 100644 --- a/channels.c +++ b/channels.c | |||
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: channels.c,v 1.212 2005/03/01 10:09:52 djm Exp $"); | 42 | RCSID("$OpenBSD: channels.c,v 1.223 2005/07/17 07:17:54 djm Exp $"); |
43 | 43 | ||
44 | #include "ssh.h" | 44 | #include "ssh.h" |
45 | #include "ssh1.h" | 45 | #include "ssh1.h" |
@@ -58,6 +58,8 @@ RCSID("$OpenBSD: channels.c,v 1.212 2005/03/01 10:09:52 djm Exp $"); | |||
58 | 58 | ||
59 | /* -- channel core */ | 59 | /* -- channel core */ |
60 | 60 | ||
61 | #define CHAN_RBUF 16*1024 | ||
62 | |||
61 | /* | 63 | /* |
62 | * Pointer to an array containing all allocated channels. The array is | 64 | * Pointer to an array containing all allocated channels. The array is |
63 | * dynamically extended as needed. | 65 | * dynamically extended as needed. |
@@ -109,6 +111,9 @@ static int all_opens_permitted = 0; | |||
109 | /* Maximum number of fake X11 displays to try. */ | 111 | /* Maximum number of fake X11 displays to try. */ |
110 | #define MAX_DISPLAYS 1000 | 112 | #define MAX_DISPLAYS 1000 |
111 | 113 | ||
114 | /* Saved X11 local (client) display. */ | ||
115 | static char *x11_saved_display = NULL; | ||
116 | |||
112 | /* Saved X11 authentication protocol name. */ | 117 | /* Saved X11 authentication protocol name. */ |
113 | static char *x11_saved_proto = NULL; | 118 | static char *x11_saved_proto = NULL; |
114 | 119 | ||
@@ -712,6 +717,9 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
712 | { | 717 | { |
713 | u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); | 718 | u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); |
714 | 719 | ||
720 | /* check buffer limits */ | ||
721 | limit = MIN(limit, (BUFFER_MAX_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF)); | ||
722 | |||
715 | if (c->istate == CHAN_INPUT_OPEN && | 723 | if (c->istate == CHAN_INPUT_OPEN && |
716 | limit > 0 && | 724 | limit > 0 && |
717 | buffer_len(&c->input) < limit) | 725 | buffer_len(&c->input) < limit) |
@@ -722,8 +730,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
722 | FD_SET(c->wfd, writeset); | 730 | FD_SET(c->wfd, writeset); |
723 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 731 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
724 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) | 732 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
725 | debug2("channel %d: obuf_empty delayed efd %d/(%d)", | 733 | debug2("channel %d: obuf_empty delayed efd %d/(%d)", |
726 | c->self, c->efd, buffer_len(&c->extended)); | 734 | c->self, c->efd, buffer_len(&c->extended)); |
727 | else | 735 | else |
728 | chan_obuf_empty(c); | 736 | chan_obuf_empty(c); |
729 | } | 737 | } |
@@ -889,7 +897,7 @@ static int | |||
889 | channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset) | 897 | channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset) |
890 | { | 898 | { |
891 | char *p, *host; | 899 | char *p, *host; |
892 | int len, have, i, found; | 900 | u_int len, have, i, found; |
893 | char username[256]; | 901 | char username[256]; |
894 | struct { | 902 | struct { |
895 | u_int8_t version; | 903 | u_int8_t version; |
@@ -974,7 +982,7 @@ channel_decode_socks5(Channel *c, fd_set * readset, fd_set * writeset) | |||
974 | } s5_req, s5_rsp; | 982 | } s5_req, s5_rsp; |
975 | u_int16_t dest_port; | 983 | u_int16_t dest_port; |
976 | u_char *p, dest_addr[255+1]; | 984 | u_char *p, dest_addr[255+1]; |
977 | int i, have, found, nmethods, addrlen, af; | 985 | u_int have, i, found, nmethods, addrlen, af; |
978 | 986 | ||
979 | debug2("channel %d: decode socks5", c->self); | 987 | debug2("channel %d: decode socks5", c->self); |
980 | p = buffer_ptr(&c->input); | 988 | p = buffer_ptr(&c->input); |
@@ -1018,7 +1026,7 @@ channel_decode_socks5(Channel *c, fd_set * readset, fd_set * writeset) | |||
1018 | debug2("channel %d: only socks5 connect supported", c->self); | 1026 | debug2("channel %d: only socks5 connect supported", c->self); |
1019 | return -1; | 1027 | return -1; |
1020 | } | 1028 | } |
1021 | switch(s5_req.atyp){ | 1029 | switch (s5_req.atyp){ |
1022 | case SSH_SOCKS5_IPV4: | 1030 | case SSH_SOCKS5_IPV4: |
1023 | addrlen = 4; | 1031 | addrlen = 4; |
1024 | af = AF_INET; | 1032 | af = AF_INET; |
@@ -1070,7 +1078,8 @@ static void | |||
1070 | channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) | 1078 | channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) |
1071 | { | 1079 | { |
1072 | u_char *p; | 1080 | u_char *p; |
1073 | int have, ret; | 1081 | u_int have; |
1082 | int ret; | ||
1074 | 1083 | ||
1075 | have = buffer_len(&c->input); | 1084 | have = buffer_len(&c->input); |
1076 | c->delayed = 0; | 1085 | c->delayed = 0; |
@@ -1173,7 +1182,7 @@ port_open_helper(Channel *c, char *rtype) | |||
1173 | int direct; | 1182 | int direct; |
1174 | char buf[1024]; | 1183 | char buf[1024]; |
1175 | char *remote_ipaddr = get_peer_ipaddr(c->sock); | 1184 | char *remote_ipaddr = get_peer_ipaddr(c->sock); |
1176 | u_short remote_port = get_peer_port(c->sock); | 1185 | int remote_port = get_peer_port(c->sock); |
1177 | 1186 | ||
1178 | direct = (strcmp(rtype, "direct-tcpip") == 0); | 1187 | direct = (strcmp(rtype, "direct-tcpip") == 0); |
1179 | 1188 | ||
@@ -1203,7 +1212,7 @@ port_open_helper(Channel *c, char *rtype) | |||
1203 | } | 1212 | } |
1204 | /* originator host and port */ | 1213 | /* originator host and port */ |
1205 | packet_put_cstring(remote_ipaddr); | 1214 | packet_put_cstring(remote_ipaddr); |
1206 | packet_put_int(remote_port); | 1215 | packet_put_int((u_int)remote_port); |
1207 | packet_send(); | 1216 | packet_send(); |
1208 | } else { | 1217 | } else { |
1209 | packet_start(SSH_MSG_PORT_OPEN); | 1218 | packet_start(SSH_MSG_PORT_OPEN); |
@@ -1360,7 +1369,7 @@ channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset) | |||
1360 | static int | 1369 | static int |
1361 | channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) | 1370 | channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) |
1362 | { | 1371 | { |
1363 | char buf[16*1024]; | 1372 | char buf[CHAN_RBUF]; |
1364 | int len; | 1373 | int len; |
1365 | 1374 | ||
1366 | if (c->rfd != -1 && | 1375 | if (c->rfd != -1 && |
@@ -1454,7 +1463,7 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1454 | static int | 1463 | static int |
1455 | channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) | 1464 | channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) |
1456 | { | 1465 | { |
1457 | char buf[16*1024]; | 1466 | char buf[CHAN_RBUF]; |
1458 | int len; | 1467 | int len; |
1459 | 1468 | ||
1460 | /** XXX handle drain efd, too */ | 1469 | /** XXX handle drain efd, too */ |
@@ -1804,8 +1813,8 @@ channel_output_poll(void) | |||
1804 | * hack for extended data: delay EOF if EFD still in use. | 1813 | * hack for extended data: delay EOF if EFD still in use. |
1805 | */ | 1814 | */ |
1806 | if (CHANNEL_EFD_INPUT_ACTIVE(c)) | 1815 | if (CHANNEL_EFD_INPUT_ACTIVE(c)) |
1807 | debug2("channel %d: ibuf_empty delayed efd %d/(%d)", | 1816 | debug2("channel %d: ibuf_empty delayed efd %d/(%d)", |
1808 | c->self, c->efd, buffer_len(&c->extended)); | 1817 | c->self, c->efd, buffer_len(&c->extended)); |
1809 | else | 1818 | else |
1810 | chan_ibuf_empty(c); | 1819 | chan_ibuf_empty(c); |
1811 | } | 1820 | } |
@@ -2190,20 +2199,20 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2190 | 2199 | ||
2191 | if (host == NULL) { | 2200 | if (host == NULL) { |
2192 | error("No forward host name."); | 2201 | error("No forward host name."); |
2193 | return success; | 2202 | return 0; |
2194 | } | 2203 | } |
2195 | if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { | 2204 | if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { |
2196 | error("Forward host name too long."); | 2205 | error("Forward host name too long."); |
2197 | return success; | 2206 | return 0; |
2198 | } | 2207 | } |
2199 | 2208 | ||
2200 | /* | 2209 | /* |
2201 | * Determine whether or not a port forward listens to loopback, | 2210 | * Determine whether or not a port forward listens to loopback, |
2202 | * specified address or wildcard. On the client, a specified bind | 2211 | * specified address or wildcard. On the client, a specified bind |
2203 | * address will always override gateway_ports. On the server, a | 2212 | * address will always override gateway_ports. On the server, a |
2204 | * gateway_ports of 1 (``yes'') will override the client's | 2213 | * gateway_ports of 1 (``yes'') will override the client's |
2205 | * specification and force a wildcard bind, whereas a value of 2 | 2214 | * specification and force a wildcard bind, whereas a value of 2 |
2206 | * (``clientspecified'') will bind to whatever address the client | 2215 | * (``clientspecified'') will bind to whatever address the client |
2207 | * asked for. | 2216 | * asked for. |
2208 | * | 2217 | * |
2209 | * Special-case listen_addrs are: | 2218 | * Special-case listen_addrs are: |
@@ -2245,12 +2254,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por | |||
2245 | packet_disconnect("getaddrinfo: fatal error: %s", | 2254 | packet_disconnect("getaddrinfo: fatal error: %s", |
2246 | gai_strerror(r)); | 2255 | gai_strerror(r)); |
2247 | } else { | 2256 | } else { |
2248 | verbose("channel_setup_fwd_listener: " | 2257 | error("channel_setup_fwd_listener: " |
2249 | "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); | ||
2250 | packet_send_debug("channel_setup_fwd_listener: " | ||
2251 | "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); | 2258 | "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); |
2252 | } | 2259 | } |
2253 | aitop = NULL; | 2260 | return 0; |
2254 | } | 2261 | } |
2255 | 2262 | ||
2256 | for (ai = aitop; ai; ai = ai->ai_next) { | 2263 | for (ai = aitop; ai; ai = ai->ai_next) { |
@@ -2317,7 +2324,7 @@ channel_cancel_rport_listener(const char *host, u_short port) | |||
2317 | u_int i; | 2324 | u_int i; |
2318 | int found = 0; | 2325 | int found = 0; |
2319 | 2326 | ||
2320 | for(i = 0; i < channels_alloc; i++) { | 2327 | for (i = 0; i < channels_alloc; i++) { |
2321 | Channel *c = channels[i]; | 2328 | Channel *c = channels[i]; |
2322 | 2329 | ||
2323 | if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && | 2330 | if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && |
@@ -2629,7 +2636,7 @@ channel_send_window_changes(void) | |||
2629 | struct winsize ws; | 2636 | struct winsize ws; |
2630 | 2637 | ||
2631 | for (i = 0; i < channels_alloc; i++) { | 2638 | for (i = 0; i < channels_alloc; i++) { |
2632 | if (channels[i] == NULL || !channels[i]->client_tty || | 2639 | if (channels[i] == NULL || !channels[i]->client_tty || |
2633 | channels[i]->type != SSH_CHANNEL_OPEN) | 2640 | channels[i]->type != SSH_CHANNEL_OPEN) |
2634 | continue; | 2641 | continue; |
2635 | if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) | 2642 | if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) |
@@ -2652,7 +2659,7 @@ channel_send_window_changes(void) | |||
2652 | */ | 2659 | */ |
2653 | int | 2660 | int |
2654 | x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | 2661 | x11_create_display_inet(int x11_display_offset, int x11_use_localhost, |
2655 | int single_connection, u_int *display_numberp) | 2662 | int single_connection, u_int *display_numberp, int **chanids) |
2656 | { | 2663 | { |
2657 | Channel *nc = NULL; | 2664 | Channel *nc = NULL; |
2658 | int display_number, sock; | 2665 | int display_number, sock; |
@@ -2742,6 +2749,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
2742 | } | 2749 | } |
2743 | 2750 | ||
2744 | /* Allocate a channel for each socket. */ | 2751 | /* Allocate a channel for each socket. */ |
2752 | if (chanids != NULL) | ||
2753 | *chanids = xmalloc(sizeof(**chanids) * (num_socks + 1)); | ||
2745 | for (n = 0; n < num_socks; n++) { | 2754 | for (n = 0; n < num_socks; n++) { |
2746 | sock = socks[n]; | 2755 | sock = socks[n]; |
2747 | nc = channel_new("x11 listener", | 2756 | nc = channel_new("x11 listener", |
@@ -2749,7 +2758,11 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
2749 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | 2758 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
2750 | 0, "X11 inet listener", 1); | 2759 | 0, "X11 inet listener", 1); |
2751 | nc->single_connection = single_connection; | 2760 | nc->single_connection = single_connection; |
2761 | if (*chanids != NULL) | ||
2762 | (*chanids)[n] = nc->self; | ||
2752 | } | 2763 | } |
2764 | if (*chanids != NULL) | ||
2765 | (*chanids)[n] = -1; | ||
2753 | 2766 | ||
2754 | /* Return the display number for the DISPLAY environment variable. */ | 2767 | /* Return the display number for the DISPLAY environment variable. */ |
2755 | *display_numberp = display_number; | 2768 | *display_numberp = display_number; |
@@ -2947,19 +2960,27 @@ deny_input_open(int type, u_int32_t seq, void *ctxt) | |||
2947 | * This should be called in the client only. | 2960 | * This should be called in the client only. |
2948 | */ | 2961 | */ |
2949 | void | 2962 | void |
2950 | x11_request_forwarding_with_spoofing(int client_session_id, | 2963 | x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, |
2951 | const char *proto, const char *data) | 2964 | const char *proto, const char *data) |
2952 | { | 2965 | { |
2953 | u_int data_len = (u_int) strlen(data) / 2; | 2966 | u_int data_len = (u_int) strlen(data) / 2; |
2954 | u_int i, value, len; | 2967 | u_int i, value; |
2955 | char *new_data; | 2968 | char *new_data; |
2956 | int screen_number; | 2969 | int screen_number; |
2957 | const char *cp; | 2970 | const char *cp; |
2958 | u_int32_t rnd = 0; | 2971 | u_int32_t rnd = 0; |
2959 | 2972 | ||
2960 | cp = getenv("DISPLAY"); | 2973 | if (x11_saved_display == NULL) |
2961 | if (cp) | 2974 | x11_saved_display = xstrdup(disp); |
2962 | cp = strchr(cp, ':'); | 2975 | else if (strcmp(disp, x11_saved_display) != 0) { |
2976 | error("x11_request_forwarding_with_spoofing: different " | ||
2977 | "$DISPLAY already forwarded"); | ||
2978 | return; | ||
2979 | } | ||
2980 | |||
2981 | cp = disp; | ||
2982 | if (disp) | ||
2983 | cp = strchr(disp, ':'); | ||
2963 | if (cp) | 2984 | if (cp) |
2964 | cp = strchr(cp, '.'); | 2985 | cp = strchr(cp, '.'); |
2965 | if (cp) | 2986 | if (cp) |
@@ -2967,33 +2988,31 @@ x11_request_forwarding_with_spoofing(int client_session_id, | |||
2967 | else | 2988 | else |
2968 | screen_number = 0; | 2989 | screen_number = 0; |
2969 | 2990 | ||
2970 | /* Save protocol name. */ | 2991 | if (x11_saved_proto == NULL) { |
2971 | x11_saved_proto = xstrdup(proto); | 2992 | /* Save protocol name. */ |
2972 | 2993 | x11_saved_proto = xstrdup(proto); | |
2973 | /* | 2994 | /* |
2974 | * Extract real authentication data and generate fake data of the | 2995 | * Extract real authentication data and generate fake data |
2975 | * same length. | 2996 | * of the same length. |
2976 | */ | 2997 | */ |
2977 | x11_saved_data = xmalloc(data_len); | 2998 | x11_saved_data = xmalloc(data_len); |
2978 | x11_fake_data = xmalloc(data_len); | 2999 | x11_fake_data = xmalloc(data_len); |
2979 | for (i = 0; i < data_len; i++) { | 3000 | for (i = 0; i < data_len; i++) { |
2980 | if (sscanf(data + 2 * i, "%2x", &value) != 1) | 3001 | if (sscanf(data + 2 * i, "%2x", &value) != 1) |
2981 | fatal("x11_request_forwarding: bad authentication data: %.100s", data); | 3002 | fatal("x11_request_forwarding: bad " |
2982 | if (i % 4 == 0) | 3003 | "authentication data: %.100s", data); |
2983 | rnd = arc4random(); | 3004 | if (i % 4 == 0) |
2984 | x11_saved_data[i] = value; | 3005 | rnd = arc4random(); |
2985 | x11_fake_data[i] = rnd & 0xff; | 3006 | x11_saved_data[i] = value; |
2986 | rnd >>= 8; | 3007 | x11_fake_data[i] = rnd & 0xff; |
2987 | } | 3008 | rnd >>= 8; |
2988 | x11_saved_data_len = data_len; | 3009 | } |
2989 | x11_fake_data_len = data_len; | 3010 | x11_saved_data_len = data_len; |
3011 | x11_fake_data_len = data_len; | ||
3012 | } | ||
2990 | 3013 | ||
2991 | /* Convert the fake data into hex. */ | 3014 | /* Convert the fake data into hex. */ |
2992 | len = 2 * data_len + 1; | 3015 | new_data = tohex(x11_fake_data, data_len); |
2993 | new_data = xmalloc(len); | ||
2994 | for (i = 0; i < data_len; i++) | ||
2995 | snprintf(new_data + 2 * i, len - 2 * i, | ||
2996 | "%02x", (u_char) x11_fake_data[i]); | ||
2997 | 3016 | ||
2998 | /* Send the request packet. */ | 3017 | /* Send the request packet. */ |
2999 | if (compat20) { | 3018 | if (compat20) { |