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 2799 - (show annotations) (download) (as text)
Sat Mar 12 12:08:05 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 60555 byte(s)
パスワード認証の前に行うkeyboard-interactiveメソッドで、デフォルト設定値を無効(0)にした。
また、認証ダイアログのラベル名を設定の有無により変更するようにした。

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

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