Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2738 - (show annotations) (download) (as text)
Mon Nov 29 15:52:37 2004 UTC (19 years, 4 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 52533 byte(s)
SSHのdefault protocolをSSH2にした。

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 /* Teraterm extension mechanism
30 Robert O'Callahan (roc+tt@cs.cmu.edu)
31
32 Teraterm by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33 */
34
35 #include "ttxssh.h"
36 #include "fwdui.h"
37 #include "util.h"
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <io.h>
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <time.h>
46
47 #include "resource.h"
48 #include <commctrl.h>
49 #include <commdlg.h>
50 #ifdef INET6
51 #include <winsock2.h>
52 static char FAR *ProtocolFamilyList[] = { "UNSPEC", "IPv6", "IPv4", NULL };
53 #else
54 #include <winsock.h>
55 #endif /* INET6 */
56
57 #define MATCH_STR(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
58
59 /* This extension implements SSH, so we choose a load order in the
60 "protocols" range. */
61 #define ORDER 2500
62
63 #ifdef TERATERM32
64 static HICON SecureIcon = NULL;
65 #endif
66
67 static TInstVar FAR *pvar;
68
69 #ifdef TERATERM32
70 /* WIN32 allows multiple instances of a DLL */
71 static TInstVar InstVar;
72 #define GET_VAR()
73 #else
74 /* WIN16 does not allow multiple instances of a DLL */
75
76 /* maximum number of Tera Term instances */
77 #define MAXNUMINST 32
78 /* list of task handles for Tera Term instances */
79 static HANDLE FAR TaskList[MAXNUMINST];
80 /* variable sets for instances */
81 static TInstVar FAR *FAR InstVar[MAXNUMINST];
82
83 /* Here's how the TS settings work.
84 Whenever the TS settings are read or written to the INI file, then
85 the shared memory containing those settings is updated.
86 When Teraterm starts, the shared memory is read to initialize the TS
87 settings. */
88
89 /* TS settings shared across instances */
90 static TS_SSH ts_SSH_settings;
91
92
93 extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
94
95
96 static BOOL NewVar()
97 {
98 int i = 0;
99 HANDLE Task = GetCurrentTask();
100
101 if (TaskList[0] == NULL)
102
103 if (Task == NULL)
104 return FALSE;
105 while ((i < MAXNUMINST) && (TaskList[i] != NULL))
106 i++;
107 if (i >= MAXNUMINST)
108 return FALSE;
109 pvar = (TInstVar FAR *) malloc(sizeof(TInstVar));
110 InstVar[i] = pvar;
111 TaskList[i] = Task;
112 return TRUE;
113 }
114
115 void DelVar()
116 {
117 int i = 0;
118 HANDLE Task = GetCurrentTask();
119
120 if (Task == NULL)
121 return;
122 while ((i < MAXNUMINST) && (TaskList[i] != Task))
123 i++;
124 if (i >= MAXNUMINST)
125 return;
126 free(TaskList[i]);
127 TaskList[i] = NULL;
128 }
129
130 BOOL GetVar()
131 {
132 int i = 0;
133 HANDLE Task = GetCurrentTask();
134
135 if (Task == NULL)
136 return FALSE;
137 while ((i < MAXNUMINST) && (TaskList[i] != Task))
138 i++;
139 if (i >= MAXNUMINST)
140 return FALSE;
141 pvar = InstVar[i];
142 return TRUE;
143 }
144
145 #define GET_VAR() if (!GetVar()) return
146 #endif
147
148 /*
149 This code makes lots of assumptions about the order in which Teraterm
150 does things, and how. A key assumption is that the Notification window
151 passed into WSAAsyncSelect is the main terminal window. We also assume
152 that the socket used in the first WSAconnect is the main session socket.
153 */
154
155 static void init_TTSSH(PTInstVar pvar)
156 {
157 pvar->socket = INVALID_SOCKET;
158 pvar->OldLargeIcon = NULL;
159 pvar->OldSmallIcon = NULL;
160 pvar->NotificationWindow = NULL;
161 pvar->hostdlg_activated = FALSE;
162 pvar->socket = INVALID_SOCKET;
163 pvar->NotificationWindow = NULL;
164 pvar->protocol_major = 0;
165 pvar->protocol_minor = 0;
166
167 PKT_init(pvar);
168 SSH_init(pvar);
169 CRYPT_init(pvar);
170 AUTH_init(pvar);
171 HOSTS_init(pvar);
172 FWD_init(pvar);
173 FWDUI_init(pvar);
174 }
175
176 static void uninit_TTSSH(PTInstVar pvar)
177 {
178 SSH_end(pvar);
179 PKT_end(pvar);
180 AUTH_end(pvar);
181 CRYPT_end(pvar);
182 HOSTS_end(pvar);
183 FWD_end(pvar);
184 FWDUI_end(pvar);
185
186 if (pvar->OldLargeIcon != NULL) {
187 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
188 (LPARAM) pvar->OldLargeIcon);
189 pvar->OldLargeIcon = NULL;
190 }
191 if (pvar->OldSmallIcon != NULL) {
192 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
193 (LPARAM) pvar->OldSmallIcon);
194 pvar->OldSmallIcon = NULL;
195 }
196 }
197
198 static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv)
199 {
200 #ifndef TERATERM32
201 if (!NewVar())
202 return; /* should be called first */
203 pvar->ts_SSH = &ts_SSH_settings;
204 #endif
205 pvar->settings = *pvar->ts_SSH;
206 pvar->ts = ts;
207 pvar->cv = cv;
208 pvar->fatal_error = FALSE;
209 pvar->showing_err = FALSE;
210 pvar->err_msg = NULL;
211
212 init_TTSSH(pvar);
213 }
214
215 static void normalize_cipher_order(char FAR * buf)
216 {
217 char ciphers_listed[SSH_CIPHER_MAX + 1];
218 char ciphers_allowed[SSH_CIPHER_MAX + 1];
219 int i, j;
220
221 /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
222 We *never* allow no encryption. */
223 #if 0
224 static char default_ciphers[] = {
225 SSH_CIPHER_3DES,
226 SSH_CIPHER_NONE,
227 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
228 };
229 #else
230 // for SSH2(yutaka)
231 static char default_ciphers[] = {
232 SSH_CIPHER_AES128,
233 SSH_CIPHER_3DES_CBC,
234 SSH_CIPHER_3DES,
235 SSH_CIPHER_NONE,
236 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
237 };
238 #endif
239
240 memset(ciphers_listed, 0, sizeof(ciphers_listed));
241
242 memset(ciphers_allowed, 0, sizeof(ciphers_allowed));
243 for (i = 0; i < NUM_ELEM(default_ciphers); i++) {
244 ciphers_allowed[default_ciphers[i]] = 1;
245 }
246
247 for (i = 0; buf[i] != 0; i++) {
248 int cipher_num = buf[i] - '0';
249
250 if (cipher_num < 0 || cipher_num > SSH_CIPHER_MAX
251 || !ciphers_allowed[cipher_num]
252 || ciphers_listed[cipher_num]) {
253 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
254 i--;
255 } else {
256 ciphers_listed[cipher_num] = 1;
257 }
258 }
259
260 for (j = 0; j < NUM_ELEM(default_ciphers); j++) {
261 int cipher_num = default_ciphers[j];
262
263 if (!ciphers_listed[cipher_num]) {
264 buf[i] = cipher_num + '0';
265 i++;
266 }
267 }
268
269 buf[i] = 0;
270 }
271
272 /* Remove local settings from the shared memory block. */
273 static void clear_local_settings(PTInstVar pvar)
274 {
275 pvar->ts_SSH->TryDefaultAuth = FALSE;
276 }
277
278 static BOOL read_BOOL_option(PCHAR fileName, char FAR * keyName, BOOL def)
279 {
280 char buf[1024];
281
282 buf[0] = 0;
283 GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
284 fileName);
285 if (buf[0] == 0) {
286 return def;
287 } else {
288 return atoi(buf) != 0 ||
289 stricmp(buf, "yes") == 0 || stricmp(buf, "y") == 0;
290 }
291 }
292
293 static void read_string_option(PCHAR fileName, char FAR * keyName,
294 char FAR * def, char FAR * buf, int bufSize)
295 {
296
297 buf[0] = 0;
298 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
299 }
300
301 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
302 {
303 extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
304 char buf[1024];
305 TS_SSH FAR *settings = pvar->ts_SSH;
306
307 #define READ_STD_STRING_OPTION(name) \
308 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
309
310 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
311
312 buf[0] = 0;
313 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
314 fileName);
315 settings->CompressionLevel = atoi(buf);
316 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
317 settings->CompressionLevel = 0;
318 }
319
320 READ_STD_STRING_OPTION(DefaultUserName);
321 READ_STD_STRING_OPTION(DefaultForwarding);
322 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
323 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
324 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
325
326 READ_STD_STRING_OPTION(CipherOrder);
327 normalize_cipher_order(settings->CipherOrder);
328 SSH2_update_cipher_myproposal(pvar); // yutaka
329
330 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
331 settings->KnownHostsFiles,
332 sizeof(settings->KnownHostsFiles));
333
334 buf[0] = 0;
335 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
336 sizeof(buf), fileName);
337 settings->DefaultAuthMethod = atoi(buf);
338 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
339 && settings->DefaultAuthMethod != SSH_AUTH_RSA
340 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS) {
341 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
342 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
343 when the dialog box has rhosts selected and an host private key file
344 is supplied. */
345 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
346 }
347
348 buf[0] = 0;
349 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
350 fileName);
351 settings->LogLevel = atoi(buf);
352
353 buf[0] = 0;
354 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
355 sizeof(buf), fileName);
356 settings->WriteBufferSize = atoi(buf);
357 if (settings->WriteBufferSize <= 0) {
358 settings->WriteBufferSize = 2 * 1024 * 1024;
359 }
360
361 settings->LocalForwardingIdentityCheck =
362 read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
363
364 // SSH protocol version (2004.10.11 yutaka)
365 // default is SSH2 (2004.11.30 yutaka)
366 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
367
368 clear_local_settings(pvar);
369 }
370
371 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
372 TS_SSH FAR * settings)
373 {
374 char buf[1024];
375
376 WritePrivateProfileString("TTSSH", "Enabled",
377 settings->Enabled ? "1" : "0", fileName);
378
379 _itoa(settings->CompressionLevel, buf, 10);
380 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
381
382 WritePrivateProfileString("TTSSH", "DefaultUserName",
383 settings->DefaultUserName, fileName);
384
385 WritePrivateProfileString("TTSSH", "DefaultForwarding",
386 settings->DefaultForwarding, fileName);
387
388 WritePrivateProfileString("TTSSH", "CipherOrder",
389 settings->CipherOrder, fileName);
390
391 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
392 settings->KnownHostsFiles, fileName);
393
394 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
395 settings->DefaultRhostsLocalUserName,
396 fileName);
397
398 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
399 settings->DefaultRhostsHostPrivateKeyFile,
400 fileName);
401
402 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
403 settings->DefaultRSAPrivateKeyFile,
404 fileName);
405
406 _itoa(settings->DefaultAuthMethod, buf, 10);
407 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
408
409 _itoa(settings->LogLevel, buf, 10);
410 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
411
412 _itoa(settings->WriteBufferSize, buf, 10);
413 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
414
415 WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
416 settings->
417 LocalForwardingIdentityCheck ? "1" : "0",
418 fileName);
419
420 // SSH protocol version (2004.10.11 yutaka)
421 WritePrivateProfileString("TTSSH", "ProtocolVersion",
422 settings->ssh_protocol_version==2 ? "2" : "1",
423 fileName);
424
425 }
426
427 /* find free port in all protocol family */
428 static unsigned short find_local_port(PTInstVar pvar)
429 {
430 int tries;
431 #ifdef INET6
432 SOCKET connecter;
433 struct addrinfo hints;
434 struct addrinfo FAR *res;
435 struct addrinfo FAR *res0;
436 unsigned short port;
437 char pname[NI_MAXHOST];
438 #endif /* INET6 */
439
440 if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
441 return 0;
442 }
443
444 /* The random numbers here are only used to try to get fresh
445 ports across runs (dangling ports can cause bind errors
446 if we're unlucky). They do not need to be (and are not)
447 cryptographically strong.
448 */
449 srand((unsigned) GetTickCount());
450
451 #ifdef INET6
452 for (tries = 20; tries > 0; tries--) {
453 memset(&hints, 0, sizeof(hints));
454 hints.ai_family = pvar->ts->ProtocolFamily;
455 hints.ai_flags = AI_PASSIVE;
456 hints.ai_socktype = SOCK_STREAM;
457 port = (unsigned) rand() % 512 + 512;
458 _snprintf(pname, sizeof(pname), "%d", (int) port);
459 if (getaddrinfo(NULL, pname, &hints, &res0)) {
460 return 0;
461 /* NOT REACHED */
462 }
463
464 for (res = res0; res; res = res->ai_next) {
465 if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
466 continue;
467
468 connecter =
469 socket(res->ai_family, res->ai_socktype, res->ai_protocol);
470 if (connecter == INVALID_SOCKET) {
471 freeaddrinfo(res0);
472 return 0;
473 }
474
475 if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
476 SOCKET_ERROR) {
477 return port;
478 freeaddrinfo(res0);
479 closesocket(connecter);
480 } else if (WSAGetLastError() != WSAEADDRINUSE) {
481 closesocket(connecter);
482 freeaddrinfo(res0);
483 return 0;
484 }
485
486 closesocket(connecter);
487 }
488 freeaddrinfo(res0);
489 }
490
491 return 0;
492 #else
493 for (tries = 20; tries > 0; tries--) {
494 SOCKET connecter = socket(AF_INET, SOCK_STREAM, 0);
495 struct sockaddr_in connecter_addr;
496
497 connecter_addr.sin_family = AF_INET;
498 connecter_addr.sin_port = (unsigned) rand() % 512 + 512;
499 connecter_addr.sin_addr.s_addr = htonl(INADDR_ANY);
500
501 if (connecter == INVALID_SOCKET) {
502 return 0;
503 }
504
505 if (bind
506 (connecter, (struct sockaddr FAR *) &connecter_addr,
507 sizeof(connecter_addr)) != SOCKET_ERROR) {
508 closesocket(connecter);
509 return connecter_addr.sin_port;
510 } else if (WSAGetLastError() != WSAEADDRINUSE) {
511 closesocket(connecter);
512 return 0;
513 }
514
515 closesocket(connecter);
516 }
517
518 return 0;
519 #endif /* INET6 */
520 }
521
522 static int PASCAL FAR TTXconnect(SOCKET s,
523 const struct sockaddr FAR * name,
524 int namelen)
525 {
526 GET_VAR();
527
528 #ifdef INET6
529 if (pvar->socket == INVALID_SOCKET) {
530 struct sockaddr_storage ss;
531 int len;
532
533 pvar->socket = s;
534
535 memset(&ss, 0, sizeof(ss));
536 switch (pvar->ts->ProtocolFamily) {
537 case AF_INET:
538 len = sizeof(struct sockaddr_in);
539 ((struct sockaddr_in FAR *) &ss)->sin_family = AF_INET;
540 ((struct sockaddr_in FAR *) &ss)->sin_addr.s_addr = INADDR_ANY;
541 ((struct sockaddr_in FAR *) &ss)->sin_port =
542 htons(find_local_port(pvar));
543 break;
544 case AF_INET6:
545 len = sizeof(struct sockaddr_in6);
546 ((struct sockaddr_in6 FAR *) &ss)->sin6_family = AF_INET6;
547 #if 0 /* symbol "in6addr_any" is not included in wsock32.lib */
548 /* if wsock32.lib will be linked, we can't refer "in6addr_any" */
549 ((struct sockaddr_in6 FAR *) &ss)->sin6_addr = in6addr_any;
550 #eles
551 memset(&((struct sockaddr_in6 FAR *) &ss)->sin6_addr, 0,
552 sizeof(struct in_addr6));
553 #endif /* 0 */
554 ((struct sockaddr_in6 FAR *) &ss)->sin6_port =
555 htons(find_local_port(pvar));
556 break;
557 default:
558 /* NOT REACHED */
559 break;
560 }
561
562 bind(s, (struct sockaddr FAR *) &ss, len);
563 }
564 #else
565 if (pvar->socket == INVALID_SOCKET) {
566 struct sockaddr_in addr;
567
568 pvar->socket = s;
569
570 addr.sin_family = AF_INET;
571 addr.sin_port = htons(find_local_port(pvar));
572 addr.sin_addr.s_addr = INADDR_ANY;
573 memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
574
575 bind(s, (struct sockaddr FAR *) &addr, sizeof(addr));
576 }
577 #endif /* INET6 */
578
579 return (pvar->Pconnect) (s, name, namelen);
580 }
581
582 static int PASCAL FAR TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
583 long lEvent)
584 {
585 GET_VAR();
586
587 if (s == pvar->socket) {
588 pvar->notification_events = lEvent;
589 pvar->notification_msg = wMsg;
590
591 if (pvar->NotificationWindow == NULL) {
592 pvar->NotificationWindow = hWnd;
593 AUTH_advance_to_next_cred(pvar);
594 }
595 }
596
597 return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
598 }
599
600 static int PASCAL FAR TTXrecv(SOCKET s, char FAR * buf, int len, int flags)
601 {
602 GET_VAR();
603
604 if (s == pvar->socket) {
605 return PKT_recv(pvar, buf, len);
606 } else {
607 return (pvar->Precv) (s, buf, len, flags);
608 }
609 }
610
611 static int PASCAL FAR TTXsend(SOCKET s, char const FAR * buf, int len,
612 int flags)
613 {
614 GET_VAR();
615
616 if (s == pvar->socket) {
617 SSH_send(pvar, buf, len);
618 return len;
619 } else {
620 return (pvar->Psend) (s, buf, len, flags);
621 }
622 }
623
624 void notify_established_secure_connection(PTInstVar pvar)
625 {
626 #ifdef TERATERM32
627 if (SecureIcon == NULL) {
628 SecureIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SECURETT));
629 }
630
631 if (SecureIcon != NULL) {
632 pvar->OldSmallIcon =
633 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
634 ICON_SMALL, 0);
635 pvar->OldLargeIcon =
636 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
637 ICON_BIG, 0);
638 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
639 (LPARAM) SecureIcon);
640 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
641 (LPARAM) SecureIcon);
642 }
643 #endif
644
645 notify_verbose_message(pvar, "Entering secure mode",
646 LOG_LEVEL_VERBOSE);
647 }
648
649 void notify_closed_connection(PTInstVar pvar)
650 {
651 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
652 pvar->socket, MAKELPARAM(FD_CLOSE, 0));
653
654 SSH_notify_disconnecting(pvar, NULL);
655 AUTH_notify_disconnecting(pvar);
656 HOSTS_notify_disconnecting(pvar);
657 }
658
659 static void add_err_msg(PTInstVar pvar, char FAR * msg)
660 {
661 if (pvar->err_msg != NULL) {
662 char FAR *buf =
663 (char FAR *) malloc(strlen(pvar->err_msg) + 3 + strlen(msg));
664
665 strcpy(buf, pvar->err_msg);
666 strcat(buf, "\n\n");
667 strcat(buf, msg);
668 free(pvar->err_msg);
669 pvar->err_msg = buf;
670 } else {
671 pvar->err_msg = _strdup(msg);
672 }
673 }
674
675 void notify_nonfatal_error(PTInstVar pvar, char FAR * msg)
676 {
677 if (!pvar->showing_err) {
678 PostMessage(pvar->NotificationWindow, WM_COMMAND,
679 ID_SSHASYNCMESSAGEBOX, 0);
680 }
681 if (msg[0] != 0) {
682 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
683 add_err_msg(pvar, msg);
684 }
685 }
686
687 void notify_fatal_error(PTInstVar pvar, char FAR * msg)
688 {
689 if (msg[0] != 0) {
690 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
691 add_err_msg(pvar, msg);
692 }
693
694 if (!pvar->fatal_error) {
695 pvar->fatal_error = TRUE;
696
697 SSH_notify_disconnecting(pvar, msg);
698 AUTH_notify_disconnecting(pvar);
699 HOSTS_notify_disconnecting(pvar);
700
701 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
702 pvar->socket, MAKELPARAM(FD_CLOSE,
703 (pvar->PWSAGetLastError) ()));
704 }
705 }
706
707 void notify_verbose_message(PTInstVar pvar, char FAR * msg, int level)
708 {
709 if (level <= pvar->session_settings.LogLevel) {
710 char buf[1024];
711 int file;
712
713 get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
714 file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
715 _S_IREAD | _S_IWRITE);
716
717 if (file >= 0) {
718 _write(file, msg, strlen(msg));
719 _write(file, "\n", 1);
720 _close(file);
721 }
722 }
723 }
724
725 static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks)
726 {
727 GET_VAR();
728
729 if (pvar->settings.Enabled) {
730 char buf[1024] = "\nInitiating SSH session at ";
731 struct tm FAR *newtime;
732 time_t long_time;
733
734 pvar->session_settings = pvar->settings;
735
736 time(&long_time);
737 newtime = localtime(&long_time);
738 strcat(buf, asctime(newtime));
739 buf[strlen(buf) - 1] = 0;
740 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
741
742 FWDUI_load_settings(pvar);
743
744 pvar->cv->TelAutoDetect = FALSE;
745 /* This next line should not be needed because Teraterm's
746 CommLib should find ts->Telnet == 0 ... but we'll do this
747 just to be on the safe side. */
748 pvar->cv->TelFlag = FALSE;
749
750 pvar->Precv = *hooks->Precv;
751 pvar->Psend = *hooks->Psend;
752 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
753 pvar->Pconnect = *hooks->Pconnect;
754 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
755
756 *hooks->Precv = TTXrecv;
757 *hooks->Psend = TTXsend;
758 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
759 *hooks->Pconnect = TTXconnect;
760
761 SSH_open(pvar);
762 HOSTS_open(pvar);
763 FWDUI_open(pvar);
764 }
765 }
766
767 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
768 {
769 GET_VAR();
770
771 if (pvar->session_settings.Enabled) {
772 pvar->socket = INVALID_SOCKET;
773
774 notify_verbose_message(pvar, "Terminating SSH session...",
775 LOG_LEVEL_VERBOSE);
776
777 *hooks->Precv = pvar->Precv;
778 *hooks->Psend = pvar->Psend;
779 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
780 *hooks->Pconnect = pvar->Pconnect;
781 }
782
783 uninit_TTSSH(pvar);
784 init_TTSSH(pvar);
785 }
786
787 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
788 {
789 for (; from <= to; from++) {
790 EnableWindow(GetDlgItem(dlg, from), enabled);
791 }
792 }
793
794 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
795 LPARAM lParam)
796 {
797 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
798 PGetHNRec GetHNRec;
799 char EntName[7];
800 char TempHost[HostNameMaxLength + 1];
801 WORD i, j, w;
802 BOOL Ok;
803
804 GET_VAR();
805
806 switch (msg) {
807 case WM_INITDIALOG:
808 GetHNRec = (PGetHNRec) lParam;
809 SetWindowLong(dlg, DWL_USER, lParam);
810
811 if (GetHNRec->PortType == IdFile)
812 GetHNRec->PortType = IdTCPIP;
813 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
814 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
815
816 strcpy(EntName, "Host");
817
818 i = 1;
819 do {
820 sprintf(&EntName[4], "%d", i);
821 GetPrivateProfileString("Hosts", EntName, "",
822 TempHost, sizeof(TempHost),
823 GetHNRec->SetupFN);
824 if (strlen(TempHost) > 0)
825 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
826 0, (LPARAM) TempHost);
827 i++;
828 } while ((i <= 99) && (strlen(TempHost) > 0));
829
830 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
831 HostNameMaxLength - 1, 0);
832
833 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
834
835 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
836 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
837 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
838 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
839 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
840 #ifdef INET6
841 for (i = 0; ProtocolFamilyList[i]; ++i) {
842 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
843 0, (LPARAM) ProtocolFamilyList[i]);
844 }
845 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
846 ProtocolFamilyMaxLength - 1, 0);
847 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
848 #endif /* INET6 */
849
850 /////// SSH version
851 for (i = 0; ssh_version[i]; ++i) {
852 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
853 0, (LPARAM) ssh_version[i]);
854 }
855 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
856 NUM_ELEM(ssh_version) - 1, 0);
857
858 if (pvar->settings.ssh_protocol_version == 1) {
859 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
860 } else {
861 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
862 }
863
864 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
865 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
866 } else {
867 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
868 }
869 /////// SSH version
870
871
872 j = 0;
873 w = 1;
874 strcpy(EntName, "COM");
875 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
876 sprintf(&EntName[3], "%d", i);
877 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
878 0, (LPARAM) EntName);
879 j++;
880 if (GetHNRec->ComPort == i)
881 w = j;
882 }
883 if (j > 0)
884 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
885 else /* All com ports are already used */
886 GetHNRec->PortType = IdTCPIP;
887
888 if (GetHNRec->PortType == IdTCPIP)
889 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
890 #ifdef INET6
891 else {
892 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
893 FALSE);
894 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
895 IDC_HOSTTCPPROTOCOL, FALSE);
896 }
897 #else
898 else
899 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
900 FALSE);
901 #endif /* INET6 */
902
903 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
904 {
905 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
906
907 SetFocus(hwnd);
908 //SendMessage(hwnd, BM_SETCHECK, BST_CHECKED, 0);
909 //style = GetClassLongPtr(hwnd, GCL_STYLE);
910 //SetClassLongPtr(hwnd, GCL_STYLE, style | WS_TABSTOP);
911 }
912
913 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
914 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
915 // (2004.11.23 yutaka)
916 return FALSE;
917 //return TRUE;
918
919 case WM_COMMAND:
920 switch (LOWORD(wParam)) {
921 case IDOK:
922 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
923 if (GetHNRec != NULL) {
924 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
925 #ifdef INET6
926 char afstr[BUFSIZ];
927 #endif /* INET6 */
928 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
929 if (Ok) {
930 GetHNRec->TCPPort = i;
931 } else {
932 MessageBox(dlg, "Teraterm",
933 "The TCP port must be a number.",
934 MB_OK | MB_ICONEXCLAMATION);
935 return TRUE;
936 }
937 #ifdef INET6
938 #define getaf(str) \
939 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
940 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
941 memset(afstr, 0, sizeof(afstr));
942 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
943 sizeof(afstr));
944 GetHNRec->ProtocolFamily = getaf(afstr);
945 #endif /* INET6 */
946 GetHNRec->PortType = IdTCPIP;
947 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
948 HostNameMaxLength);
949 GetHNRec->Telnet = FALSE;
950 pvar->hostdlg_activated = TRUE;
951 pvar->hostdlg_Enabled = FALSE;
952 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
953 GetHNRec->Telnet = TRUE;
954 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
955 pvar->hostdlg_Enabled = TRUE;
956
957 // check SSH protocol version
958 memset(afstr, 0, sizeof(afstr));
959 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
960 if (stricmp(afstr, "SSH1") == 0) {
961 pvar->settings.ssh_protocol_version = 1;
962 } else {
963 pvar->settings.ssh_protocol_version = 2;
964 }
965 }
966 } else {
967 GetHNRec->PortType = IdSerial;
968 GetHNRec->HostName[0] = 0;
969 memset(EntName, 0, sizeof(EntName));
970 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
971 sizeof(EntName) - 1);
972 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
973 if (strlen(EntName) > 4)
974 GetHNRec->ComPort =
975 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
976 0x30;
977 }
978 }
979 EndDialog(dlg, 1);
980 return TRUE;
981
982 case IDCANCEL:
983 EndDialog(dlg, 0);
984 return TRUE;
985
986 case IDC_HOSTTCPIP:
987 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
988 TRUE);
989 #ifdef INET6
990 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
991 IDC_HOSTTCPPROTOCOL, TRUE);
992 #endif /* INET6 */
993 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
994
995 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
996 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
997 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
998 } else {
999 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1000 }
1001
1002 return TRUE;
1003
1004 case IDC_HOSTSERIAL:
1005 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1006 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1007 FALSE);
1008 #ifdef INET6
1009 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1010 IDC_HOSTTCPPROTOCOL, FALSE);
1011 #endif /* INET6 */
1012 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1013 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1014
1015 return TRUE;
1016
1017 case IDC_HOSTSSH:
1018 enable_dlg_items(dlg, IDC_SSH_VERSION,
1019 IDC_SSH_VERSION, TRUE);
1020 goto hostssh_enabled;
1021
1022 case IDC_HOSTTELNET:
1023 case IDC_HOSTOTHER:
1024 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1025 hostssh_enabled:
1026
1027 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1028
1029 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1030 if (GetHNRec != NULL)
1031 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1032 FALSE);
1033 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1034 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1035 }
1036 return TRUE;
1037
1038 case IDC_HOSTHELP:
1039 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1040 }
1041 }
1042 return FALSE;
1043 }
1044
1045 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1046 {
1047 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1048 parent, TTXHostDlg, (LONG) rec);
1049 }
1050
1051 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1052 {
1053 GET_VAR();
1054
1055 *hooks->GetHostName = TTXGetHostName;
1056 }
1057
1058 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1059 {
1060 GET_VAR();
1061
1062 (pvar->ReadIniFile) (fileName, ts);
1063 read_ssh_options(pvar, fileName);
1064 pvar->settings = *pvar->ts_SSH;
1065 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1066 FWDUI_load_settings(pvar);
1067 }
1068
1069 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1070 {
1071 GET_VAR();
1072
1073 (pvar->WriteIniFile) (fileName, ts);
1074 *pvar->ts_SSH = pvar->settings;
1075 clear_local_settings(pvar);
1076 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1077 write_ssh_options(pvar, fileName, pvar->ts_SSH);
1078 }
1079
1080 static void read_ssh_options_from_user_file(PTInstVar pvar,
1081 char FAR * user_file_name)
1082 {
1083 if (user_file_name[0] == '.') {
1084 read_ssh_options(pvar, user_file_name);
1085 } else {
1086 char buf[1024];
1087
1088 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1089 read_ssh_options(pvar, buf);
1090 }
1091
1092 pvar->settings = *pvar->ts_SSH;
1093 FWDUI_load_settings(pvar);
1094 }
1095
1096 /* returns 1 if the option text must be deleted */
1097 static int parse_option(PTInstVar pvar, char FAR * option)
1098 {
1099 if ((option[0] == '-' || option[0] == '/')) {
1100 if (MATCH_STR(option + 1, "ssh") == 0) {
1101 if (option[4] == 0) {
1102 pvar->settings.Enabled = 1;
1103 } else if (MATCH_STR(option + 4, "-L") == 0
1104 || MATCH_STR(option + 4, "-R") == 0
1105 || stricmp(option + 4, "-X") == 0) {
1106 if (pvar->settings.DefaultForwarding[0] == 0) {
1107 strcpy(pvar->settings.DefaultForwarding, option + 5);
1108 } else {
1109 strcat(pvar->settings.DefaultForwarding, ";");
1110 strcat(pvar->settings.DefaultForwarding, option + 5);
1111 }
1112 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1113 read_ssh_options_from_user_file(pvar, option + 7);
1114 } else if (MATCH_STR(option + 4, "-v") == 0) {
1115 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1116 } else if (stricmp(option + 4, "-autologin") == 0
1117 || stricmp(option + 4, "-autologon") == 0) {
1118 pvar->settings.TryDefaultAuth = TRUE;
1119 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1120 read_ssh_options_from_user_file(pvar, option + 13);
1121 DeleteFile(option + 13);
1122 } else {
1123 char buf[1024];
1124
1125 _snprintf(buf, sizeof(buf),
1126 "Unrecognized command-line option: %s", option);
1127 buf[sizeof(buf) - 1] = 0;
1128
1129 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1130 }
1131
1132 return 1;
1133 } else if (MATCH_STR(option + 1, "t=") == 0) {
1134 if (strcmp(option + 3, "2") == 0) {
1135 pvar->settings.Enabled = 1;
1136 return 1;
1137 } else {
1138 pvar->settings.Enabled = 0;
1139 }
1140 } else if (MATCH_STR(option + 1, "f=") == 0) {
1141 read_ssh_options_from_user_file(pvar, option + 3);
1142
1143 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1144 } else if (MATCH_STR(option + 1, "1") == 0) {
1145 // command line: /ssh /1 is SSH1 only
1146 pvar->settings.ssh_protocol_version = 1;
1147
1148 } else if (MATCH_STR(option + 1, "2") == 0) {
1149 // command line: /ssh /2 is SSH2 & SSH1
1150 pvar->settings.ssh_protocol_version = 2;
1151
1152 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1153 // '/nossh' �I�v�V�����������B
1154 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1155 // �����������������B(2004.10.11 yutaka)
1156 pvar->settings.Enabled = 0;
1157
1158 }
1159
1160 }
1161
1162 return 0;
1163 }
1164
1165 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1166 PCHAR DDETopic)
1167 {
1168 int i;
1169 BOOL inParam = FALSE;
1170 BOOL inQuotes = FALSE;
1171 PCHAR option = NULL;
1172 GET_VAR();
1173
1174 if (pvar->hostdlg_activated) {
1175 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1176 }
1177
1178 for (i = 0; param[i] != 0; i++) {
1179 if (inQuotes ? param[i] ==
1180 '"' : (param[i] == ' ' || param[i] == '\t')) {
1181 if (option != NULL) {
1182 char ch = param[i];
1183
1184 param[i] = 0;
1185 if (parse_option
1186 (pvar, *option == '"' ? option + 1 : option)) {
1187 memset(option, ' ', i + 1 - (option - param));
1188 } else {
1189 param[i] = ch;
1190 }
1191 option = NULL;
1192 }
1193 inParam = FALSE;
1194 inQuotes = FALSE;
1195 } else if (!inParam) {
1196 if (param[i] == '"') {
1197 inQuotes = TRUE;
1198 inParam = TRUE;
1199 option = param + i;
1200 } else if (param[i] != ' ' && param[i] != '\t') {
1201 inParam = TRUE;
1202 option = param + i;
1203 }
1204 }
1205 }
1206
1207 if (option != NULL) {
1208 if (parse_option(pvar, option)) {
1209 memset(option, ' ', i - (option - param));
1210 }
1211 }
1212
1213 FWDUI_load_settings(pvar);
1214
1215 (pvar->ParseParam) (param, ts, DDETopic);
1216
1217 }
1218
1219 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1220 {
1221 GET_VAR();
1222
1223 pvar->ReadIniFile = *hooks->ReadIniFile;
1224 pvar->WriteIniFile = *hooks->WriteIniFile;
1225 pvar->ParseParam = *hooks->ParseParam;
1226
1227 *hooks->ReadIniFile = TTXReadINIFile;
1228 *hooks->WriteIniFile = TTXWriteINIFile;
1229 *hooks->ParseParam = TTXParseParam;
1230 }
1231
1232 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1233 {
1234 GET_VAR();
1235
1236 SSH_notify_win_size(pvar, cols, rows);
1237 }
1238
1239 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1240 WORD newItemID, char FAR * text)
1241 {
1242 int i, j;
1243
1244 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1245 HMENU submenu = GetSubMenu(menu, i);
1246
1247 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1248 if (GetMenuItemID(submenu, j) == beforeItemID) {
1249 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1250 text);
1251 return;
1252 }
1253 }
1254 }
1255 }
1256
1257 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1258 {
1259 GET_VAR();
1260
1261 /* inserts before ID_HELP_ABOUT */
1262 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1263 "About &TTSSH...");
1264
1265 /* inserts before ID_SETUP_TCPIP */
1266 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1267 "SS&H...");
1268 /* inserts before ID_SETUP_TCPIP */
1269 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1270 "SSH &Authentication...");
1271 /* inserts before ID_SETUP_TCPIP */
1272 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1273 "SSH F&orwarding...");
1274 }
1275
1276 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1277 {
1278 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1279 (LPARAM) prefix);
1280 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1281 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1282 (LPARAM) (char FAR *) "\r\n");
1283 }
1284
1285 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1286 {
1287 char buf[1024];
1288
1289 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1290
1291 if (pvar->socket != INVALID_SOCKET) {
1292 if (SSHv1(pvar)) {
1293 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1294 append_about_text(dlg, "Server ID: ", buf);
1295 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1296 append_about_text(dlg, "Using protocol: ", buf);
1297 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1298 append_about_text(dlg, "Encryption: ", buf);
1299 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1300 append_about_text(dlg, "Server keys: ", buf);
1301 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1302 append_about_text(dlg, "Authentication: ", buf);
1303 SSH_get_compression_info(pvar, buf, sizeof(buf));
1304 append_about_text(dlg, "Compression: ", buf);
1305
1306 } else { // SSH2
1307 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1308 append_about_text(dlg, "Server ID: ", buf);
1309
1310 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1311
1312 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1313 append_about_text(dlg, "Using protocol: ", buf);
1314
1315 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1316 strcpy(buf, KEX_DH1);
1317 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1318 strcpy(buf, KEX_DH14);
1319 } else {
1320 strcpy(buf, KEX_DHGEX);
1321 }
1322 append_about_text(dlg, "KEX: ", buf);
1323
1324 if (pvar->hostkey_type == KEY_DSA) {
1325 strcpy(buf, "ssh-dss");
1326 } else {
1327 strcpy(buf, "ssh-rsa");
1328 }
1329 append_about_text(dlg, "Host Key: ", buf);
1330
1331 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1332 append_about_text(dlg, "Encryption: ", buf);
1333 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1334 append_about_text(dlg, "Server keys: ", buf);
1335 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1336 append_about_text(dlg, "Authentication: ", buf);
1337 SSH_get_compression_info(pvar, buf, sizeof(buf));
1338 append_about_text(dlg, "Compression: ", buf);
1339
1340 }
1341 }
1342 }
1343
1344 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1345 LPARAM lParam)
1346 {
1347 switch (msg) {
1348 case WM_INITDIALOG:
1349 init_about_dlg((PTInstVar) lParam, dlg);
1350 return TRUE;
1351 case WM_COMMAND:
1352 switch (LOWORD(wParam)) {
1353 case IDOK:
1354 EndDialog(dlg, 1);
1355 return TRUE;
1356 case IDCANCEL: /* there isn't a cancel button, but other Windows
1357 UI things can send this message */
1358 EndDialog(dlg, 0);
1359 return TRUE;
1360 }
1361 break;
1362 }
1363
1364 return FALSE;
1365 }
1366
1367 static char FAR *get_cipher_name(int cipher)
1368 {
1369 switch (cipher) {
1370 case SSH_CIPHER_NONE:
1371 return "<ciphers below this line are disabled>";
1372 case SSH_CIPHER_RC4:
1373 return "RC4";
1374 case SSH_CIPHER_3DES:
1375 return "3DES";
1376 case SSH_CIPHER_DES:
1377 return "DES";
1378 case SSH_CIPHER_IDEA:
1379 return "IDEA";
1380 case SSH_CIPHER_TSS:
1381 return "TSS";
1382 case SSH_CIPHER_BLOWFISH:
1383 return "Blowfish";
1384
1385 // for SSH2(yutaka)
1386 case SSH_CIPHER_AES128:
1387 return "AES128(SSH2)";
1388 case SSH_CIPHER_3DES_CBC:
1389 return "3DES-CBC(SSH2)";
1390
1391 default:
1392 return NULL;
1393 }
1394 }
1395
1396 static void set_move_button_status(HWND dlg)
1397 {
1398 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1399 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1400 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1401
1402 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1403 && curPos <= maxPos);
1404 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1405 && curPos < maxPos);
1406 }
1407
1408 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1409 {
1410 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1411 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1412 int i;
1413 int ch;
1414
1415 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1416 SendMessage(compressionControl, TBM_SETPOS, TRUE,
1417 pvar->settings.CompressionLevel);
1418
1419 normalize_cipher_order(pvar->settings.CipherOrder);
1420 SSH2_update_cipher_myproposal(pvar); // yutaka
1421
1422 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1423 int cipher = pvar->settings.CipherOrder[i] - '0';
1424 char FAR *name = get_cipher_name(cipher);
1425
1426 if (name != NULL) {
1427 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1428 }
1429 }
1430
1431 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1432 set_move_button_status(dlg);
1433
1434 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1435 i++) {
1436 }
1437 if (ch != 0) {
1438 pvar->settings.KnownHostsFiles[i] = 0;
1439 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1440 pvar->settings.KnownHostsFiles);
1441 pvar->settings.KnownHostsFiles[i] = ch;
1442 SetDlgItemText(dlg, IDC_READONLYFILENAME,
1443 pvar->settings.KnownHostsFiles + i + 1);
1444 } else {
1445 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1446 pvar->settings.KnownHostsFiles);
1447 }
1448 }
1449
1450 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1451 char FAR * basename)
1452 {
1453 int filename_start = 0;
1454 int i;
1455 int ch;
1456
1457 if (basename[0] == '\\' || basename[0] == '/'
1458 || (basename[0] != 0 && basename[1] == ':')) {
1459 strncpy(buf, basename, bufsize);
1460 buf[bufsize - 1] = 0;
1461 return;
1462 }
1463
1464 GetModuleFileName(NULL, buf, bufsize);
1465 for (i = 0; (ch = buf[i]) != 0; i++) {
1466 if (ch == '\\' || ch == '/' || ch == ':') {
1467 filename_start = i + 1;
1468 }
1469 }
1470
1471 if (bufsize > filename_start) {
1472 strncpy(buf + filename_start, basename, bufsize - filename_start);
1473 }
1474 buf[bufsize - 1] = 0;
1475 }
1476
1477 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1478 char FAR * basename)
1479 {
1480 char buf[1024];
1481 int filename_start = 0;
1482 int i;
1483 int ch, ch2;
1484
1485 if (basename[0] != '\\' && basename[0] != '/'
1486 && (basename[0] == 0 || basename[1] != ':')) {
1487 strncpy(dest, basename, destsize);
1488 dest[destsize - 1] = 0;
1489 return strlen(dest);
1490 }
1491
1492 GetModuleFileName(NULL, buf, sizeof(buf));
1493 for (i = 0; (ch = buf[i]) != 0; i++) {
1494 if (ch == '\\' || ch == '/' || ch == ':') {
1495 filename_start = i + 1;
1496 }
1497 }
1498
1499 for (i = 0; i < filename_start; i++) {
1500 ch = toupper(buf[i]);
1501 ch2 = toupper(basename[i]);
1502
1503 if (ch == ch2
1504 || ((ch == '\\' || ch == '/')
1505 && (ch2 == '\\' || ch2 == '/'))) {
1506 } else {
1507 break;
1508 }
1509 }
1510
1511 if (i == filename_start) {
1512 strncpy(dest, basename + i, destsize);
1513 } else {
1514 strncpy(dest, basename, destsize);
1515 }
1516 dest[destsize - 1] = 0;
1517 return strlen(dest);
1518 }
1519
1520 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1521 {
1522 char buf[4096];
1523 char buf2[1024];
1524 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1525 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1526 int i, j, buf2index, bufindex;
1527 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1528
1529 pvar->settings.CompressionLevel =
1530 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1531
1532 buf2index = 0;
1533 for (i = 0; i < count; i++) {
1534 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1535
1536 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1537 buf[0] = 0;
1538 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1539 for (j = 0;
1540 j <= SSH_CIPHER_MAX
1541 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1542 }
1543 if (j <= SSH_CIPHER_MAX) {
1544 buf2[buf2index] = '0' + j;
1545 buf2index++;
1546 }
1547 }
1548 }
1549 buf2[buf2index] = 0;
1550 normalize_cipher_order(buf2);
1551 strcpy(pvar->settings.CipherOrder, buf2);
1552 SSH2_update_cipher_myproposal(pvar); // yutaka
1553
1554 buf[0] = 0;
1555 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1556 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1557 sizeof(pvar->settings.
1558 KnownHostsFiles), buf);
1559 buf[0] = 0;
1560 bufindex = 0;
1561 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1562 for (i = 0; buf[i] != 0; i++) {
1563 if (buf[i] == ';') {
1564 buf[i] = 0;
1565 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1566 pvar->settings.KnownHostsFiles[j] = ';';
1567 j++;
1568 j += copy_teraterm_dir_relative_path(pvar->settings.
1569 KnownHostsFiles + j,
1570 sizeof(pvar->settings.
1571 KnownHostsFiles)
1572 - j, buf + bufindex);
1573 }
1574 bufindex = i + 1;
1575 }
1576 }
1577 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1578 pvar->settings.KnownHostsFiles[j] = ';';
1579 j++;
1580 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1581 sizeof(pvar->settings.
1582 KnownHostsFiles) - j,
1583 buf + bufindex);
1584 }
1585 }
1586
1587 static void move_cur_sel_delta(HWND listbox, int delta)
1588 {
1589 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1590 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1591 int newPos = curPos + delta;
1592 char buf[1024];
1593
1594 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1595 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1596
1597 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1598 buf[0] = 0;
1599 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1600 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1601 SendMessage(listbox, LB_INSERTSTRING, newPos,
1602 (LPARAM) (char FAR *) buf);
1603 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1604 }
1605 }
1606 }
1607
1608 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1609 int readonly)
1610 {
1611 #ifdef TERATERM32
1612 OPENFILENAME params;
1613 char fullname_buf[2048] = "ssh_known_hosts";
1614
1615 params.lStructSize = sizeof(OPENFILENAME);
1616 params.hwndOwner = parent;
1617 params.lpstrFilter = NULL;
1618 params.lpstrCustomFilter = NULL;
1619 params.nFilterIndex = 0;
1620 buf[0] = 0;
1621 params.lpstrFile = fullname_buf;
1622 params.nMaxFile = sizeof(fullname_buf);
1623 params.lpstrFileTitle = NULL;
1624 params.lpstrInitialDir = NULL;
1625 params.lpstrTitle =
1626 readonly ? "Choose a read-only known-hosts file to add" :
1627 "Choose a read/write known-hosts file";
1628 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1629 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1630 params.lpstrDefExt = NULL;
1631
1632 if (GetOpenFileName(&params) != 0) {
1633 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1634 return 1;
1635 } else {
1636 int err = CommDlgExtendedError();
1637
1638 if (err != 0) {
1639 char buf[1024];
1640
1641 _snprintf(buf, sizeof(buf),
1642 "Cannot show file dialog box: error %d", err);
1643 buf[sizeof(buf) - 1] = 0;
1644 MessageBox(parent, buf, "TTSSH Error",
1645 MB_OK | MB_ICONEXCLAMATION);
1646 }
1647
1648 return 0;
1649 }
1650 #else
1651 return 0;
1652 #endif
1653 }
1654
1655 static void choose_read_write_file(HWND dlg)
1656 {
1657 char buf[1024];
1658
1659 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1660 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1661 }
1662 }
1663
1664 static void choose_read_only_file(HWND dlg)
1665 {
1666 char buf[1024];
1667 char buf2[4096];
1668
1669 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1670 buf2[0] = 0;
1671 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1672 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1673 strncat(buf2, ";", sizeof(buf2));
1674 }
1675 strncat(buf2, buf, sizeof(buf2));
1676 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1677 }
1678 }
1679
1680 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1681 LPARAM lParam)
1682 {
1683 switch (msg) {
1684 case WM_INITDIALOG:
1685 SetWindowLong(dlg, DWL_USER, lParam);
1686 init_setup_dlg((PTInstVar) lParam, dlg);
1687 return TRUE;
1688 case WM_COMMAND:
1689 switch (LOWORD(wParam)) {
1690 case IDOK:
1691 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1692 dlg);
1693 EndDialog(dlg, 1);
1694 return TRUE;
1695 case IDCANCEL: /* there isn't a cancel button, but other Windows
1696 UI things can send this message */
1697 EndDialog(dlg, 0);
1698 return TRUE;
1699 case IDC_SSHMOVECIPHERUP:
1700 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1701 set_move_button_status(dlg);
1702 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1703 return TRUE;
1704 case IDC_SSHMOVECIPHERDOWN:
1705 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1706 set_move_button_status(dlg);
1707 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1708 return TRUE;
1709 case IDC_SSHCIPHERPREFS:
1710 set_move_button_status(dlg);
1711 return TRUE;
1712 case IDC_CHOOSEREADWRITEFILE:
1713 choose_read_write_file(dlg);
1714 return TRUE;
1715 case IDC_CHOOSEREADONLYFILE:
1716 choose_read_only_file(dlg);
1717 return TRUE;
1718 }
1719 break;
1720 }
1721
1722 return FALSE;
1723 }
1724
1725 static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1726 {
1727 GET_VAR();
1728
1729 if (pvar->fatal_error) {
1730 return 0;
1731 }
1732
1733 switch (cmd) {
1734 case ID_ABOUTMENU:
1735 if (DialogBoxParam
1736 (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1737 (LPARAM) pvar)
1738 == -1) {
1739 MessageBox(hWin, "Cannot create About box window.",
1740 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1741 }
1742 return 1;
1743 case ID_SSHAUTH:
1744 AUTH_do_cred_dialog(pvar);
1745 return 1;
1746 case ID_SSHSETUPMENU:
1747 if (DialogBoxParam
1748 (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1749 (LPARAM) pvar)
1750 == -1) {
1751 MessageBox(hWin, "Cannot create TTSSH Setup window.",
1752 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1753 }
1754 return 1;
1755 case ID_SSHAUTHSETUPMENU:
1756 AUTH_do_default_cred_dialog(pvar);
1757 return 1;
1758 case ID_SSHFWDSETUPMENU:
1759 FWDUI_do_forwarding_dialog(pvar);
1760 return 1;
1761 case ID_SSHUNKNOWNHOST:
1762 HOSTS_do_unknown_host_dialog(hWin, pvar);
1763 return 1;
1764 case ID_SSHDIFFERENTHOST:
1765 HOSTS_do_different_host_dialog(hWin, pvar);
1766 return 1;
1767 case ID_SSHASYNCMESSAGEBOX:
1768 if (pvar->err_msg != NULL) {
1769 char FAR *msg = pvar->err_msg;
1770
1771 /* Could there be a buffer overrun bug anywhere in Win32
1772 MessageBox? Who knows? I'm paranoid. */
1773 if (strlen(msg) > 2048) {
1774 msg[2048] = 0;
1775 }
1776
1777 pvar->showing_err = TRUE;
1778 pvar->err_msg = NULL;
1779 MessageBox(NULL, msg, "TTSSH",
1780 MB_TASKMODAL | MB_ICONEXCLAMATION);
1781 free(msg);
1782 pvar->showing_err = FALSE;
1783 if (pvar->err_msg != NULL) {
1784 PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1785 } else {
1786 AUTH_notify_end_error(pvar);
1787 }
1788 }
1789 return 1;
1790 default:
1791 return 0;
1792 }
1793 }
1794
1795 static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
1796 PGetHNRec rec)
1797 {
1798 char tmpFile[MAX_PATH];
1799 char tmpPath[1024];
1800 char buf[1024];
1801 int i;
1802 GET_VAR();
1803
1804 GetTempPath(sizeof(tmpPath), tmpPath);
1805 GetTempFileName(tmpPath, "TTX", 0, tmpFile);
1806
1807 for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
1808 }
1809
1810 if (i < cmdlen) {
1811 strncpy(buf, cmd + i, sizeof(buf));
1812 cmd[i] = 0;
1813
1814 write_ssh_options(pvar, tmpFile, &pvar->settings);
1815
1816 strncat(cmd, " /ssh-consume=", cmdlen);
1817 strncat(cmd, tmpFile, cmdlen);
1818
1819 strncat(cmd, buf, cmdlen);
1820
1821 if (pvar->hostdlg_Enabled) {
1822 strncat(cmd, " /ssh", cmdlen);
1823
1824 // add option of SSH protcol version (2004.10.11 yutaka)
1825 if (pvar->settings.ssh_protocol_version == 2) {
1826 strncat(cmd, " /2", cmdlen);
1827 } else {
1828 strncat(cmd, " /1", cmdlen);
1829 }
1830
1831 }
1832 }
1833 }
1834
1835 /* This function is called when Teraterm is quitting. You can use it to clean
1836 up.
1837
1838 This function is called for each extension, in reverse load order (see
1839 below).
1840 */
1841 static void PASCAL FAR TTXEnd(void)
1842 {
1843 GET_VAR();
1844
1845 uninit_TTSSH(pvar);
1846
1847 if (pvar->err_msg != NULL) {
1848 /* Could there be a buffer overrun bug anywhere in Win32
1849 MessageBox? Who knows? I'm paranoid. */
1850 if (strlen(pvar->err_msg) > 2048) {
1851 pvar->err_msg[2048] = 0;
1852 }
1853
1854 MessageBox(NULL, pvar->err_msg, "TTSSH",
1855 MB_TASKMODAL | MB_ICONEXCLAMATION);
1856
1857 free(pvar->err_msg);
1858 pvar->err_msg = NULL;
1859 }
1860 #ifndef TERATERM32
1861 DelVar();
1862 #endif
1863 }
1864
1865 /* This record contains all the information that the extension forwards to the
1866 main Teraterm code. It mostly consists of pointers to the above functions.
1867 Any of the function pointers can be replaced with NULL, in which case
1868 Teraterm will just ignore that function and assume default behaviour, which
1869 means "do nothing".
1870 */
1871 static TTXExports Exports = {
1872 /* This must contain the size of the structure. See below for its usage. */
1873 sizeof(TTXExports),
1874 ORDER,
1875
1876 /* Now we just list the functions that we've implemented. */
1877 TTXInit,
1878 TTXGetUIHooks,
1879 TTXGetSetupHooks,
1880 TTXOpenTCP,
1881 TTXCloseTCP,
1882 TTXSetWinSize,
1883 TTXModifyMenu,
1884 NULL,
1885 TTXProcessCommand,
1886 TTXEnd,
1887 TTXSetCommandLine
1888 };
1889
1890 #ifdef TERATERM32
1891 BOOL __declspec(dllexport)
1892 PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
1893 {
1894 #else
1895 BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
1896 {
1897 #endif
1898 int size = sizeof(Exports) - sizeof(exports->size);
1899 /* do version checking if necessary */
1900 /* if (Version!=TTVERSION) return FALSE; */
1901
1902 if (size > exports->size) {
1903 size = exports->size;
1904 }
1905 memcpy((char FAR *) exports + sizeof(exports->size),
1906 (char FAR *) &Exports + sizeof(exports->size), size);
1907 return TRUE;
1908 }
1909
1910 #ifdef TERATERM32
1911 static HANDLE __mem_mapping = NULL;
1912
1913 BOOL WINAPI DllMain(HANDLE hInstance,
1914 ULONG ul_reason_for_call, LPVOID lpReserved)
1915 {
1916 switch (ul_reason_for_call) {
1917 case DLL_THREAD_ATTACH:
1918 /* do thread initialization */
1919 break;
1920 case DLL_THREAD_DETACH:
1921 /* do thread cleanup */
1922 break;
1923 case DLL_PROCESS_ATTACH:
1924 /* do process initialization */
1925 DisableThreadLibraryCalls(hInstance);
1926 hInst = hInstance;
1927 pvar = &InstVar;
1928 __mem_mapping =
1929 CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
1930 sizeof(TS_SSH), "TTSSH_1-4_TS_data");
1931 if (__mem_mapping == NULL) {
1932 /* fake it. The settings won't be shared, but what the heck. */
1933 pvar->ts_SSH = NULL;
1934 } else {
1935 pvar->ts_SSH =
1936 (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
1937 0, 0);
1938 }
1939 if (pvar->ts_SSH == NULL) {
1940 /* fake it. The settings won't be shared, but what the heck. */
1941 pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
1942 if (__mem_mapping != NULL) {
1943 CloseHandle(__mem_mapping);
1944 }
1945 }
1946 break;
1947 case DLL_PROCESS_DETACH:
1948 /* do process cleanup */
1949 if (__mem_mapping == NULL) {
1950 free(pvar->ts_SSH);
1951 } else {
1952 CloseHandle(__mem_mapping);
1953 UnmapViewOfFile(pvar->ts_SSH);
1954 }
1955 break;
1956 }
1957 return TRUE;
1958 }
1959 #else
1960 #ifdef WATCOM
1961 #pragma off (unreferenced);
1962 #endif
1963 int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
1964 WORD wHeapSize, LPSTR lpszCmdLine)
1965 #ifdef WATCOM
1966 #pragma on (unreferenced);
1967 #endif
1968 {
1969 int i;
1970 for (i = 0; i < MAXNUMINST; i++)
1971 TaskList[i] = NULL;
1972 hInst = hInstance;
1973 return (1);
1974 }
1975 #endif
1976
1977
1978 /*
1979 * $Log: not supported by cvs2svn $
1980 * Revision 1.2 2004/11/23 14:32:26 yutakakn
1981 * �����_�C�A���O���N�������ATCP/IP���u�z�X�g���v���t�H�[�J�X�������������������B
1982 *
1983 *
1984 */

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26