|
Lines 96-101
Link Here
|
| 96 |
*/ |
96 |
*/ |
| 97 |
static int channel_max_fd = 0; |
97 |
static int channel_max_fd = 0; |
| 98 |
|
98 |
|
|
|
99 |
/* |
| 100 |
* Flag indicating that channel fds have been modified, used to restart |
| 101 |
* preparations for select if necessary |
| 102 |
*/ |
| 103 |
static int channel_fds_changed = 0; |
| 99 |
|
104 |
|
| 100 |
/* -- tcp forwarding */ |
105 |
/* -- tcp forwarding */ |
| 101 |
|
106 |
|
|
Lines 136-158
Link Here
|
| 136 |
/* Maximum number of fake X11 displays to try. */ |
141 |
/* Maximum number of fake X11 displays to try. */ |
| 137 |
#define MAX_DISPLAYS 1000 |
142 |
#define MAX_DISPLAYS 1000 |
| 138 |
|
143 |
|
| 139 |
/* Saved X11 local (client) display. */ |
144 |
struct x11_fwd { |
| 140 |
static char *x11_saved_display = NULL; |
145 |
/* Saved X11 local (client) display. */ |
| 141 |
|
146 |
char *saved_display; |
| 142 |
/* Saved X11 authentication protocol name. */ |
147 |
|
| 143 |
static char *x11_saved_proto = NULL; |
148 |
/* Saved X11 authentication protocol name. */ |
|
|
149 |
char *saved_proto; |
| 150 |
|
| 151 |
/* Saved X11 authentication data. These are the real data. */ |
| 152 |
u_char *saved_data; |
| 153 |
u_int saved_data_len; |
| 144 |
|
154 |
|
| 145 |
/* Saved X11 authentication data. This is the real data. */ |
155 |
/* |
| 146 |
static char *x11_saved_data = NULL; |
156 |
* Fake X11 authentication data. This is what the server will be |
| 147 |
static u_int x11_saved_data_len = 0; |
157 |
sending us; we should replace any occurrences with the real data. |
|
|
158 |
*/ |
| 159 |
u_char *fake_data; |
| 160 |
u_int fake_data_len; |
| 161 |
|
| 162 |
u_int usecount; |
| 163 |
struct x11_fwd *next; |
| 164 |
}; |
| 148 |
|
165 |
|
| 149 |
/* |
166 |
static struct x11_fwd *x11_fwds = NULL; |
| 150 |
* Fake X11 authentication data. This is what the server will be sending us; |
|
|
| 151 |
* we should replace any occurrences of this by the real data. |
| 152 |
*/ |
| 153 |
static u_char *x11_fake_data = NULL; |
| 154 |
static u_int x11_fake_data_len; |
| 155 |
|
167 |
|
|
|
168 |
static void x11_put_fwd(struct x11_fwd *fwd); |
| 156 |
|
169 |
|
| 157 |
/* -- agent forwarding */ |
170 |
/* -- agent forwarding */ |
| 158 |
|
171 |
|
|
Lines 218-223
Link Here
|
| 218 |
channel_register_fds(Channel *c, int rfd, int wfd, int efd, |
231 |
channel_register_fds(Channel *c, int rfd, int wfd, int efd, |
| 219 |
int extusage, int nonblock) |
232 |
int extusage, int nonblock) |
| 220 |
{ |
233 |
{ |
|
|
234 |
c->rfd = rfd; |
| 235 |
c->wfd = wfd; |
| 236 |
c->sock = (rfd == wfd) ? rfd : -1; |
| 237 |
c->ctl_fd = -1; /* XXX: set elsewhere */ |
| 238 |
c->efd = efd; |
| 239 |
channel_fds_changed = 1; |
| 240 |
|
| 241 |
if (rfd == -1 && wfd == -1 && efd == -1) |
| 242 |
return; |
| 243 |
|
| 221 |
/* Update the maximum file descriptor value. */ |
244 |
/* Update the maximum file descriptor value. */ |
| 222 |
channel_max_fd = MAX(channel_max_fd, rfd); |
245 |
channel_max_fd = MAX(channel_max_fd, rfd); |
| 223 |
channel_max_fd = MAX(channel_max_fd, wfd); |
246 |
channel_max_fd = MAX(channel_max_fd, wfd); |
|
Lines 225-235
Link Here
|
| 225 |
|
248 |
|
| 226 |
/* XXX set close-on-exec -markus */ |
249 |
/* XXX set close-on-exec -markus */ |
| 227 |
|
250 |
|
| 228 |
c->rfd = rfd; |
|
|
| 229 |
c->wfd = wfd; |
| 230 |
c->sock = (rfd == wfd) ? rfd : -1; |
| 231 |
c->ctl_fd = -1; /* XXX: set elsewhere */ |
| 232 |
c->efd = efd; |
| 233 |
c->extended_usage = extusage; |
251 |
c->extended_usage = extusage; |
| 234 |
|
252 |
|
| 235 |
/* XXX ugly hack: nonblock is only set by the server */ |
253 |
/* XXX ugly hack: nonblock is only set by the server */ |
|
Lines 403-408
Link Here
|
| 403 |
c->remote_name = NULL; |
421 |
c->remote_name = NULL; |
| 404 |
} |
422 |
} |
| 405 |
channels[c->self] = NULL; |
423 |
channels[c->self] = NULL; |
|
|
424 |
if (c->x11_fwd) |
| 425 |
x11_put_fwd(c->x11_fwd); |
| 406 |
xfree(c); |
426 |
xfree(c); |
| 407 |
} |
427 |
} |
| 408 |
|
428 |
|
|
Lines 826-831
Link Here
|
| 826 |
FD_SET(c->sock, writeset); |
846 |
FD_SET(c->sock, writeset); |
| 827 |
} |
847 |
} |
| 828 |
|
848 |
|
|
|
849 |
static struct x11_fwd * |
| 850 |
x11_lookup_fwd_by_fakedata(unsigned char *proto, u_int protolen, unsigned char *data, u_int datalen) |
| 851 |
{ |
| 852 |
struct x11_fwd *fwd; |
| 853 |
|
| 854 |
for (fwd = x11_fwds; fwd; fwd = fwd->next) { |
| 855 |
if (protolen == strlen(fwd->saved_proto) && |
| 856 |
!memcmp(fwd->saved_proto, proto, protolen) && |
| 857 |
fwd->fake_data_len == datalen && |
| 858 |
!memcmp(fwd->fake_data, data, datalen)) |
| 859 |
break; |
| 860 |
} |
| 861 |
return fwd; |
| 862 |
} |
| 863 |
|
| 864 |
static struct x11_fwd * |
| 865 |
x11_lookup_fwd_by_realdata(const char *display, const char *proto, const u_char *authdata, u_int datalen) |
| 866 |
{ |
| 867 |
struct x11_fwd *fwd; |
| 868 |
|
| 869 |
for (fwd = x11_fwds; fwd; fwd = fwd->next) { |
| 870 |
if (!strcmp(display, fwd->saved_display) && |
| 871 |
!strcmp(proto, fwd->saved_proto) && |
| 872 |
datalen == fwd->saved_data_len && |
| 873 |
!memcmp(authdata, fwd->saved_data, datalen)) |
| 874 |
break; |
| 875 |
} |
| 876 |
return fwd; |
| 877 |
} |
| 878 |
|
| 879 |
static void x11_put_fwd(struct x11_fwd *fwd) |
| 880 |
{ |
| 881 |
fwd->usecount--; |
| 882 |
debug("Decrease usecount on X11 forward data for %s to %d.", fwd->saved_display, fwd->usecount); |
| 883 |
if (!fwd->usecount) { |
| 884 |
struct x11_fwd **tmp = &x11_fwds; |
| 885 |
while (*tmp) { |
| 886 |
if (*tmp == fwd) { |
| 887 |
*tmp = fwd->next; |
| 888 |
xfree(fwd); |
| 889 |
return; |
| 890 |
} |
| 891 |
tmp = &(*tmp)->next; |
| 892 |
} |
| 893 |
fatal("X11 forward data not found."); |
| 894 |
} |
| 895 |
} |
| 896 |
|
| 829 |
/* |
897 |
/* |
| 830 |
* This is a special state for X11 authentication spoofing. An opened X11 |
898 |
* This is a special state for X11 authentication spoofing. An opened X11 |
| 831 |
* connection (when authentication spoofing is being done) remains in this |
899 |
* connection (when authentication spoofing is being done) remains in this |
|
Lines 836-845
Link Here
|
| 836 |
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok |
904 |
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok |
| 837 |
*/ |
905 |
*/ |
| 838 |
static int |
906 |
static int |
| 839 |
x11_open_helper(Buffer *b) |
907 |
x11_open_helper(Channel *c) |
| 840 |
{ |
908 |
{ |
|
|
909 |
Buffer *b = &c->output; |
| 841 |
u_char *ucp; |
910 |
u_char *ucp; |
| 842 |
u_int proto_len, data_len; |
911 |
u_int proto_len, data_len; |
|
|
912 |
struct x11_fwd *fwd; |
| 913 |
int sock; |
| 843 |
|
914 |
|
| 844 |
/* Check if the fixed size part of the packet is in buffer. */ |
915 |
/* Check if the fixed size part of the packet is in buffer. */ |
| 845 |
if (buffer_len(b) < 12) |
916 |
if (buffer_len(b) < 12) |
|
Lines 864-913
Link Here
|
| 864 |
12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) |
935 |
12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) |
| 865 |
return 0; |
936 |
return 0; |
| 866 |
|
937 |
|
| 867 |
/* Check if authentication protocol matches. */ |
938 |
fwd = x11_lookup_fwd_by_fakedata(ucp+12, proto_len, |
| 868 |
if (proto_len != strlen(x11_saved_proto) || |
939 |
ucp + 12 + ((proto_len + 3) & ~3), data_len); |
| 869 |
memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { |
940 |
|
| 870 |
debug2("X11 connection uses different authentication protocol."); |
941 |
if (!fwd) { |
| 871 |
return -1; |
942 |
debug("No matching X11 forward found."); |
| 872 |
} |
|
|
| 873 |
/* Check if authentication data matches our fake data. */ |
| 874 |
if (data_len != x11_fake_data_len || |
| 875 |
memcmp(ucp + 12 + ((proto_len + 3) & ~3), |
| 876 |
x11_fake_data, x11_fake_data_len) != 0) { |
| 877 |
debug2("X11 auth data does not match fake data."); |
| 878 |
return -1; |
| 879 |
} |
| 880 |
/* Check fake data length */ |
| 881 |
if (x11_fake_data_len != x11_saved_data_len) { |
| 882 |
error("X11 fake_data_len %d != saved_data_len %d", |
| 883 |
x11_fake_data_len, x11_saved_data_len); |
| 884 |
return -1; |
943 |
return -1; |
| 885 |
} |
944 |
} |
|
|
945 |
fwd->usecount++; |
| 946 |
debug("Increase use count for X11 fwd for display %s to %d.", fwd->saved_display, fwd->usecount); |
| 947 |
c->x11_fwd = fwd; |
| 886 |
/* |
948 |
/* |
| 887 |
* Received authentication protocol and data match |
949 |
* We found a matching X11 forward. Substitute the fake data |
| 888 |
* our fake data. Substitute the fake data with real |
950 |
* with real data. |
| 889 |
* data. |
|
|
| 890 |
*/ |
951 |
*/ |
| 891 |
memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
952 |
memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
| 892 |
x11_saved_data, x11_saved_data_len); |
953 |
fwd->saved_data, fwd->saved_data_len); |
| 893 |
return 1; |
954 |
|
|
|
955 |
sock = x11_connect_display(fwd->saved_display); |
| 956 |
if (sock == -1) |
| 957 |
return -2; |
| 958 |
channel_register_fds(c, sock, sock, -1, 0, 1); |
| 959 |
c->type = SSH_CHANNEL_OPEN; |
| 960 |
|
| 961 |
/* Because we registered a new fd, the channel_pre handlers will be |
| 962 |
called again immediately. And because we changed the channel type |
| 963 |
to SSH_CHANNEL_OPEN, the x11 function won't be called next time. |
| 964 |
It's just a normal channel now */ |
| 965 |
return 0; |
| 894 |
} |
966 |
} |
| 895 |
|
967 |
|
| 896 |
static void |
968 |
static void |
| 897 |
channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset) |
969 |
channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset) |
| 898 |
{ |
970 |
{ |
| 899 |
int ret = x11_open_helper(&c->output); |
971 |
int ret = x11_open_helper(c); |
| 900 |
|
972 |
|
| 901 |
if (ret == 1) { |
973 |
if (ret < 0) { |
| 902 |
/* Start normal processing for the channel. */ |
|
|
| 903 |
c->type = SSH_CHANNEL_OPEN; |
| 904 |
channel_pre_open_13(c, readset, writeset); |
| 905 |
} else if (ret == -1) { |
| 906 |
/* |
974 |
/* |
| 907 |
* We have received an X11 connection that has bad |
975 |
* We have received an X11 connection that has bad |
| 908 |
* authentication information. |
976 |
* authentication information. |
| 909 |
*/ |
977 |
*/ |
| 910 |
logit("X11 connection rejected because of wrong authentication."); |
978 |
switch (ret) { |
|
|
979 |
case -1: |
| 980 |
logit("X11 connection rejected because of wrong authentication."); |
| 981 |
break; |
| 982 |
case -2: |
| 983 |
logit("X11 connection rejected due to failure to connect to local server."); |
| 984 |
break; |
| 985 |
} |
| 911 |
buffer_clear(&c->input); |
986 |
buffer_clear(&c->input); |
| 912 |
buffer_clear(&c->output); |
987 |
buffer_clear(&c->output); |
| 913 |
channel_close_fd(&c->sock); |
988 |
channel_close_fd(&c->sock); |
|
Lines 922-936
Link Here
|
| 922 |
static void |
997 |
static void |
| 923 |
channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) |
998 |
channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) |
| 924 |
{ |
999 |
{ |
| 925 |
int ret = x11_open_helper(&c->output); |
1000 |
int ret = x11_open_helper(c); |
| 926 |
|
|
|
| 927 |
/* c->force_drain = 1; */ |
| 928 |
|
1001 |
|
| 929 |
if (ret == 1) { |
1002 |
if (ret < 0) { |
| 930 |
c->type = SSH_CHANNEL_OPEN; |
1003 |
switch (ret) { |
| 931 |
channel_pre_open(c, readset, writeset); |
1004 |
case -1: |
| 932 |
} else if (ret == -1) { |
1005 |
logit("X11 connection rejected because of wrong authentication."); |
| 933 |
logit("X11 connection rejected because of wrong authentication."); |
1006 |
break; |
|
|
1007 |
case -2: |
| 1008 |
logit("X11 connection rejected due to failure to connect to local server."); |
| 1009 |
break; |
| 1010 |
} |
| 934 |
debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); |
1011 |
debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); |
| 935 |
chan_read_failed(c); |
1012 |
chan_read_failed(c); |
| 936 |
buffer_clear(&c->input); |
1013 |
buffer_clear(&c->input); |
|
Lines 1834-1859
Link Here
|
| 1834 |
{ |
1911 |
{ |
| 1835 |
u_int n, sz, nfdset; |
1912 |
u_int n, sz, nfdset; |
| 1836 |
|
1913 |
|
| 1837 |
n = MAX(*maxfdp, channel_max_fd); |
1914 |
for (channel_fds_changed = 1; channel_fds_changed;) { |
|
|
1915 |
channel_fds_changed = 0; |
| 1916 |
n = MAX(*maxfdp, channel_max_fd); |
| 1917 |
|
| 1918 |
nfdset = howmany(n+1, NFDBITS); |
| 1919 |
/* Explicitly test here, because xrealloc isn't always called */ |
| 1920 |
if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask)) |
| 1921 |
fatal("channel_prepare_select: max_fd (%d) is too large", n); |
| 1922 |
sz = nfdset * sizeof(fd_mask); |
| 1923 |
|
| 1924 |
/* perhaps check sz < nalloc/2 and shrink? */ |
| 1925 |
if (*readsetp == NULL || sz > *nallocp) { |
| 1926 |
*readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask)); |
| 1927 |
*writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask)); |
| 1928 |
*nallocp = sz; |
| 1929 |
} |
| 1930 |
*maxfdp = n; |
| 1931 |
memset(*readsetp, 0, sz); |
| 1932 |
memset(*writesetp, 0, sz); |
| 1838 |
|
1933 |
|
| 1839 |
nfdset = howmany(n+1, NFDBITS); |
1934 |
if (!rekeying) |
| 1840 |
/* Explicitly test here, because xrealloc isn't always called */ |
1935 |
channel_handler(channel_pre, *readsetp, *writesetp); |
| 1841 |
if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask)) |
1936 |
} |
| 1842 |
fatal("channel_prepare_select: max_fd (%d) is too large", n); |
|
|
| 1843 |
sz = nfdset * sizeof(fd_mask); |
| 1844 |
|
| 1845 |
/* perhaps check sz < nalloc/2 and shrink? */ |
| 1846 |
if (*readsetp == NULL || sz > *nallocp) { |
| 1847 |
*readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask)); |
| 1848 |
*writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask)); |
| 1849 |
*nallocp = sz; |
| 1850 |
} |
| 1851 |
*maxfdp = n; |
| 1852 |
memset(*readsetp, 0, sz); |
| 1853 |
memset(*writesetp, 0, sz); |
| 1854 |
|
1937 |
|
| 1855 |
if (!rekeying) |
|
|
| 1856 |
channel_handler(channel_pre, *readsetp, *writesetp); |
| 1857 |
} |
1938 |
} |
| 1858 |
|
1939 |
|
| 1859 |
/* |
1940 |
/* |
|
Lines 2973-2995
Link Here
|
| 2973 |
} |
3054 |
} |
| 2974 |
|
3055 |
|
| 2975 |
int |
3056 |
int |
| 2976 |
x11_connect_display(void) |
3057 |
x11_connect_display(char *display) |
| 2977 |
{ |
3058 |
{ |
| 2978 |
u_int display_number; |
3059 |
u_int display_number; |
| 2979 |
const char *display; |
|
|
| 2980 |
char buf[1024], *cp; |
3060 |
char buf[1024], *cp; |
| 2981 |
struct addrinfo hints, *ai, *aitop; |
3061 |
struct addrinfo hints, *ai, *aitop; |
| 2982 |
char strport[NI_MAXSERV]; |
3062 |
char strport[NI_MAXSERV]; |
| 2983 |
int gaierr, sock = 0; |
3063 |
int gaierr, sock = 0; |
| 2984 |
|
3064 |
|
| 2985 |
/* Try to open a socket for the local X server. */ |
|
|
| 2986 |
display = getenv("DISPLAY"); |
| 2987 |
if (!display) { |
| 2988 |
error("DISPLAY not set."); |
| 2989 |
return -1; |
| 2990 |
} |
| 2991 |
/* |
3065 |
/* |
| 2992 |
* Now we decode the value of the DISPLAY variable and make a |
3066 |
* Decode the value of the DISPLAY variable and make a |
| 2993 |
* connection to the real X server. |
3067 |
* connection to the real X server. |
| 2994 |
*/ |
3068 |
*/ |
| 2995 |
|
3069 |
|
|
Lines 3078-3084
Link Here
|
| 3078 |
x11_input_open(int type, u_int32_t seq, void *ctxt) |
3152 |
x11_input_open(int type, u_int32_t seq, void *ctxt) |
| 3079 |
{ |
3153 |
{ |
| 3080 |
Channel *c = NULL; |
3154 |
Channel *c = NULL; |
| 3081 |
int remote_id, sock = 0; |
3155 |
int remote_id; |
| 3082 |
char *remote_host; |
3156 |
char *remote_host; |
| 3083 |
|
3157 |
|
| 3084 |
debug("Received X11 open request."); |
3158 |
debug("Received X11 open request."); |
|
Lines 3092-3118
Link Here
|
| 3092 |
} |
3166 |
} |
| 3093 |
packet_check_eom(); |
3167 |
packet_check_eom(); |
| 3094 |
|
3168 |
|
| 3095 |
/* Obtain a connection to the real X display. */ |
3169 |
/* Allocate a channel for this connection. */ |
| 3096 |
sock = x11_connect_display(); |
3170 |
c = channel_new("connected x11 socket", |
| 3097 |
if (sock != -1) { |
3171 |
SSH_CHANNEL_X11_OPEN, -1, -1, -1, 0, 0, 0, |
| 3098 |
/* Allocate a channel for this connection. */ |
3172 |
remote_host, 1); |
| 3099 |
c = channel_new("connected x11 socket", |
3173 |
c->remote_id = remote_id; |
| 3100 |
SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, |
3174 |
c->force_drain = 1; |
| 3101 |
remote_host, 1); |
3175 |
|
| 3102 |
c->remote_id = remote_id; |
|
|
| 3103 |
c->force_drain = 1; |
| 3104 |
} |
| 3105 |
xfree(remote_host); |
3176 |
xfree(remote_host); |
| 3106 |
if (c == NULL) { |
3177 |
|
| 3107 |
/* Send refusal to the remote host. */ |
3178 |
/* Send a confirmation to the remote host. */ |
| 3108 |
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); |
3179 |
packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); |
| 3109 |
packet_put_int(remote_id); |
3180 |
packet_put_int(remote_id); |
| 3110 |
} else { |
3181 |
packet_put_int(c->self); |
| 3111 |
/* Send a confirmation to the remote host. */ |
3182 |
|
| 3112 |
packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); |
|
|
| 3113 |
packet_put_int(remote_id); |
| 3114 |
packet_put_int(c->self); |
| 3115 |
} |
| 3116 |
packet_send(); |
3183 |
packet_send(); |
| 3117 |
} |
3184 |
} |
| 3118 |
|
3185 |
|
|
Lines 3149-3169
Link Here
|
| 3149 |
x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, |
3216 |
x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, |
| 3150 |
const char *proto, const char *data) |
3217 |
const char *proto, const char *data) |
| 3151 |
{ |
3218 |
{ |
|
|
3219 |
Channel *c = NULL; |
| 3152 |
u_int data_len = (u_int) strlen(data) / 2; |
3220 |
u_int data_len = (u_int) strlen(data) / 2; |
| 3153 |
u_int i, value; |
3221 |
u_int i, value; |
| 3154 |
char *new_data; |
3222 |
char *new_data; |
|
|
3223 |
u_char *realdata; |
| 3155 |
int screen_number; |
3224 |
int screen_number; |
| 3156 |
const char *cp; |
3225 |
const char *cp; |
| 3157 |
u_int32_t rnd = 0; |
3226 |
u_int32_t rnd = 0; |
|
|
3227 |
struct x11_fwd *fwd; |
| 3158 |
|
3228 |
|
| 3159 |
if (x11_saved_display == NULL) |
3229 |
if (compat20) { |
| 3160 |
x11_saved_display = xstrdup(disp); |
3230 |
c = channel_lookup(client_session_id); |
| 3161 |
else if (strcmp(disp, x11_saved_display) != 0) { |
3231 |
if (!c) |
| 3162 |
error("x11_request_forwarding_with_spoofing: different " |
3232 |
error("%s: channel %d: unknown channel", __func__, client_session_id); |
| 3163 |
"$DISPLAY already forwarded"); |
3233 |
} |
| 3164 |
return; |
3234 |
|
|
|
3235 |
/* Convert real authentication data to binary */ |
| 3236 |
realdata = xmalloc(data_len); |
| 3237 |
for (i = 0; i < data_len; i++) { |
| 3238 |
if (sscanf(data + 2 * i, "%2x", &value) != 1) |
| 3239 |
fatal("x11_request_forwarding: bad " |
| 3240 |
"authentication data: %.100s", data); |
| 3241 |
realdata[i] = value; |
| 3242 |
} |
| 3243 |
|
| 3244 |
fwd = x11_lookup_fwd_by_realdata(disp, proto, realdata, data_len); |
| 3245 |
if (fwd) { |
| 3246 |
fwd->usecount++; |
| 3247 |
debug("Increase use count for X11 fwd for display %s to %d.", disp, fwd->usecount); |
| 3248 |
xfree(realdata); |
| 3249 |
} else { |
| 3250 |
/* No existing forward. Create a new one */ |
| 3251 |
debug("Create new X11 fake auth data for display %s.", disp); |
| 3252 |
fwd = xmalloc(sizeof(*fwd)); |
| 3253 |
fwd->saved_display = xstrdup(disp); |
| 3254 |
fwd->saved_proto = xstrdup(proto); |
| 3255 |
fwd->saved_data = realdata; |
| 3256 |
fwd->saved_data_len = data_len; |
| 3257 |
fwd->fake_data = xmalloc(data_len); |
| 3258 |
fwd->fake_data_len = data_len; |
| 3259 |
|
| 3260 |
for (i = 0; i < data_len; i++) { |
| 3261 |
if (i % 4 == 0) |
| 3262 |
rnd = arc4random(); |
| 3263 |
fwd->fake_data[i] = rnd & 0xff; |
| 3264 |
rnd >>= 8; |
| 3265 |
} |
| 3266 |
|
| 3267 |
fwd->usecount = 1; |
| 3268 |
fwd->next = x11_fwds; |
| 3269 |
x11_fwds = fwd; |
| 3165 |
} |
3270 |
} |
| 3166 |
|
3271 |
|
|
|
3272 |
if (c) |
| 3273 |
c->x11_fwd = fwd; |
| 3274 |
|
| 3167 |
cp = strchr(disp, ':'); |
3275 |
cp = strchr(disp, ':'); |
| 3168 |
if (cp) |
3276 |
if (cp) |
| 3169 |
cp = strchr(cp, '.'); |
3277 |
cp = strchr(cp, '.'); |
|
Lines 3172-3202
Link Here
|
| 3172 |
else |
3280 |
else |
| 3173 |
screen_number = 0; |
3281 |
screen_number = 0; |
| 3174 |
|
3282 |
|
| 3175 |
if (x11_saved_proto == NULL) { |
|
|
| 3176 |
/* Save protocol name. */ |
| 3177 |
x11_saved_proto = xstrdup(proto); |
| 3178 |
/* |
| 3179 |
* Extract real authentication data and generate fake data |
| 3180 |
* of the same length. |
| 3181 |
*/ |
| 3182 |
x11_saved_data = xmalloc(data_len); |
| 3183 |
x11_fake_data = xmalloc(data_len); |
| 3184 |
for (i = 0; i < data_len; i++) { |
| 3185 |
if (sscanf(data + 2 * i, "%2x", &value) != 1) |
| 3186 |
fatal("x11_request_forwarding: bad " |
| 3187 |
"authentication data: %.100s", data); |
| 3188 |
if (i % 4 == 0) |
| 3189 |
rnd = arc4random(); |
| 3190 |
x11_saved_data[i] = value; |
| 3191 |
x11_fake_data[i] = rnd & 0xff; |
| 3192 |
rnd >>= 8; |
| 3193 |
} |
| 3194 |
x11_saved_data_len = data_len; |
| 3195 |
x11_fake_data_len = data_len; |
| 3196 |
} |
| 3197 |
|
| 3198 |
/* Convert the fake data into hex. */ |
3283 |
/* Convert the fake data into hex. */ |
| 3199 |
new_data = tohex(x11_fake_data, data_len); |
3284 |
new_data = tohex(fwd->fake_data, data_len); |
| 3200 |
|
3285 |
|
| 3201 |
/* Send the request packet. */ |
3286 |
/* Send the request packet. */ |
| 3202 |
if (compat20) { |
3287 |
if (compat20) { |