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 2805 - (show annotations) (download) (as text)
Sun Mar 27 04:39:55 2005 UTC (19 years ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 61478 byte(s)
SSH2のログ採取(verbose)のデータを追加した。

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

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