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

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