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 2766 - (show annotations) (download) (as text)
Mon Dec 27 14:05:08 2004 UTC (19 years, 3 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 55576 byte(s)
'Auto window close'が有効の場合、切断後の接続ができない問題を修正した。
 ・スレッドの終了待ち合わせ処理の追加
 ・確保済みSSHリソースの解放

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

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