Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/fwd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4690 - (show annotations) (download) (as text)
Thu Oct 27 14:59:30 2011 UTC (18 months, 3 weeks ago) by doda
File MIME type: text/x-csrc
File size: 60598 byte(s)
スクリーン番号としてディスプレイ番号を使っていたのを修正。
1 /*
2 Copyright (c) 1998-2001, Robert O'Callahan
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 This code is copyright (C) 1998-1999 Robert O'Callahan.
31 See LICENSE.TXT for the license.
32 */
33
34 #include "ttxssh.h"
35
36 #include "x11util.h"
37
38 #include "fwd.h"
39
40 #include <assert.h>
41 #ifndef NO_INET6
42 #include "WSAAsyncGetAddrInfo.h"
43 #endif /* NO_INET6 */
44
45 #define WM_SOCK_ACCEPT (WM_APP+9999)
46 #define WM_SOCK_IO (WM_APP+9998)
47 #define WM_SOCK_GOTNAME (WM_APP+9997)
48
49 #define CHANNEL_READ_BUF_SIZE 8192
50
51 static LRESULT CALLBACK accept_wnd_proc(HWND wnd, UINT msg, WPARAM wParam,
52 LPARAM lParam);
53
54 static int find_request_num(PTInstVar pvar, SOCKET s)
55 {
56 int i;
57 #ifndef NO_INET6
58 int j;
59 #endif /* NO_INET6 */
60
61 if (s == INVALID_SOCKET)
62 return -1;
63
64 #ifndef NO_INET6
65 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
66 for (j = 0; j < pvar->fwd_state.requests[i].num_listening_sockets;
67 ++j) {
68 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0
69 && pvar->fwd_state.requests[i].listening_sockets[j] == s) {
70 return i;
71 }
72 }
73 }
74 #else
75 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
76 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0
77 && pvar->fwd_state.requests[i].listening_socket == s) {
78 return i;
79 }
80 }
81 #endif /* NO_INET6 */
82
83 return -1;
84 }
85
86 static int find_channel_num(PTInstVar pvar, SOCKET s)
87 {
88 int i;
89
90 if (s == INVALID_SOCKET)
91 return -1;
92
93 for (i = 0; i < pvar->fwd_state.num_channels; i++) {
94 if (pvar->fwd_state.channels[i].local_socket == s) {
95 return i;
96 }
97 }
98
99 return -1;
100 }
101
102 static int find_request_num_from_async_request(PTInstVar pvar,
103 HANDLE request)
104 {
105 int i;
106
107 if (request == 0)
108 return -1;
109
110 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
111 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0
112 && pvar->fwd_state.requests[i].to_host_lookup_handle == request) {
113 return i;
114 }
115 }
116
117 return -1;
118 }
119
120 #ifndef NO_INET6
121 static int find_listening_socket_num(PTInstVar pvar, int request_num,
122 SOCKET s)
123 {
124 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
125 int i;
126
127 for (i = 0; i < request->num_listening_sockets; ++i)
128 if (request->listening_sockets[i] == s)
129 return i;
130
131 /* not found */
132 return -1;
133 }
134 #endif /* NO_INET6 */
135
136 static void drain_matching_messages(HWND wnd, UINT msg, WPARAM wParam)
137 {
138 MSG m;
139 MSG FAR *buf;
140 int buf_len;
141 int buf_size;
142 int i;
143
144 /* fast path for case where there are no suitable messages */
145 if (!PeekMessage(&m, wnd, msg, msg, PM_NOREMOVE)) {
146 return;
147 }
148
149 /* suck out all the messages */
150 buf_size = 1;
151 buf_len = 0;
152 buf = (MSG FAR *) malloc(sizeof(MSG) * buf_size);
153
154 while (PeekMessage(&m, wnd, msg, msg, PM_REMOVE)) {
155 if (buf_len == buf_size) {
156 buf_size *= 2;
157 buf = (MSG FAR *) realloc(buf, sizeof(MSG) * buf_size);
158 }
159
160 buf[buf_len] = m;
161 buf_len++;
162 }
163
164 for (i = 0; i < buf_len; i++) {
165 if (buf[i].wParam != wParam) {
166 PostMessage(wnd, msg, buf[i].wParam, buf[i].lParam);
167 }
168 }
169
170 free(buf);
171 }
172
173 /* hideous hack to fix broken Winsock API.
174 After we close a socket further WM_ messages may arrive for it, according to
175 the docs for WSAAsyncSelect. This sucks because we may allocate a new socket
176 before these messages are processed, which may get the same handle value as
177 the old socket, which may mean that we get confused and try to process the old
178 message according to the new request or channel, which could cause chaos and
179 possibly even security problems.
180 "Solution": scan the accept_wnd message queue whenever we close a socket and
181 remove all pending messages for that socket. Possibly this might not even be
182 enough if there is a system thread that is in the process of posting
183 a new message while during execution of the closesocket. I'm hoping
184 that those actions are serialized...
185 */
186 static void safe_closesocket(PTInstVar pvar, SOCKET s)
187 {
188 HWND wnd = pvar->fwd_state.accept_wnd;
189
190 closesocket(s);
191 if (wnd != NULL) {
192 drain_matching_messages(wnd, WM_SOCK_ACCEPT, (WPARAM) s);
193 drain_matching_messages(wnd, WM_SOCK_IO, (WPARAM) s);
194 }
195 }
196
197 static void safe_WSACancelAsyncRequest(PTInstVar pvar, HANDLE request)
198 {
199 HWND wnd = pvar->fwd_state.accept_wnd;
200
201 WSACancelAsyncRequest(request);
202 if (wnd != NULL) {
203 drain_matching_messages(wnd, WM_SOCK_GOTNAME, (WPARAM) request);
204 }
205 }
206
207 int FWD_check_local_channel_num(PTInstVar pvar, int local_num)
208 {
209 if (local_num < 0 || local_num >= pvar->fwd_state.num_channels
210 || pvar->fwd_state.channels[local_num].status == 0) {
211 UTIL_get_lang_msg("MSG_FWD_LOCAL_CHANNEL_ERROR", pvar,
212 "The server attempted to manipulate a forwarding channel that does not exist.\n"
213 "Either the server has a bug or is hostile. You should close this connection.");
214 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
215 return 0;
216 } else {
217 return 1;
218 }
219 }
220
221 static void request_error(PTInstVar pvar, int request_num, int err)
222 {
223 #ifndef NO_INET6
224 SOCKET FAR *s =
225 pvar->fwd_state.requests[request_num].listening_sockets;
226 int i;
227 #else
228 SOCKET s = pvar->fwd_state.requests[request_num].listening_socket;
229 #endif /* NO_INET6 */
230
231 #ifndef NO_INET6
232 for (i = 0;
233 i < pvar->fwd_state.requests[request_num].num_listening_sockets;
234 ++i) {
235 if (s[i] != INVALID_SOCKET) {
236 safe_closesocket(pvar, s[i]);
237 pvar->fwd_state.requests[request_num].listening_sockets[i] =
238 INVALID_SOCKET;
239 }
240 }
241 #else
242 if (s != INVALID_SOCKET) {
243 safe_closesocket(pvar, s);
244 pvar->fwd_state.requests[request_num].listening_socket =
245 INVALID_SOCKET;
246 }
247 #endif /* NO_INET6 */
248
249 UTIL_get_lang_msg("MSG_FWD_REQUEST_ERROR", pvar,
250 "Communications error while listening for a connection to forward.\n"
251 "The listening port will be terminated.");
252 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
253 }
254
255 static void send_local_connection_closure(PTInstVar pvar, int channel_num)
256 {
257 FWDChannel FAR *channel = pvar->fwd_state.channels + channel_num;
258
259 if ((channel->status & (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED))
260 == (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED)) {
261 SSH_channel_input_eof(pvar, channel->remote_num, channel_num);
262 SSH_channel_output_eof(pvar, channel->remote_num);
263 channel->status |= FWD_CLOSED_LOCAL_IN | FWD_CLOSED_LOCAL_OUT;
264 }
265 }
266
267 static void closed_local_connection(PTInstVar pvar, int channel_num)
268 {
269 FWDChannel FAR *channel = pvar->fwd_state.channels + channel_num;
270
271 if (channel->local_socket != INVALID_SOCKET) {
272 safe_closesocket(pvar, channel->local_socket);
273 channel->local_socket = INVALID_SOCKET;
274
275 send_local_connection_closure(pvar, channel_num);
276 }
277 }
278
279 /* This gets called when a request becomes both deleted and has no
280 active channels. */
281 static void really_delete_request(PTInstVar pvar, int request_num)
282 {
283 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
284
285 if (request->to_host_lookup_handle != 0) {
286 safe_WSACancelAsyncRequest(pvar, request->to_host_lookup_handle);
287 request->to_host_lookup_handle = 0;
288 }
289 #ifndef NO_INET6
290 /*****/
291 /* freeaddrinfo(); */
292 #else
293 free(request->to_host_hostent_buf);
294 request->to_host_hostent_buf = NULL;
295 #endif /* NO_INET6 */
296 }
297
298 void FWD_free_channel(PTInstVar pvar, uint32 local_channel_num)
299 {
300 FWDChannel FAR *channel = &pvar->fwd_state.channels[local_channel_num];
301
302 if (channel->type == TYPE_AGENT) { // TYPE_AGENT でここに来るのは SSH1 のみ
303 buffer_free(channel->agent_msg);
304 // channel_close 時と TTSSH 終了時に2回呼ばれるので、二重 free 防止のため
305 channel->agent_msg = NULL;
306 channel->status = 0;
307 }
308 else { // TYPE_PORTFWD
309 UTIL_destroy_sock_write_buf(&channel->writebuf);
310 if (channel->filter != NULL) {
311 channel->filter(channel->filter_closure, 0, NULL, NULL);
312 channel->filter = NULL;
313 channel->filter_closure = NULL;
314 }
315 channel->status = 0;
316 if (channel->local_socket != INVALID_SOCKET) {
317 safe_closesocket(pvar, channel->local_socket);
318 channel->local_socket = INVALID_SOCKET;
319 }
320 }
321
322 if (channel->request_num >= 0) {
323 FWDRequest FAR *request =
324 &pvar->fwd_state.requests[channel->request_num];
325
326 request->num_channels--;
327 if (request->num_channels == 0
328 && (request->status & FWD_DELETED) != 0) {
329 really_delete_request(pvar, channel->request_num);
330 }
331 channel->request_num = -1;
332 }
333 }
334
335 void FWD_channel_input_eof(PTInstVar pvar, uint32 local_channel_num)
336 {
337 FWDChannel FAR *channel;
338
339 if (!FWD_check_local_channel_num(pvar, local_channel_num))
340 return;
341
342 channel = pvar->fwd_state.channels + local_channel_num;
343
344 if (channel->local_socket != INVALID_SOCKET) {
345 shutdown(channel->local_socket, 1);
346 }
347 channel->status |= FWD_CLOSED_REMOTE_IN;
348 if ((channel->status & FWD_CLOSED_REMOTE_OUT) == FWD_CLOSED_REMOTE_OUT) {
349 closed_local_connection(pvar, local_channel_num);
350 FWD_free_channel(pvar, local_channel_num);
351 }
352 }
353
354 void FWD_channel_output_eof(PTInstVar pvar, uint32 local_channel_num)
355 {
356 FWDChannel FAR *channel;
357
358 if (!FWD_check_local_channel_num(pvar, local_channel_num))
359 return;
360
361 channel = pvar->fwd_state.channels + local_channel_num;
362
363 if (channel->local_socket != INVALID_SOCKET) {
364 shutdown(channel->local_socket, 0);
365 }
366 channel->status |= FWD_CLOSED_REMOTE_OUT;
367 if ((channel->status & FWD_CLOSED_REMOTE_IN) == FWD_CLOSED_REMOTE_IN) {
368 closed_local_connection(pvar, local_channel_num);
369 FWD_free_channel(pvar, local_channel_num);
370 }
371 }
372
373 static char FAR *describe_socket_error(PTInstVar pvar, int code)
374 {
375 switch (code) {
376 case WSAECONNREFUSED:
377 UTIL_get_lang_msg("MSG_FWD_REFUSED_ERROR", pvar,
378 "Connection refused (perhaps the service is not currently running)");
379 return pvar->ts->UIMsg;
380 case WSAENETDOWN:
381 case WSAENETUNREACH:
382 case WSAEHOSTUNREACH:
383 UTIL_get_lang_msg("MSG_FWD_NETDOWN_ERROR", pvar,
384 "The machine could not be contacted (possibly a network problem)");
385 return pvar->ts->UIMsg;
386 case WSAETIMEDOUT:
387 case WSAEHOSTDOWN:
388 UTIL_get_lang_msg("MSG_FWD_MACHINEDOWN_ERROR", pvar,
389 "The machine could not be contacted (possibly the machine is down)");
390 return pvar->ts->UIMsg;
391 case WSATRY_AGAIN:
392 case WSANO_RECOVERY:
393 case WSANO_ADDRESS:
394 case WSAHOST_NOT_FOUND:
395 UTIL_get_lang_msg("MSG_FWD_ADDRNOTFOUTD_ERROR", pvar,
396 "No address was found for the machine");
397 return pvar->ts->UIMsg;
398 default:
399 UTIL_get_lang_msg("MSG_FWD_CONNECT_ERROR", pvar,
400 "The forwarding connection could not be established");
401 return pvar->ts->UIMsg;
402 }
403 }
404
405 static void channel_error(PTInstVar pvar, char FAR * action,
406 int channel_num, int err)
407 {
408 char FAR *err_msg;
409 char uimsg[MAX_UIMSG];
410
411 closed_local_connection(pvar, channel_num);
412
413 switch (err) {
414 case WSAECONNRESET:
415 case WSAECONNABORTED:
416 err_msg = NULL;
417 break;
418 default:
419 strncpy_s(uimsg, sizeof(uimsg), describe_socket_error(pvar, err), _TRUNCATE);
420 err_msg = uimsg;
421 }
422
423 if (err_msg != NULL) {
424 char buf[1024];
425
426 UTIL_get_lang_msg("MSG_FWD_CHANNEL_ERROR", pvar,
427 "Communications error %s forwarded local %s.\n"
428 "%s (code %d).\n"
429 "The forwarded connection will be closed.");
430 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
431 pvar->ts->UIMsg, action,
432 pvar->fwd_state.requests[pvar->fwd_state.channels[channel_num].
433 request_num].spec.from_port_name,
434 err_msg, err);
435 notify_nonfatal_error(pvar, buf);
436 }
437 }
438
439 static void channel_opening_error(PTInstVar pvar, int channel_num, int err)
440 {
441 char buf[1024];
442 FWDChannel FAR *channel = &pvar->fwd_state.channels[channel_num];
443 FWDRequest FAR *request =
444 &pvar->fwd_state.requests[channel->request_num];
445 char uimsg[MAX_UIMSG];
446
447 SSH_fail_channel_open(pvar, channel->remote_num);
448 strncpy_s(uimsg, sizeof(uimsg), describe_socket_error(pvar, err), _TRUNCATE);
449 if (request->spec.type == FWD_REMOTE_X11_TO_LOCAL) {
450 UTIL_get_lang_msg("MSG_FWD_CHANNEL_OPEN_X_ERROR", pvar,
451 "The server attempted to forward a connection through this machine.\n"
452 "It requested a connection to the X server on %s (display %d:%d).\n"
453 "%s.\n" "The forwarded connection will be closed.");
454 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
455 pvar->ts->UIMsg,
456 request->spec.to_host, request->spec.to_port - 6000, request->spec.x11_screen,
457 uimsg);
458 } else {
459 UTIL_get_lang_msg("MSG_FWD_CHANNEL_OPEN_ERROR", pvar,
460 "The server attempted to forward a connection through this machine.\n"
461 "It requested a connection to %s (port %s).\n" "%s.\n"
462 "The forwarded connection will be closed.");
463 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
464 pvar->ts->UIMsg,
465 request->spec.to_host, request->spec.to_port_name,
466 uimsg);
467 }
468 notify_nonfatal_error(pvar, buf);
469 FWD_free_channel(pvar, channel_num);
470 }
471
472 static int alloc_channel(PTInstVar pvar, int new_status,
473 int new_request_num)
474 {
475 int i;
476 int new_num_channels;
477 int new_channel = -1;
478 FWDChannel FAR *channel;
479
480 for (i = 0; i < pvar->fwd_state.num_channels && new_channel < 0; i++) {
481 if (pvar->fwd_state.channels[i].status == 0) {
482 new_channel = i;
483 }
484 }
485
486 if (new_channel < 0) {
487 new_num_channels = pvar->fwd_state.num_channels + 1;
488 pvar->fwd_state.channels =
489 (FWDChannel FAR *) realloc(pvar->fwd_state.channels,
490 sizeof(FWDChannel) *
491 new_num_channels);
492
493 for (; i < new_num_channels; i++) {
494 channel = pvar->fwd_state.channels + i;
495
496 channel->status = 0;
497 channel->local_socket = INVALID_SOCKET;
498 channel->request_num = -1;
499 channel->filter = NULL;
500 channel->filter_closure = NULL;
501 UTIL_init_sock_write_buf(&channel->writebuf);
502 }
503
504 new_channel = pvar->fwd_state.num_channels;
505 pvar->fwd_state.num_channels = new_num_channels;
506 }
507
508 channel = pvar->fwd_state.channels + new_channel;
509
510 channel->status = new_status;
511 channel->request_num = new_request_num;
512 pvar->fwd_state.requests[new_request_num].num_channels++;
513 UTIL_init_sock_write_buf(&channel->writebuf);
514
515 return new_channel;
516 }
517
518 static int alloc_agent_channel(PTInstVar pvar, int remote_channel_num)
519 {
520 int i;
521 int new_num_channels;
522 int new_channel = -1;
523 FWDChannel FAR *channel;
524
525 for (i = 0; i < pvar->fwd_state.num_channels && new_channel < 0; i++) {
526 if (pvar->fwd_state.channels[i].status == 0) {
527 new_channel = i;
528 }
529 }
530
531 if (new_channel < 0) {
532 new_num_channels = pvar->fwd_state.num_channels + 1;
533 pvar->fwd_state.channels =
534 (FWDChannel FAR *) realloc(pvar->fwd_state.channels,
535 sizeof(FWDChannel) *
536 new_num_channels);
537
538 new_channel = pvar->fwd_state.num_channels;
539 pvar->fwd_state.num_channels = new_num_channels;
540 }
541
542 channel = pvar->fwd_state.channels + new_channel;
543 channel->status = FWD_AGENT_DUMMY;
544 channel->remote_num = remote_channel_num;
545 channel->request_num = -1;
546 channel->type = TYPE_AGENT;
547 channel->agent_msg = buffer_init();
548 channel->agent_request_len = 0;
549
550 return new_channel;
551 }
552
553 static HWND make_accept_wnd(PTInstVar pvar)
554 {
555 if (pvar->fwd_state.accept_wnd == NULL) {
556 UTIL_get_lang_msg("DLG_FWDMON_TITLE", pvar, "TTSSH Port Forwarding Monitor");
557 pvar->fwd_state.accept_wnd =
558 CreateWindow("STATIC", pvar->ts->UIMsg,
559 WS_DISABLED | WS_POPUP, 0, 0, 1, 1, NULL, NULL,
560 hInst, NULL);
561 if (pvar->fwd_state.accept_wnd != NULL) {
562 pvar->fwd_state.old_accept_wnd_proc =
563 (WNDPROC) SetWindowLong(pvar->fwd_state.accept_wnd,
564 GWL_WNDPROC,
565 (LONG) accept_wnd_proc);
566 SetWindowLong(pvar->fwd_state.accept_wnd, GWL_USERDATA,
567 (LONG) pvar);
568 }
569 }
570
571 return pvar->fwd_state.accept_wnd;
572 }
573
574 static void connected_local_connection(PTInstVar pvar, int channel_num)
575 {
576 SSH_confirm_channel_open(pvar,
577 pvar->fwd_state.channels[channel_num].
578 remote_num, channel_num);
579 pvar->fwd_state.channels[channel_num].status |= FWD_LOCAL_CONNECTED;
580 }
581
582 static void make_local_connection(PTInstVar pvar, int channel_num)
583 {
584 FWDChannel FAR *channel = pvar->fwd_state.channels + channel_num;
585 FWDRequest FAR *request =
586 pvar->fwd_state.requests + channel->request_num;
587 #ifndef NO_INET6
588 for (channel->to_host_addrs = request->to_host_addrs;
589 channel->to_host_addrs;
590 channel->to_host_addrs = channel->to_host_addrs->ai_next) {
591 channel->local_socket = socket(channel->to_host_addrs->ai_family,
592 channel->to_host_addrs->ai_socktype,
593 channel->to_host_addrs->ai_protocol);
594 if (channel->local_socket == INVALID_SOCKET)
595 continue;
596 if (WSAAsyncSelect
597 (channel->local_socket, make_accept_wnd(pvar), WM_SOCK_IO,
598 FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE) == SOCKET_ERROR) {
599 closesocket(channel->local_socket);
600 channel->local_socket = INVALID_SOCKET;
601 continue;
602 }
603 if (connect(channel->local_socket,
604 channel->to_host_addrs->ai_addr,
605 channel->to_host_addrs->ai_addrlen) != SOCKET_ERROR) {
606 connected_local_connection(pvar, channel_num);
607 return;
608 } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
609 /* do nothing, we'll just wait */
610 return;
611 } else {
612 /* connect() failed */
613 closesocket(channel->local_socket);
614 channel->local_socket = INVALID_SOCKET;
615 continue;
616 }
617 }
618
619 channel_opening_error(pvar, channel_num, WSAGetLastError());
620 #else
621 struct sockaddr_in addr;
622
623 addr.sin_family = AF_INET;
624 addr.sin_port = htons((unsigned short) request->spec.to_port);
625 addr.sin_addr.s_addr = htonl(request->to_host_addr);
626
627 if ((channel->local_socket =
628 socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET
629 && WSAAsyncSelect(channel->local_socket, make_accept_wnd(pvar),
630 WM_SOCK_IO,
631 FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE) !=
632 SOCKET_ERROR) {
633 if (connect
634 (channel->local_socket, (struct sockaddr FAR *) &addr,
635 sizeof(addr)) != SOCKET_ERROR) {
636 connected_local_connection(pvar, channel_num);
637 return;
638 } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
639 /* do nothing, we'll just wait */
640 return;
641 }
642 }
643
644 channel_opening_error(pvar, channel_num, WSAGetLastError());
645 #endif /* NO_INET6 */
646 }
647
648 #ifndef NO_INET6
649 static void accept_local_connection(PTInstVar pvar, int request_num,
650 int listening_socket_num)
651 {
652 #else
653 static void accept_local_connection(PTInstVar pvar, int request_num)
654 {
655 #endif /* NO_INET6 */
656 int channel_num;
657 SOCKET s;
658 #ifndef NO_INET6
659 struct sockaddr_storage addr;
660 char hname[NI_MAXHOST];
661 char strport[NI_MAXSERV]; // ws2tcpip.h
662 #else
663 struct sockaddr addr;
664 #endif /* NO_INET6 */
665 int addrlen = sizeof(addr);
666 char buf[1024];
667 #ifndef INET6
668 BYTE FAR *IP;
669 #endif /* NO_INET6 */
670 FWDChannel FAR *channel;
671 FWDRequest FAR *request = &pvar->fwd_state.requests[request_num];
672 BOOL is_localhost = FALSE;
673
674 #ifndef NO_INET6
675 s = accept(request->listening_sockets[listening_socket_num],
676 (struct sockaddr FAR *) &addr, &addrlen);
677 #else
678 s = accept(request->listening_socket, &addr, &addrlen);
679 #endif /* NO_INET6 */
680 if (s == INVALID_SOCKET)
681 return;
682
683 #ifndef INET6
684 IP = (BYTE FAR *) & ((struct sockaddr_in *) (&addr))->sin_addr.s_addr;
685 #endif
686
687 #ifndef NO_INET6
688 // SSH2 port-forwardingに接続元のリモートポートが必要。(2005.2.27 yutaka)
689 if (getnameinfo
690 ((struct sockaddr FAR *) &addr, addrlen, hname, sizeof(hname),
691 strport, sizeof(strport), NI_NUMERICHOST | NI_NUMERICSERV)) {
692 /* NOT REACHED */
693 }
694 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
695 "Host %s connecting to port %d; forwarding to %s:%d",
696 hname, request->spec.from_port, request->spec.to_host,
697 request->spec.to_port);
698 #else
699 _snprintf(buf, sizeof(buf),
700 "Host %d.%d.%d.%d connecting to port %d; forwarding to %s:%d",
701 IP[0], IP[1], IP[2], IP[3], request->spec.from_port,
702 request->spec.to_host, request->spec.to_port);
703 buf[NUM_ELEM(buf) - 1] = 0;
704 #endif /* NO_INET6 */
705 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
706
707 #ifndef NO_INET6
708 strncpy_s(buf, sizeof(buf), hname, _TRUNCATE);
709 #else
710 _snprintf(buf, sizeof(buf), "%d.%d.%d.%d", IP[0], IP[1], IP[2], IP[3]);
711 buf[NUM_ELEM(buf) - 1] = 0;
712 #endif
713
714 channel_num = alloc_channel(pvar, FWD_LOCAL_CONNECTED, request_num);
715 channel = pvar->fwd_state.channels + channel_num;
716
717 channel->local_socket = s;
718 channel->filter_closure = NULL;
719 channel->filter = NULL;
720
721 // add originator-port (2005.2.27 yutaka)
722 SSH_open_channel(pvar, channel_num, request->spec.to_host,
723 request->spec.to_port, buf, atoi(strport));
724 }
725
726 static void write_local_connection_buffer(PTInstVar pvar, int channel_num)
727 {
728 FWDChannel FAR *channel = pvar->fwd_state.channels + channel_num;
729
730 if ((channel->status & (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED))
731 == (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED)) {
732 if (!UTIL_sock_write_more
733 (pvar, &channel->writebuf, channel->local_socket)) {
734 channel_error(pvar, "writing", channel_num, WSAGetLastError());
735 }
736 }
737 }
738
739 static void read_local_connection(PTInstVar pvar, int channel_num)
740 {
741 FWDChannel FAR *channel = pvar->fwd_state.channels + channel_num;
742
743 if ((channel->status & (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED))
744 != (FWD_REMOTE_CONNECTED | FWD_LOCAL_CONNECTED)) {
745 return;
746 }
747
748 while (channel->local_socket != INVALID_SOCKET) {
749 char buf[CHANNEL_READ_BUF_SIZE];
750 int amount = recv(channel->local_socket, buf, sizeof(buf), 0);
751 int err;
752
753 if (amount > 0) {
754 char FAR *new_buf = buf;
755 int action = FWD_FILTER_RETAIN;
756
757 if (channel->filter != NULL) {
758 action =
759 channel->filter(channel->filter_closure,
760 FWD_FILTER_FROM_CLIENT, &amount,
761 &new_buf);
762 }
763
764 if (amount > 0
765 && (channel->status & FWD_CLOSED_REMOTE_OUT) == 0) {
766 // ポートフォワーディングにおいてクライアントからの送信要求を、SSH通信に乗せてサーバまで送り届ける。
767 SSH_channel_send(pvar, channel_num, channel->remote_num, new_buf,
768 amount);
769 }
770
771 switch (action) {
772 case FWD_FILTER_REMOVE:
773 channel->filter(channel->filter_closure, 0, NULL, NULL);
774 channel->filter = NULL;
775 channel->filter_closure = NULL;
776 break;
777 case FWD_FILTER_CLOSECHANNEL:
778 closed_local_connection(pvar, channel_num);
779 break;
780 }
781 } else if (amount == 0
782 || (err = WSAGetLastError()) == WSAEWOULDBLOCK) {
783 return;
784 } else {
785 channel_error(pvar, "reading", channel_num, err);
786 return;
787 }
788 }
789 }
790
791 static void failed_to_host_addr(PTInstVar pvar, int request_num, int err)
792 {
793 int i;
794
795 for (i = 0; i < pvar->fwd_state.num_channels; i++) {
796 if (pvar->fwd_state.channels[i].request_num == request_num) {
797 channel_opening_error(pvar, i, err);
798 }
799 }
800 }
801
802 static void found_to_host_addr(PTInstVar pvar, int request_num)
803 {
804 int i;
805
806 #ifdef NO_INET6
807 pvar->fwd_state.requests[request_num].to_host_addr =
808 ntohl(*(uint32 FAR *)
809 ((HOSTENT FAR *) pvar->fwd_state.requests[request_num].
810 to_host_hostent_buf)->h_addr_list[0]);
811 #endif /* NO_INET6 */
812
813 for (i = 0; i < pvar->fwd_state.num_channels; i++) {
814 if (pvar->fwd_state.channels[i].request_num == request_num) {
815 make_local_connection(pvar, i);
816 }
817 }
818 }
819
820 static LRESULT CALLBACK accept_wnd_proc(HWND wnd, UINT msg, WPARAM wParam,
821 LPARAM lParam)
822 {
823 PTInstVar pvar = (PTInstVar) GetWindowLong(wnd, GWL_USERDATA);
824
825 if (msg == WM_SOCK_ACCEPT &&
826 (LOWORD(lParam) == FD_READ || LOWORD(lParam) == FD_CLOSE ||
827 LOWORD(lParam) == FD_WRITE)) {
828 msg = WM_SOCK_IO;
829 }
830
831 switch (msg) {
832 case WM_SOCK_ACCEPT:{
833 int request_num = find_request_num(pvar, (SOCKET) wParam);
834
835 if (request_num < 0)
836 return TRUE;
837
838 if (HIWORD(lParam) != 0) {
839 request_error(pvar, request_num, HIWORD(lParam));
840 } else {
841 #ifndef NO_INET6
842 int listening_socket_num;
843 #endif /* NO_INET6 */
844 switch (LOWORD(lParam)) {
845 case FD_ACCEPT:
846 #ifndef NO_INET6
847 listening_socket_num =
848 find_listening_socket_num(pvar, request_num,
849 (SOCKET) wParam);
850 if (listening_socket_num == -1)
851 return FALSE;
852 accept_local_connection(pvar, request_num,
853 listening_socket_num);
854 #else
855 accept_local_connection(pvar, request_num);
856 #endif /* NO_INET6 */
857 break;
858 }
859 }
860 return TRUE;
861 }
862
863 case WM_SOCK_GOTNAME:{
864 int request_num =
865 find_request_num_from_async_request(pvar, (HANDLE) wParam);
866
867 if (request_num < 0)
868 return TRUE;
869
870 if (HIWORD(lParam) != 0) {
871 failed_to_host_addr(pvar, request_num, HIWORD(lParam));
872 } else {
873 found_to_host_addr(pvar, request_num);
874 }
875 pvar->fwd_state.requests[request_num].to_host_lookup_handle = 0;
876 #ifdef NO_INET6
877 free(pvar->fwd_state.requests[request_num].
878 to_host_hostent_buf);
879 pvar->fwd_state.requests[request_num].to_host_hostent_buf =
880 NULL;
881 #endif /* NO_INET6 */
882 return TRUE;
883 }
884
885 case WM_SOCK_IO:{
886 int channel_num = find_channel_num(pvar, (SOCKET) wParam);
887 #ifndef NO_INET6
888 FWDChannel FAR *channel =
889 pvar->fwd_state.channels + channel_num;
890 #endif /* NO_INET6 */
891
892 if (channel_num < 0)
893 return TRUE;
894
895 if (HIWORD(lParam) != 0) {
896 #ifndef NO_INET6
897 if (LOWORD(lParam) == FD_CONNECT) {
898 if (channel->to_host_addrs->ai_next == NULL) {
899 /* all protocols were failed */
900 channel_opening_error(pvar, channel_num,
901 HIWORD(lParam));
902 } else {
903 for (channel->to_host_addrs =
904 channel->to_host_addrs->ai_next;
905 channel->to_host_addrs;
906 channel->to_host_addrs =
907 channel->to_host_addrs->ai_next) {
908 channel->local_socket =
909 socket(channel->to_host_addrs->ai_family,
910 channel->to_host_addrs->ai_socktype,
911 channel->to_host_addrs->ai_protocol);
912 if (channel->local_socket == INVALID_SOCKET)
913 continue;
914 if (WSAAsyncSelect
915 (channel->local_socket,
916 make_accept_wnd(pvar), WM_SOCK_IO,
917 FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE
918 ) == SOCKET_ERROR) {
919 closesocket(channel->local_socket);
920 channel->local_socket = INVALID_SOCKET;
921 continue;
922 }
923 if (connect(channel->local_socket,
924 channel->to_host_addrs->ai_addr,
925 channel->to_host_addrs->ai_addrlen
926 ) != SOCKET_ERROR) {
927 connected_local_connection(pvar,
928 channel_num);
929 return TRUE;
930 } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
931 /* do nothing, we'll just wait */
932 return TRUE;
933 } else {
934 closesocket(channel->local_socket);
935 channel->local_socket = INVALID_SOCKET;
936 continue;
937 }
938 }
939 channel_opening_error(pvar, channel_num,
940 HIWORD(lParam));
941 return TRUE;
942 }
943 } else {
944 channel_error(pvar, "accessing", channel_num,
945 HIWORD(lParam));
946 return TRUE;
947 }
948 #else
949 if (LOWORD(lParam) == FD_CONNECT) {
950 channel_opening_error(pvar, channel_num,
951 HIWORD(lParam));
952 } else {
953 channel_error(pvar, "accessing", channel_num,
954 HIWORD(lParam));
955 }
956 #endif /* NO_INET6 */
957 } else {
958 switch (LOWORD(lParam)) {
959 case FD_CONNECT:
960 connected_local_connection(pvar, channel_num);
961 break;
962 case FD_READ:
963 read_local_connection(pvar, channel_num);
964 break;
965 case FD_CLOSE:
966 read_local_connection(pvar, channel_num);
967 closed_local_connection(pvar, channel_num);
968 break;
969 case FD_WRITE:
970 write_local_connection_buffer(pvar, channel_num);
971 break;
972 }
973 }
974 return TRUE;
975 }
976 }
977
978 return CallWindowProc(pvar->fwd_state.old_accept_wnd_proc, wnd, msg,
979 wParam, lParam);
980 }
981
982 int FWD_compare_specs(void const FAR * void_spec1,
983 void const FAR * void_spec2)
984 {
985 FWDRequestSpec FAR *spec1 = (FWDRequestSpec FAR *) void_spec1;
986 FWDRequestSpec FAR *spec2 = (FWDRequestSpec FAR *) void_spec2;
987 int delta = spec1->from_port - spec2->from_port;
988
989 if (delta == 0) {
990 delta = spec1->type - spec2->type;
991 }
992
993 if (delta == 0) {
994 delta = strcmp(spec1->bind_address, spec2->bind_address);
995 }
996
997 return delta;
998 }
999
1000 /* Check if the server can listen for 'spec' using the old listening spec 'listener'.
1001 We check that the to_port and (for non-X connections) the to_host are equal
1002 so that we never lie to the server about where its forwarded connection is
1003 ending up. Maybe some SSH implementation depends on this information being
1004 reliable, for security? */
1005 static BOOL can_server_listen_using(FWDRequestSpec FAR * listener,
1006 FWDRequestSpec FAR * spec)
1007 {
1008 return listener->type == spec->type
1009 && listener->from_port == spec->from_port
1010 && listener->to_port == spec->to_port
1011 && (spec->type == FWD_REMOTE_X11_TO_LOCAL
1012 || strcmp(listener->to_host, spec->to_host) == 0)
1013 && (spec->type == FWD_REMOTE_X11_TO_LOCAL
1014 || strcmp(listener->bind_address, spec->bind_address) == 0);
1015 }
1016
1017 BOOL FWD_can_server_listen_for(PTInstVar pvar, FWDRequestSpec FAR * spec)
1018 {
1019 int num_server_listening_requests =
1020 pvar->fwd_state.num_server_listening_specs;
1021
1022 if (num_server_listening_requests < 0) {
1023 return TRUE;
1024 } else {
1025 FWDRequestSpec FAR *listener =
1026 bsearch(spec, pvar->fwd_state.server_listening_specs,
1027 num_server_listening_requests,
1028 sizeof(FWDRequestSpec), FWD_compare_specs);
1029
1030 if (listener == NULL) {
1031 return FALSE;
1032 } else {
1033 return can_server_listen_using(listener, spec);
1034 }
1035 }
1036 }
1037
1038 int FWD_get_num_request_specs(PTInstVar pvar)
1039 {
1040 int num_request_specs = 0;
1041 int i;
1042
1043 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1044 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0) {
1045 num_request_specs++;
1046 }
1047 }
1048
1049 return num_request_specs;
1050 }
1051
1052 void FWD_get_request_specs(PTInstVar pvar, FWDRequestSpec FAR * specs,
1053 int num_specs)
1054 {
1055 int i;
1056
1057 for (i = 0; i < pvar->fwd_state.num_requests && num_specs > 0; i++) {
1058 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0) {
1059 *specs = pvar->fwd_state.requests[i].spec;
1060 num_specs--;
1061 specs++;
1062 }
1063 }
1064 }
1065
1066 /* This function can be called while channels remain open on the request.
1067 Take care.
1068 It returns the listening socket for the request, if there is one.
1069 The caller must close this socket if it is not INVALID_SOCKET.
1070 */
1071 #ifndef NO_INET6
1072 static SOCKET FAR *delete_request(PTInstVar pvar, int request_num,
1073 int *p_num_listening_sockets)
1074 {
1075 #else
1076 static SOCKET delete_request(PTInstVar pvar, int request_num)
1077 {
1078 #endif /* NO_INET6 */
1079 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
1080 #ifndef NO_INET6
1081 SOCKET FAR *lp_listening_sockets;
1082 #else
1083 SOCKET result = INVALID_SOCKET;
1084 #endif /* NO_INET6 */
1085
1086 /* safe to shut down the listening socket here. Any pending connections
1087 that haven't yet been turned into channels will be broken, but that's
1088 just tough luck. */
1089 #ifndef NO_INET6
1090 *p_num_listening_sockets = request->num_listening_sockets;
1091 lp_listening_sockets = request->listening_sockets;
1092 if (request->listening_sockets != NULL) {
1093 request->num_listening_sockets = 0;
1094 request->listening_sockets = NULL;
1095 }
1096
1097 request->status |= FWD_DELETED;
1098
1099 if (request->num_channels == 0) {
1100 really_delete_request(pvar, request_num);
1101 }
1102
1103 return lp_listening_sockets;
1104 #else
1105 if (request->listening_socket != INVALID_SOCKET) {
1106 result = request->listening_socket;
1107 request->listening_socket = INVALID_SOCKET;
1108 }
1109
1110 request->status |= FWD_DELETED;
1111
1112 if (request->num_channels == 0) {
1113 really_delete_request(pvar, request_num);
1114 }
1115
1116 return result;
1117 #endif /* NO_INET6 */
1118 }
1119
1120 static BOOL are_specs_identical(FWDRequestSpec FAR * spec1,
1121 FWDRequestSpec FAR * spec2)
1122 {
1123 return spec1->type == spec2->type
1124 && spec1->from_port == spec2->from_port
1125 && spec1->to_port == spec2->to_port
1126 && strcmp(spec1->to_host, spec2->to_host) == 0
1127 && strcmp(spec1->bind_address, spec2->bind_address) == 0;
1128 }
1129
1130 static BOOL interactive_init_request(PTInstVar pvar, int request_num,
1131 BOOL report_error)
1132 {
1133 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
1134
1135 if (request->spec.type == FWD_LOCAL_TO_REMOTE) {
1136 #ifndef NO_INET6
1137 struct addrinfo hints;
1138 struct addrinfo FAR *res;
1139 struct addrinfo FAR *res0;
1140 SOCKET s;
1141 char pname[NI_MAXSERV];
1142 char bname[NI_MAXHOST];
1143
1144 _snprintf_s(pname, sizeof(pname), _TRUNCATE,
1145 "%d", request->spec.from_port);
1146 _snprintf_s(bname, sizeof(bname), _TRUNCATE,
1147 "%s", request->spec.bind_address);
1148 memset(&hints, 0, sizeof(hints));
1149 hints.ai_family = AF_UNSPEC; /* a user will be able to specify protocol in future version */
1150 hints.ai_flags = AI_PASSIVE;
1151 hints.ai_socktype = SOCK_STREAM;
1152 if (getaddrinfo(bname, pname, &hints, &res0))
1153 return FALSE;
1154
1155 /* count number of listening sockets and allocate area for them */
1156 for (request->num_listening_sockets = 0, res = res0; res;
1157 res = res->ai_next)
1158 request->num_listening_sockets++;
1159 request->listening_sockets =
1160 (SOCKET FAR *) malloc(sizeof(SOCKET) *
1161 request->num_listening_sockets);
1162 if (request->listening_sockets == NULL) {
1163 freeaddrinfo(res0);
1164 return FALSE;
1165 }
1166
1167 for (request->num_listening_sockets = 0, res = res0; res;
1168 res = res->ai_next) {
1169 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1170 request->listening_sockets[request->num_listening_sockets++] = s;
1171 if (s == INVALID_SOCKET)
1172 continue;
1173 if (bind(s, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
1174 s = INVALID_SOCKET;
1175 continue;
1176 }
1177 if (WSAAsyncSelect
1178 (s, make_accept_wnd(pvar), WM_SOCK_ACCEPT,
1179 FD_ACCEPT | FD_READ | FD_CLOSE | FD_WRITE
1180 ) == SOCKET_ERROR) {
1181 s = INVALID_SOCKET;
1182 continue;
1183 }
1184 if (listen(s, SOMAXCONN) == SOCKET_ERROR) {
1185 s = INVALID_SOCKET;
1186 continue;
1187 }
1188 }
1189 if (s == INVALID_SOCKET) {
1190 if (report_error) {
1191 char buf[256];
1192 UTIL_get_lang_msg("MSG_FWD_SOCKET_ERROR", pvar,
1193 "Some socket(s) required for port forwarding could not be initialized.\n"
1194 "Some port forwarding services may not be available.\n"
1195 "(errno %d)");
1196 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1197 pvar->ts->UIMsg, WSAGetLastError());
1198 notify_verbose_message(pvar,buf,LOG_LEVEL_WARNING);
1199 }
1200 freeaddrinfo(res0);
1201 /* free(request->listening_sockets); /* DO NOT FREE HERE, listening_sockets'll be freed in FWD_end */
1202 return FALSE;
1203 }
1204 freeaddrinfo(res0);
1205 }
1206
1207 return TRUE;
1208 #else
1209 SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
1210 struct sockaddr_in addr;
1211
1212 addr.sin_family = AF_INET;
1213 addr.sin_port = htons((unsigned short) request->spec.from_port);
1214 addr.sin_addr.s_addr = htonl(INADDR_ANY);
1215
1216 request->listening_socket = s;
1217 if (s == INVALID_SOCKET
1218 || WSAAsyncSelect(s, make_accept_wnd(pvar), WM_SOCK_ACCEPT,
1219 FD_ACCEPT | FD_READ | FD_CLOSE | FD_WRITE) ==
1220 SOCKET_ERROR
1221 || bind(s, (struct sockaddr FAR *) &addr,
1222 sizeof(addr)) == SOCKET_ERROR
1223 || listen(s, SOMAXCONN) == SOCKET_ERROR) {
1224 if (report_error) {
1225 notify_nonfatal_error(pvar,
1226 "Some socket(s) required for port forwarding could not be initialized.\n"
1227 "Some port forwarding services may not be available.");
1228 }
1229 return FALSE;
1230 }
1231 }
1232
1233 return TRUE;
1234 #endif /* NO_INET6 */
1235 }
1236
1237 /* This function will only be called on a request when all its channels are
1238 closed. */
1239 #ifndef NO_INET6
1240 static BOOL init_request(PTInstVar pvar, int request_num,
1241 BOOL report_error, SOCKET FAR * listening_sockets,
1242 int num_listening_sockets)
1243 {
1244 #else
1245 static BOOL init_request(PTInstVar pvar, int request_num,
1246 BOOL report_error, SOCKET listening_socket)
1247 {
1248 #endif /* NO_INET6 */
1249 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
1250
1251 #ifndef NO_INET6
1252 request->num_listening_sockets = 0;
1253 request->listening_sockets = NULL;
1254 request->to_host_addrs = NULL;
1255 request->to_host_lookup_handle = 0;
1256 request->status = 0;
1257
1258 if (pvar->fwd_state.in_interactive_mode) {
1259 if (listening_sockets != NULL) {
1260 request->num_listening_sockets = num_listening_sockets;
1261 request->listening_sockets = listening_sockets;
1262 return TRUE;
1263 } else {
1264 return interactive_init_request(pvar, request_num,
1265 report_error);
1266 }
1267 } else {
1268 assert(listening_sockets == NULL);
1269 return TRUE;
1270 }
1271 #else
1272 request->listening_socket = INVALID_SOCKET;
1273 request->to_host_addr = 0;
1274 request->to_host_hostent_buf = NULL;
1275 request->to_host_lookup_handle = 0;
1276 request->status = 0;
1277
1278 if (pvar->fwd_state.in_interactive_mode) {
1279 if (listening_socket != INVALID_SOCKET) {
1280 request->listening_socket = listening_socket;
1281 return TRUE;
1282 } else {
1283 return interactive_init_request(pvar, request_num,
1284 report_error);
1285 }
1286 } else {
1287 assert(listening_socket == INVALID_SOCKET);
1288 return TRUE;
1289 }
1290 #endif /* NO_INET6 */
1291 }
1292
1293 void FWD_set_request_specs(PTInstVar pvar, FWDRequestSpec FAR * specs,
1294 int num_specs)
1295 {
1296 FWDRequestSpec FAR *new_specs =
1297 (FWDRequestSpec FAR *) malloc(sizeof(FWDRequestSpec) * num_specs);
1298 char FAR *specs_accounted_for;
1299 #ifndef NO_INET6
1300 typedef struct _saved_sockets {
1301 SOCKET FAR *listening_sockets;
1302 int num_listening_sockets;
1303 } saved_sockets_t;
1304 saved_sockets_t FAR *ptr_to_saved_sockets;
1305 #else
1306 SOCKET FAR *saved_sockets;
1307 #endif /* NO_INET6 */
1308 int i;
1309 int num_new_requests = num_specs;
1310 int num_free_requests = 0;
1311 int free_request = 0;
1312 BOOL report_err = TRUE;
1313
1314 memcpy(new_specs, specs, sizeof(FWDRequestSpec) * num_specs);
1315 qsort(new_specs, num_specs, sizeof(FWDRequestSpec), FWD_compare_specs);
1316
1317 for (i = 0; i < num_specs - 1; i++) {
1318 if (FWD_compare_specs(new_specs + i, new_specs + i + 1) == 0) {
1319 UTIL_get_lang_msg("MSG_FWD_DUPLICATE_ERROR", pvar,
1320 "TTSSH INTERNAL ERROR: Could not set port forwards because duplicate type/port requests were found");
1321 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1322 free(new_specs);
1323 return;
1324 }
1325 }
1326
1327 specs_accounted_for = (char FAR *) malloc(sizeof(char) * num_specs);
1328 #ifndef NO_INET6
1329 ptr_to_saved_sockets =
1330 (saved_sockets_t FAR *) malloc(sizeof(saved_sockets_t) *
1331 num_specs);
1332 #else
1333 saved_sockets = (SOCKET FAR *) malloc(sizeof(SOCKET) * num_specs);
1334 #endif /* NO_INET6 */
1335
1336 memset(specs_accounted_for, 0, num_specs);
1337 for (i = 0; i < num_specs; i++) {
1338 #ifndef NO_INET6
1339 ptr_to_saved_sockets[i].listening_sockets = NULL;
1340 ptr_to_saved_sockets[i].num_listening_sockets = 0;
1341 #else
1342 saved_sockets[i] = INVALID_SOCKET;
1343 #endif /* NO_INET6 */
1344 }
1345
1346 for (i = pvar->fwd_state.num_requests - 1; i >= 0; i--) {
1347 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0) {
1348 FWDRequestSpec FAR *cur_spec =
1349 &pvar->fwd_state.requests[i].spec;
1350 FWDRequestSpec FAR *new_spec =
1351 bsearch(cur_spec, new_specs, num_specs,
1352 sizeof(FWDRequestSpec), FWD_compare_specs);
1353
1354 if (new_spec != NULL
1355 && are_specs_identical(cur_spec, new_spec)) {
1356 specs_accounted_for[new_spec - new_specs] = 1;
1357 num_new_requests--;
1358 } else {
1359 #ifndef NO_INET6
1360 int num_listening_sockets;
1361 SOCKET FAR *listening_sockets;
1362 listening_sockets =
1363 delete_request(pvar, i, &num_listening_sockets);
1364 #else
1365 SOCKET listening_socket = delete_request(pvar, i);
1366 #endif /* NO_INET6 */
1367
1368 #ifndef NO_INET6
1369 if (new_spec != NULL) {
1370 ptr_to_saved_sockets[new_spec - new_specs].
1371 listening_sockets = listening_sockets;
1372 ptr_to_saved_sockets[new_spec - new_specs].
1373 num_listening_sockets = num_listening_sockets;
1374 } else if (listening_sockets != NULL) {
1375 /* if there is no new spec(new request), free listening_sockets */
1376 int i;
1377 for (i = 0; i < num_listening_sockets; ++i)
1378 safe_closesocket(pvar, listening_sockets[i]);
1379 }
1380 #else
1381 if (new_spec != NULL) {
1382 saved_sockets[new_spec - new_specs] = listening_socket;
1383 } else if (listening_socket != INVALID_SOCKET) {
1384 safe_closesocket(pvar, listening_socket);
1385 }
1386 #endif /* NO_INET6 */
1387
1388 if (pvar->fwd_state.requests[i].num_channels == 0) {
1389 num_free_requests++;
1390 }
1391 }
1392 } else {
1393 if (pvar->fwd_state.requests[i].num_channels == 0) {
1394 num_free_requests++;
1395 }
1396 }
1397 }
1398
1399 if (num_new_requests > num_free_requests) {
1400 int total_requests =
1401 pvar->fwd_state.num_requests + num_new_requests - num_free_requests;
1402
1403 pvar->fwd_state.requests =
1404 (FWDRequest FAR *) realloc(pvar->fwd_state.requests,
1405 sizeof(FWDRequest) *
1406 total_requests);
1407 for (i = pvar->fwd_state.num_requests; i < total_requests; i++) {
1408 pvar->fwd_state.requests[i].status = FWD_DELETED;
1409 pvar->fwd_state.requests[i].num_channels = 0;
1410 }
1411 pvar->fwd_state.num_requests = total_requests;
1412 }
1413
1414 for (i = 0; i < num_specs; i++) {
1415 if (!specs_accounted_for[i]) {
1416 while ((pvar->fwd_state.requests[free_request].status & FWD_DELETED) == 0
1417 || pvar->fwd_state.requests[free_request].num_channels != 0) {
1418 free_request++;
1419 }
1420
1421 assert(free_request < pvar->fwd_state.num_requests);
1422
1423 pvar->fwd_state.requests[free_request].spec = new_specs[i];
1424 #ifndef NO_INET6
1425 if (!init_request(pvar, free_request, report_err,
1426 ptr_to_saved_sockets[i].listening_sockets,
1427 ptr_to_saved_sockets[i].num_listening_sockets)) {
1428 #else
1429 if (!init_request
1430 (pvar, free_request, report_err, saved_sockets[i])) {
1431 #endif /* NO_INET6 */
1432 report_err = FALSE;
1433 }
1434
1435 free_request++;
1436 }
1437 }
1438
1439 #ifndef NO_INET6
1440 free(ptr_to_saved_sockets);
1441 #else
1442 free(saved_sockets);
1443 #endif /* NO_INET6 */
1444 free(specs_accounted_for);
1445 free(new_specs);
1446 }
1447
1448 void FWD_prep_forwarding(PTInstVar pvar)
1449 {
1450 int i;
1451 int num_server_listening_requests = 0;
1452
1453 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1454 FWDRequest FAR *request = pvar->fwd_state.requests + i;
1455
1456 if ((request->status & FWD_DELETED) == 0) {
1457 switch (request->spec.type) {
1458 case FWD_REMOTE_TO_LOCAL:
1459 SSH_request_forwarding(pvar,
1460 request->spec.bind_address,
1461 request->spec.from_port,
1462 request->spec.to_host,
1463 request->spec.to_port);
1464 num_server_listening_requests++;
1465 break;
1466 case FWD_REMOTE_X11_TO_LOCAL:{
1467 int screen_num = request->spec.x11_screen;
1468
1469 pvar->fwd_state.X11_auth_data =
1470 X11_load_local_auth_data(screen_num);
1471 SSH_request_X11_forwarding(pvar,
1472 X11_get_spoofed_protocol_name
1473 (pvar->fwd_state.X11_auth_data),
1474 X11_get_spoofed_protocol_data
1475 (pvar->fwd_state.X11_auth_data),
1476 X11_get_spoofed_protocol_data_len
1477 (pvar->fwd_state.X11_auth_data),
1478 screen_num);
1479 num_server_listening_requests++;
1480 break;
1481 }
1482 }
1483 }
1484 }
1485
1486 pvar->fwd_state.num_server_listening_specs =
1487 num_server_listening_requests;
1488
1489 if (num_server_listening_requests > 0) {
1490 FWDRequestSpec FAR *server_listening_requests =
1491 (FWDRequestSpec FAR *) malloc(sizeof(FWDRequestSpec) *
1492 num_server_listening_requests);
1493
1494 pvar->fwd_state.server_listening_specs = server_listening_requests;
1495
1496 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1497 if ((pvar->fwd_state.requests[i].status & FWD_DELETED) == 0) {
1498 switch (pvar->fwd_state.requests[i].spec.type) {
1499 case FWD_REMOTE_X11_TO_LOCAL:
1500 case FWD_REMOTE_TO_LOCAL:
1501 *server_listening_requests =
1502 pvar->fwd_state.requests[i].spec;
1503 server_listening_requests++;
1504 break;
1505 }
1506 }
1507 }
1508
1509 /* No two server-side request specs can have the same port. */
1510 qsort(pvar->fwd_state.server_listening_specs,
1511 num_server_listening_requests, sizeof(FWDRequestSpec),
1512 FWD_compare_specs);
1513 }
1514 }
1515
1516 void FWD_enter_interactive_mode(PTInstVar pvar)
1517 {
1518 BOOL report_error = TRUE;
1519 int i;
1520
1521 pvar->fwd_state.in_interactive_mode = TRUE;
1522
1523 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1524 if (!interactive_init_request(pvar, i, report_error)) {
1525 report_error = FALSE;
1526 }
1527 }
1528 }
1529
1530 static void create_local_channel(PTInstVar pvar, uint32 remote_channel_num,
1531 int request_num, void *filter_closure,
1532 FWDFilter filter, int *chan_num)
1533 {
1534 char buf[1024];
1535 int channel_num;
1536 FWDChannel FAR *channel;
1537 FWDRequest FAR *request = pvar->fwd_state.requests + request_num;
1538 #ifndef NO_INET6
1539 struct addrinfo hints;
1540 char pname[NI_MAXSERV];
1541 #endif /* NO_INET6 */
1542
1543 #ifndef NO_INET6
1544 if (request->to_host_addrs == NULL
1545 && request->to_host_lookup_handle == 0) {
1546 HANDLE task_handle;
1547 #else
1548 if (request->to_host_addr == 0 && request->to_host_lookup_handle == 0) {
1549 HANDLE task_handle;
1550 #endif /* NO_INET6 */
1551
1552 #ifdef NO_INET6
1553 if (request->to_host_hostent_buf == NULL) {
1554 request->to_host_hostent_buf =
1555 (char FAR *) malloc(MAXGETHOSTSTRUCT);
1556 }
1557 #endif /* NO_INET6 */
1558
1559 #ifndef NO_INET6
1560 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", request->spec.to_port);
1561 memset(&hints, 0, sizeof(hints));
1562 hints.ai_family = AF_UNSPEC;
1563 hints.ai_socktype = SOCK_STREAM;
1564 task_handle =
1565 WSAAsyncGetAddrInfo(make_accept_wnd(pvar), WM_SOCK_GOTNAME,
1566 request->spec.to_host, pname, &hints,
1567 &request->to_host_addrs);
1568 #else
1569 task_handle =
1570 WSAAsyncGetHostByName(make_accept_wnd(pvar), WM_SOCK_GOTNAME,
1571 request->spec.to_host,
1572 request->to_host_hostent_buf,
1573 MAXGETHOSTSTRUCT);
1574 #endif /* NO_INET6 */
1575
1576 if (task_handle == 0) {
1577 SSH_fail_channel_open(pvar, remote_channel_num);
1578 UTIL_get_lang_msg("MSG_FWD_DENIED_HANDLE_ERROR", pvar,
1579 "The server attempted to forward a connection through this machine.\n"
1580 "It requested a connection to machine %s on port %s.\n"
1581 "An error occurred while processing the request, and it has been denied.");
1582 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1583 pvar->ts->UIMsg,
1584 request->spec.to_host, request->spec.to_port_name);
1585 notify_nonfatal_error(pvar, buf);
1586 #ifndef NO_INET6
1587 /*****/
1588 freeaddrinfo(request->to_host_addrs);
1589 #else
1590 free(request->to_host_hostent_buf);
1591 request->to_host_hostent_buf = NULL;
1592 #endif /* NO_INET6 */
1593 return;
1594 } else {
1595 request->to_host_lookup_handle = task_handle;
1596 }
1597 }
1598
1599 channel_num = alloc_channel(pvar, FWD_REMOTE_CONNECTED, request_num);
1600 channel = pvar->fwd_state.channels + channel_num;
1601
1602 channel->remote_num = remote_channel_num;
1603 channel->filter_closure = filter_closure;
1604 channel->filter = filter;
1605
1606 // (2008.12.5 maya)
1607 channel->type = TYPE_PORTFWD;
1608
1609 // save channel number (2005.7.2 yutaka)
1610 if (chan_num != NULL) {
1611 *chan_num = channel_num;
1612 }
1613
1614 #ifndef NO_INET6
1615 if (request->to_host_addrs != NULL) {
1616 make_local_connection(pvar, channel_num);
1617 }
1618 #else
1619 if (request->to_host_addr != 0) {
1620 make_local_connection(pvar, channel_num);
1621 }
1622 #endif /* NO_INET6 */
1623 }
1624
1625 void FWD_open(PTInstVar pvar, uint32 remote_channel_num,
1626 char FAR * local_hostname, int local_port,
1627 char FAR * originator, int originator_len,
1628 int *chan_num)
1629 {
1630 int i;
1631 char buf[1024];
1632
1633 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1634 FWDRequest FAR *request = pvar->fwd_state.requests + i;
1635
1636 if (SSHv1(pvar)) {
1637 if ((request->status & FWD_DELETED) == 0
1638 && request->spec.type == FWD_REMOTE_TO_LOCAL
1639 && request->spec.to_port == local_port
1640 && strcmp(request->spec.to_host, local_hostname) == 0) {
1641 create_local_channel(pvar, remote_channel_num, i, NULL, NULL, chan_num);
1642 return;
1643 }
1644
1645 } else { // SSH2
1646 if ((request->status & FWD_DELETED) == 0
1647 && request->spec.type == FWD_REMOTE_TO_LOCAL
1648 && request->spec.from_port == local_port
1649 // && strcmp(request->spec.to_host, local_hostname) == 0) {
1650 ) {
1651 create_local_channel(pvar, remote_channel_num, i, NULL, NULL, chan_num);
1652 return;
1653 }
1654 }
1655 }
1656
1657 SSH_fail_channel_open(pvar, remote_channel_num);
1658
1659 /* now, before we panic, maybe we TOLD the server we could forward this port
1660 and then the user changed the settings. */
1661 for (i = 0; i < pvar->fwd_state.num_server_listening_specs; i++) {
1662 FWDRequestSpec FAR *spec =
1663 pvar->fwd_state.server_listening_specs + i;
1664
1665 if (spec->type == FWD_REMOTE_TO_LOCAL
1666 && spec->to_port == local_port
1667 && strcmp(spec->to_host, local_hostname) == 0) {
1668 return; /* no error message needed. The user just turned this off, that's all */
1669 }
1670 }
1671
1672 /* this forwarding was not prespecified */
1673 UTIL_get_lang_msg("MSG_FWD_DENIED_ERROR", pvar,
1674 "The server attempted to forward a connection through this machine.\n"
1675 "It requested a connection to machine %s on port %d.\n"
1676 "You did not specify this forwarding to TTSSH in advance, and therefore the request was denied.");
1677 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1678 pvar->ts->UIMsg,
1679 local_hostname, local_port);
1680 notify_nonfatal_error(pvar, buf);
1681 }
1682
1683 void FWD_X11_open(PTInstVar pvar, uint32 remote_channel_num,
1684 char FAR * originator, int originator_len,
1685 int *chan_num)
1686 {
1687 int i;
1688
1689 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1690 FWDRequest FAR *request = pvar->fwd_state.requests + i;
1691
1692 if ((request->status & FWD_DELETED) == 0
1693 && request->spec.type == FWD_REMOTE_X11_TO_LOCAL) {
1694 create_local_channel(pvar, remote_channel_num, i,
1695 X11_init_unspoofing_filter(pvar,
1696 pvar->fwd_state.
1697 X11_auth_data),
1698 X11_unspoofing_filter,
1699 chan_num);
1700 return;
1701 }
1702 }
1703
1704 SSH_fail_channel_open(pvar, remote_channel_num);
1705
1706 /* now, before we panic, maybe we TOLD the server we could forward this port
1707 and then the user changed the settings. */
1708 for (i = 0; i < pvar->fwd_state.num_server_listening_specs; i++) {
1709 FWDRequestSpec FAR *spec =
1710 pvar->fwd_state.server_listening_specs + i;
1711
1712 if (spec->type == FWD_REMOTE_X11_TO_LOCAL) {
1713 return; /* no error message needed. The user just turned this off, that's all */
1714 }
1715 }
1716
1717 /* this forwarding was not prespecified */
1718 UTIL_get_lang_msg("MSG_FWD_DENIED_X_ERROR", pvar,
1719 "The server attempted to forward a connection through this machine.\n"
1720 "It requested a connection to the local X server.\n"
1721 "You did not specify this forwarding to TTSSH in advance, and therefore the request was denied.");
1722 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1723 }
1724
1725 // agent forwarding の要求に対し、FWDChannel を作成する
1726 // SSH1 のときのみ呼ばれる
1727 int FWD_agent_open(PTInstVar pvar, uint32 remote_channel_num)
1728 {
1729 if (SSHv1(pvar)) {
1730 return alloc_agent_channel(pvar, remote_channel_num);
1731 }
1732
1733 return -1;
1734 }
1735
1736 void FWD_confirmed_open(PTInstVar pvar, uint32 local_channel_num,
1737 uint32 remote_channel_num)
1738 {
1739 SOCKET s;
1740 FWDChannel FAR *channel;
1741
1742 if (!FWD_check_local_channel_num(pvar, local_channel_num))
1743 return;
1744
1745 channel = pvar->fwd_state.channels + local_channel_num;
1746 s = channel->local_socket;
1747 if (s != INVALID_SOCKET) {
1748 channel->remote_num = remote_channel_num;
1749 channel->status |= FWD_REMOTE_CONNECTED;
1750
1751 read_local_connection(pvar, local_channel_num);
1752 } else {
1753 SSH_channel_input_eof(pvar, remote_channel_num, local_channel_num);
1754 SSH_channel_output_eof(pvar, remote_channel_num);
1755 channel->status |= FWD_CLOSED_LOCAL_IN | FWD_CLOSED_LOCAL_OUT;
1756 }
1757 }
1758
1759 void FWD_failed_open(PTInstVar pvar, uint32 local_channel_num)
1760 {
1761 if (!FWD_check_local_channel_num(pvar, local_channel_num))
1762 return;
1763
1764 UTIL_get_lang_msg("MSG_FWD_DENIED_BY_SERVER_ERROR", pvar,
1765 "A program on the local machine attempted to connect to a forwarded port.\n"
1766 "The forwarding request was denied by the server. The connection has been closed.");
1767 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1768 FWD_free_channel(pvar, local_channel_num);
1769 }
1770
1771 static BOOL blocking_write(PTInstVar pvar, SOCKET s, const char FAR * data,
1772 int length)
1773 {
1774 u_long do_block = 0;
1775
1776 #if 0
1777 return (pvar->PWSAAsyncSelect) (s, make_accept_wnd(pvar), 0,
1778 0) == SOCKET_ERROR
1779 || ioctlsocket(s, FIONBIO, &do_block) == SOCKET_ERROR
1780 || (pvar->Psend) (s, data, length, 0) != length
1781 || (pvar->PWSAAsyncSelect) (s, pvar->fwd_state.accept_wnd,
1782 WM_SOCK_ACCEPT,
1783 FD_READ | FD_CLOSE | FD_WRITE) == SOCKET_ERROR;
1784 #else
1785 if ( (pvar->PWSAAsyncSelect) (s, make_accept_wnd(pvar), 0, 0) == SOCKET_ERROR ) {
1786 goto error;
1787 }
1788
1789 if ( ioctlsocket(s, FIONBIO, &do_block) == SOCKET_ERROR ) {
1790 goto error;
1791 }
1792
1793 if ( (pvar->Psend) (s, data, length, 0) != length ) {
1794 goto error;
1795 }
1796
1797 if ( (pvar->PWSAAsyncSelect) (s, pvar->fwd_state.accept_wnd,
1798 WM_SOCK_ACCEPT,
1799 FD_READ | FD_CLOSE | FD_WRITE) == SOCKET_ERROR ) {
1800 goto error;
1801 }
1802
1803 return (TRUE);
1804
1805 error:
1806 return (FALSE);
1807 #endif
1808 }
1809
1810 void FWD_received_data(PTInstVar pvar, uint32 local_channel_num,
1811 unsigned char FAR * data, int length)
1812 {
1813 SOCKET s;
1814 FWDChannel FAR *channel;
1815 int action = FWD_FILTER_RETAIN;
1816
1817 if (!FWD_check_local_channel_num(pvar, local_channel_num))
1818 return;
1819
1820 channel = pvar->fwd_state.channels + local_channel_num;
1821
1822 if (channel->filter != NULL) {
1823 action =
1824 channel->filter(channel->filter_closure,
1825 FWD_FILTER_FROM_SERVER, &length, &data);
1826 }
1827
1828 s = channel->local_socket;
1829 if (length > 0 && s != INVALID_SOCKET) {
1830 if (!UTIL_sock_buffered_write
1831 (pvar, &channel->writebuf, blocking_write, s, data, length)) {
1832 closed_local_connection(pvar, local_channel_num);
1833 UTIL_get_lang_msg("MSG_FWD_COMM_ERROR", pvar,
1834 "A communications error occurred while sending forwarded data to a local port.\n"
1835 "The forwarded connection will be closed.");
1836 notify_nonfatal_error(pvar, pvar->ts->UIMsg);
1837 }
1838 }
1839
1840 switch (action) {
1841 case FWD_FILTER_REMOVE:
1842 channel->filter(channel->filter_closure, 0, NULL, NULL);
1843 channel->filter = NULL;
1844 channel->filter_closure = NULL;
1845 break;
1846 case FWD_FILTER_CLOSECHANNEL:
1847 closed_local_connection(pvar, local_channel_num);
1848 break;
1849 }
1850 }
1851
1852 void FWD_init(PTInstVar pvar)
1853 {
1854 pvar->fwd_state.requests = NULL;
1855 pvar->fwd_state.num_requests = 0;
1856 pvar->fwd_state.num_server_listening_specs = -1; /* forwarding prep not yet done */
1857 pvar->fwd_state.server_listening_specs = NULL;
1858 pvar->fwd_state.num_channels = 0;
1859 pvar->fwd_state.channels = NULL;
1860 pvar->fwd_state.local_host_IP_numbers = NULL;
1861 pvar->fwd_state.X11_auth_data = NULL;
1862 pvar->fwd_state.accept_wnd = NULL;
1863 pvar->fwd_state.in_interactive_mode = FALSE;
1864 }
1865
1866 void FWD_end(PTInstVar pvar)
1867 {
1868 int i;
1869
1870 if (pvar->fwd_state.channels != NULL) {
1871 for (i = 0; i < pvar->fwd_state.num_channels; i++) {
1872 FWD_free_channel(pvar, i);
1873 }
1874 free(pvar->fwd_state.channels);
1875 }
1876 #ifndef NO_INET6
1877 if (pvar->fwd_state.requests != NULL) {
1878 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1879 int j;
1880 int num_listening_sockets;
1881 SOCKET FAR *s =
1882 delete_request(pvar, i, &num_listening_sockets);
1883
1884 for (j = 0; j < num_listening_sockets; ++j) {
1885 if (s[j] != INVALID_SOCKET)
1886 closesocket(s[j]);
1887 }
1888 if (s != NULL)
1889 free(s); /* free(request[i]->listening_sockets) */
1890 }
1891 free(pvar->fwd_state.requests);
1892 }
1893 #else
1894 if (pvar->fwd_state.requests != NULL) {
1895 for (i = 0; i < pvar->fwd_state.num_requests; i++) {
1896 SOCKET s = delete_request(pvar, i);
1897
1898 if (s != INVALID_SOCKET) {
1899 closesocket(s);
1900 }
1901 }
1902 free(pvar->fwd_state.requests);
1903 }
1904 #endif /* NO_INET6 */
1905
1906 free(pvar->fwd_state.local_host_IP_numbers);
1907 free(pvar->fwd_state.server_listening_specs);
1908
1909 if (pvar->fwd_state.X11_auth_data != NULL) {
1910 X11_dispose_auth_data(pvar->fwd_state.X11_auth_data);
1911 }
1912
1913 if (pvar->fwd_state.accept_wnd != NULL) {
1914 DestroyWindow(pvar->fwd_state.accept_wnd);
1915 }
1916 }
1917
1918 BOOL FWD_agent_forward_confirm(PTInstVar pvar)
1919 {
1920 HWND cur_active = GetActiveWindow();
1921 if (pvar->session_settings.ForwardAgentConfirm) {
1922 UTIL_get_lang_msg("MSG_FWD_AGENT_FORWARDING_CONFIRM", pvar,
1923 "Are you sure you want to accept agent-forwarding request?");
1924 if (MessageBox(cur_active != NULL ? cur_active : pvar->NotificationWindow,
1925 pvar->ts->UIMsg, "TTSSH",
1926 MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES) {
1927 return TRUE;
1928 }
1929 else {
1930 return FALSE;
1931 }
1932 }
1933 return TRUE;
1934 }

SourceForge.JP is a Japanese version of SourceForge.net. For developments that are not related to Japan, we recommend you to use SourceForge.net.