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 2992 - (show annotations) (download) (as text)
Wed Aug 8 16:04:09 2007 UTC (16 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 123964 byte(s)
安全な関数を使用するように変更した。

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 #include "ttcommon.h"
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <io.h>
45 #include <fcntl.h>
46 #include <sys/stat.h>
47 #include <time.h>
48
49 #include "resource.h"
50 #include <commctrl.h>
51 #include <commdlg.h>
52 #ifndef NO_INET6
53 #include <winsock2.h>
54 static char FAR *ProtocolFamilyList[] = { "UNSPEC", "IPv6", "IPv4", NULL };
55 #else
56 #include <winsock.h>
57 #endif /* NO_INET6 */
58
59 #include <Lmcons.h>
60
61 // include OpenSSL header file
62 #include <openssl/opensslv.h>
63 #include <openssl/evp.h>
64 #include <openssl/rsa.h>
65 #include <openssl/dsa.h>
66 #include <openssl/bn.h>
67 #include <openssl/pem.h>
68 #include <openssl/rand.h>
69 #include <openssl/rc4.h>
70 #include <openssl/md5.h>
71
72 // include ZLib header file
73 #include <zlib.h>
74
75 #include "buffer.h"
76 #include "cipher.h"
77
78
79 #define MATCH_STR(s, o) strncmp((s), (o), NUM_ELEM(o) - 1)
80 #define MATCH_STR_I(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
81
82 /* This extension implements SSH, so we choose a load order in the
83 "protocols" range. */
84 #define ORDER 2500
85
86 #ifdef TERATERM32
87 static HICON SecureLargeIcon = NULL;
88 static HICON SecureSmallIcon = NULL;
89 #endif
90
91 #ifndef NO_I18N
92 static HFONT DlgHostFont;
93 static HFONT DlgAboutFont;
94 static HFONT DlgSetupFont;
95 static HFONT DlgKeygenFont;
96 #endif
97
98 static TInstVar FAR *pvar;
99
100 #ifdef TERATERM32
101 /* WIN32 allows multiple instances of a DLL */
102 static TInstVar InstVar;
103 #define GET_VAR()
104 #else
105 /* WIN16 does not allow multiple instances of a DLL */
106
107 /* maximum number of Tera Term instances */
108 #define MAXNUMINST 32
109 /* list of task handles for Tera Term instances */
110 static HANDLE FAR TaskList[MAXNUMINST];
111 /* variable sets for instances */
112 static TInstVar FAR *FAR InstVar[MAXNUMINST];
113
114 /* Here's how the TS settings work.
115 Whenever the TS settings are read or written to the INI file, then
116 the shared memory containing those settings is updated.
117 When Teraterm starts, the shared memory is read to initialize the TS
118 settings. */
119
120 /* TS settings shared across instances */
121 static TS_SSH ts_SSH_settings;
122
123
124 extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
125
126
127 static BOOL NewVar()
128 {
129 int i = 0;
130 HANDLE Task = GetCurrentTask();
131
132 if (TaskList[0] == NULL)
133
134 if (Task == NULL)
135 return FALSE;
136 while ((i < MAXNUMINST) && (TaskList[i] != NULL))
137 i++;
138 if (i >= MAXNUMINST)
139 return FALSE;
140 pvar = (TInstVar FAR *) malloc(sizeof(TInstVar));
141 InstVar[i] = pvar;
142 TaskList[i] = Task;
143 return TRUE;
144 }
145
146 void DelVar()
147 {
148 int i = 0;
149 HANDLE Task = GetCurrentTask();
150
151 if (Task == NULL)
152 return;
153 while ((i < MAXNUMINST) && (TaskList[i] != Task))
154 i++;
155 if (i >= MAXNUMINST)
156 return;
157 free(TaskList[i]);
158 TaskList[i] = NULL;
159 }
160
161 BOOL GetVar()
162 {
163 int i = 0;
164 HANDLE Task = GetCurrentTask();
165
166 if (Task == NULL)
167 return FALSE;
168 while ((i < MAXNUMINST) && (TaskList[i] != Task))
169 i++;
170 if (i >= MAXNUMINST)
171 return FALSE;
172 pvar = InstVar[i];
173 return TRUE;
174 }
175
176 #define GET_VAR() if (!GetVar()) return
177 #endif
178
179 /*
180 This code makes lots of assumptions about the order in which Teraterm
181 does things, and how. A key assumption is that the Notification window
182 passed into WSAAsyncSelect is the main terminal window. We also assume
183 that the socket used in the first WSAconnect is the main session socket.
184 */
185
186 static void init_TTSSH(PTInstVar pvar)
187 {
188 pvar->socket = INVALID_SOCKET;
189 pvar->OldLargeIcon = NULL;
190 pvar->OldSmallIcon = NULL;
191 pvar->NotificationWindow = NULL;
192 pvar->hostdlg_activated = FALSE;
193 pvar->socket = INVALID_SOCKET;
194 pvar->NotificationWindow = NULL;
195 pvar->protocol_major = 0;
196 pvar->protocol_minor = 0;
197
198 PKT_init(pvar);
199 SSH_init(pvar);
200 CRYPT_init(pvar);
201 AUTH_init(pvar);
202 HOSTS_init(pvar);
203 FWD_init(pvar);
204 FWDUI_init(pvar);
205
206 ssh_heartbeat_lock_initialize();
207 }
208
209 static void uninit_TTSSH(PTInstVar pvar)
210 {
211 halt_ssh_heartbeat_thread(pvar);
212
213 ssh2_channel_free();
214
215 SSH_end(pvar);
216 PKT_end(pvar);
217 AUTH_end(pvar);
218 CRYPT_end(pvar);
219 HOSTS_end(pvar);
220 FWD_end(pvar);
221 FWDUI_end(pvar);
222
223 if (pvar->OldLargeIcon != NULL) {
224 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
225 (LPARAM) pvar->OldLargeIcon);
226 pvar->OldLargeIcon = NULL;
227 }
228 if (pvar->OldSmallIcon != NULL) {
229 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
230 (LPARAM) pvar->OldSmallIcon);
231 pvar->OldSmallIcon = NULL;
232 }
233
234 ssh_heartbeat_lock_finalize();
235 }
236
237 static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv)
238 {
239 #ifndef TERATERM32
240 if (!NewVar())
241 return; /* should be called first */
242 pvar->ts_SSH = &ts_SSH_settings;
243 #endif
244 pvar->settings = *pvar->ts_SSH;
245 pvar->ts = ts;
246 pvar->cv = cv;
247 pvar->fatal_error = FALSE;
248 pvar->showing_err = FALSE;
249 pvar->err_msg = NULL;
250
251 init_TTSSH(pvar);
252 }
253
254 static void normalize_cipher_order(char FAR * buf)
255 {
256 char ciphers_listed[SSH_CIPHER_MAX + 1];
257 char ciphers_allowed[SSH_CIPHER_MAX + 1];
258 int i, j;
259
260 /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
261 We *never* allow no encryption. */
262 #if 0
263 static char default_ciphers[] = {
264 SSH_CIPHER_3DES,
265 SSH_CIPHER_NONE,
266 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
267 };
268 #else
269 // for SSH2(yutaka)
270 static char default_ciphers[] = {
271 SSH_CIPHER_AES128,
272 SSH_CIPHER_3DES_CBC,
273 SSH_CIPHER_3DES,
274 SSH_CIPHER_NONE,
275 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
276 };
277 #endif
278
279 memset(ciphers_listed, 0, sizeof(ciphers_listed));
280
281 memset(ciphers_allowed, 0, sizeof(ciphers_allowed));
282 for (i = 0; i < NUM_ELEM(default_ciphers); i++) {
283 ciphers_allowed[default_ciphers[i]] = 1;
284 }
285
286 for (i = 0; buf[i] != 0; i++) {
287 int cipher_num = buf[i] - '0';
288
289 if (cipher_num < 0 || cipher_num > SSH_CIPHER_MAX
290 || !ciphers_allowed[cipher_num]
291 || ciphers_listed[cipher_num]) {
292 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
293 i--;
294 } else {
295 ciphers_listed[cipher_num] = 1;
296 }
297 }
298
299 for (j = 0; j < NUM_ELEM(default_ciphers); j++) {
300 int cipher_num = default_ciphers[j];
301
302 if (!ciphers_listed[cipher_num]) {
303 buf[i] = cipher_num + '0';
304 i++;
305 }
306 }
307
308 buf[i] = 0;
309 }
310
311 /* Remove local settings from the shared memory block. */
312 static void clear_local_settings(PTInstVar pvar)
313 {
314 pvar->ts_SSH->TryDefaultAuth = FALSE;
315 }
316
317 static BOOL read_BOOL_option(PCHAR fileName, char FAR * keyName, BOOL def)
318 {
319 char buf[1024];
320
321 buf[0] = 0;
322 GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
323 fileName);
324 if (buf[0] == 0) {
325 return def;
326 } else {
327 return atoi(buf) != 0 ||
328 _stricmp(buf, "yes") == 0 || _stricmp(buf, "y") == 0;
329 }
330 }
331
332 static void read_string_option(PCHAR fileName, char FAR * keyName,
333 char FAR * def, char FAR * buf, int bufSize)
334 {
335
336 buf[0] = 0;
337 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
338 }
339
340 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
341 {
342 char buf[1024];
343 TS_SSH FAR *settings = pvar->ts_SSH;
344
345 #define READ_STD_STRING_OPTION(name) \
346 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
347
348 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
349
350 buf[0] = 0;
351 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
352 fileName);
353 settings->CompressionLevel = atoi(buf);
354 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
355 settings->CompressionLevel = 0;
356 }
357
358 READ_STD_STRING_OPTION(DefaultUserName);
359 READ_STD_STRING_OPTION(DefaultForwarding);
360 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
361 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
362 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
363
364 READ_STD_STRING_OPTION(CipherOrder);
365 normalize_cipher_order(settings->CipherOrder);
366
367 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
368 settings->KnownHostsFiles,
369 sizeof(settings->KnownHostsFiles));
370
371 buf[0] = 0;
372 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
373 sizeof(buf), fileName);
374 settings->DefaultAuthMethod = atoi(buf);
375 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
376 && settings->DefaultAuthMethod != SSH_AUTH_RSA
377 && settings->DefaultAuthMethod != SSH_AUTH_TIS // add (2005.3.12 yutaka)
378 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS) {
379 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
380 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
381 when the dialog box has rhosts selected and an host private key file
382 is supplied. */
383 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
384 }
385
386 buf[0] = 0;
387 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
388 fileName);
389 settings->LogLevel = atoi(buf);
390
391 buf[0] = 0;
392 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
393 sizeof(buf), fileName);
394 settings->WriteBufferSize = atoi(buf);
395 if (settings->WriteBufferSize <= 0) {
396 settings->WriteBufferSize = 2 * 1024 * 1024;
397 }
398
399 settings->LocalForwardingIdentityCheck =
400 read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
401
402 // SSH protocol version (2004.10.11 yutaka)
403 // default is SSH2 (2004.11.30 yutaka)
404 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
405
406 // SSH heartbeat time(second) (2004.12.11 yutaka)
407 settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
408
409 // SSH2 keyboard-interactive (2005.1.23 yutaka)
410 // �f�t�H���g���������������BOpenSSH 4.0����keyboard-interactive���\�b�h�����`�������������������A
411 // ���Y���\�b�h���g�����R�l�N�V���������������������B(2005.3.12 yutaka)
412 settings->ssh2_keyboard_interactive = GetPrivateProfileInt("TTSSH", "KeyboardInteractive", 0, fileName);
413
414 // �p�X���[�h�F�����������J���F�����g���p�X���[�h����������������������������������
415 // �\���B(2006.8.5 yutaka)
416 settings->remember_password = GetPrivateProfileInt("TTSSH", "RememberPassword", 1, fileName);
417
418 clear_local_settings(pvar);
419 }
420
421 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
422 TS_SSH FAR * settings, BOOL copy_forward)
423 {
424 char buf[1024];
425
426 WritePrivateProfileString("TTSSH", "Enabled",
427 settings->Enabled ? "1" : "0", fileName);
428
429 _itoa(settings->CompressionLevel, buf, 10);
430 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
431
432 WritePrivateProfileString("TTSSH", "DefaultUserName",
433 settings->DefaultUserName, fileName);
434
435 if (copy_forward) {
436 WritePrivateProfileString("TTSSH", "DefaultForwarding",
437 settings->DefaultForwarding, fileName);
438 }
439
440 WritePrivateProfileString("TTSSH", "CipherOrder",
441 settings->CipherOrder, fileName);
442
443 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
444 settings->KnownHostsFiles, fileName);
445
446 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
447 settings->DefaultRhostsLocalUserName,
448 fileName);
449
450 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
451 settings->DefaultRhostsHostPrivateKeyFile,
452 fileName);
453
454 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
455 settings->DefaultRSAPrivateKeyFile,
456 fileName);
457
458 _itoa(settings->DefaultAuthMethod, buf, 10);
459 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
460
461 _itoa(settings->LogLevel, buf, 10);
462 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
463
464 _itoa(settings->WriteBufferSize, buf, 10);
465 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
466
467 WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
468 settings->
469 LocalForwardingIdentityCheck ? "1" : "0",
470 fileName);
471
472 // SSH protocol version (2004.10.11 yutaka)
473 WritePrivateProfileString("TTSSH", "ProtocolVersion",
474 settings->ssh_protocol_version==2 ? "2" : "1",
475 fileName);
476
477 // SSH heartbeat time(second) (2004.12.11 yutaka)
478 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
479 "%d", settings->ssh_heartbeat_overtime);
480 WritePrivateProfileString("TTSSH", "HeartBeat", buf, fileName);
481
482 // SSH2 keyboard-interactive (2005.1.23 yutaka)
483 WritePrivateProfileString("TTSSH", "KeyboardInteractive",
484 settings->ssh2_keyboard_interactive ? "1" : "0",
485 fileName);
486
487 // Remember password (2006.8.5 yutaka)
488 WritePrivateProfileString("TTSSH", "RememberPassword",
489 settings->remember_password ? "1" : "0",
490 fileName);
491 }
492
493
494 /* find free port in all protocol family */
495 static unsigned short find_local_port(PTInstVar pvar)
496 {
497 int tries;
498 #ifndef NO_INET6
499 SOCKET connecter;
500 struct addrinfo hints;
501 struct addrinfo FAR *res;
502 struct addrinfo FAR *res0;
503 unsigned short port;
504 char pname[NI_MAXHOST];
505 #endif /* NO_INET6 */
506
507 if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
508 return 0;
509 }
510
511 /* The random numbers here are only used to try to get fresh
512 ports across runs (dangling ports can cause bind errors
513 if we're unlucky). They do not need to be (and are not)
514 cryptographically strong.
515 */
516 srand((unsigned) GetTickCount());
517
518 #ifndef NO_INET6
519 for (tries = 20; tries > 0; tries--) {
520 memset(&hints, 0, sizeof(hints));
521 hints.ai_family = pvar->ts->ProtocolFamily;
522 hints.ai_flags = AI_PASSIVE;
523 hints.ai_socktype = SOCK_STREAM;
524 port = (unsigned) rand() % 512 + 512;
525 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", (int) port);
526 if (getaddrinfo(NULL, pname, &hints, &res0)) {
527 return 0;
528 /* NOT REACHED */
529 }
530
531 for (res = res0; res; res = res->ai_next) {
532 if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
533 continue;
534
535 connecter =
536 socket(res->ai_family, res->ai_socktype, res->ai_protocol);
537 if (connecter == INVALID_SOCKET) {
538 freeaddrinfo(res0);
539 return 0;
540 }
541
542 if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
543 SOCKET_ERROR) {
544 return port;
545 freeaddrinfo(res0);
546 closesocket(connecter);
547 } else if (WSAGetLastError() != WSAEADDRINUSE) {
548 closesocket(connecter);
549 freeaddrinfo(res0);
550 return 0;
551 }
552
553 closesocket(connecter);
554 }
555 freeaddrinfo(res0);
556 }
557
558 return 0;
559 #else
560 for (tries = 20; tries > 0; tries--) {
561 SOCKET connecter = socket(AF_INET, SOCK_STREAM, 0);
562 struct sockaddr_in connecter_addr;
563
564 connecter_addr.sin_family = AF_INET;
565 connecter_addr.sin_port = (unsigned) rand() % 512 + 512;
566 connecter_addr.sin_addr.s_addr = htonl(INADDR_ANY);
567
568 if (connecter == INVALID_SOCKET) {
569 return 0;
570 }
571
572 if (bind
573 (connecter, (struct sockaddr FAR *) &connecter_addr,
574 sizeof(connecter_addr)) != SOCKET_ERROR) {
575 closesocket(connecter);
576 return connecter_addr.sin_port;
577 } else if (WSAGetLastError() != WSAEADDRINUSE) {
578 closesocket(connecter);
579 return 0;
580 }
581
582 closesocket(connecter);
583 }
584
585 return 0;
586 #endif /* NO_INET6 */
587 }
588
589 static int PASCAL FAR TTXconnect(SOCKET s,
590 const struct sockaddr FAR * name,
591 int namelen)
592 {
593 GET_VAR();
594
595 #ifndef NO_INET6
596 if (pvar->socket == INVALID_SOCKET) {
597 struct sockaddr_storage ss;
598 int len;
599
600 pvar->socket = s;
601
602 memset(&ss, 0, sizeof(ss));
603 switch (pvar->ts->ProtocolFamily) {
604 case AF_INET:
605 len = sizeof(struct sockaddr_in);
606 ((struct sockaddr_in FAR *) &ss)->sin_family = AF_INET;
607 ((struct sockaddr_in FAR *) &ss)->sin_addr.s_addr = INADDR_ANY;
608 ((struct sockaddr_in FAR *) &ss)->sin_port =
609 htons(find_local_port(pvar));
610 break;
611 case AF_INET6:
612 len = sizeof(struct sockaddr_in6);
613 ((struct sockaddr_in6 FAR *) &ss)->sin6_family = AF_INET6;
614 #if 0 /* symbol "in6addr_any" is not included in wsock32.lib */
615 /* if wsock32.lib will be linked, we can't refer "in6addr_any" */
616 ((struct sockaddr_in6 FAR *) &ss)->sin6_addr = in6addr_any;
617 #eles
618 memset(&((struct sockaddr_in6 FAR *) &ss)->sin6_addr, 0,
619 sizeof(struct in_addr6));
620 #endif /* 0 */
621 ((struct sockaddr_in6 FAR *) &ss)->sin6_port =
622 htons(find_local_port(pvar));
623 break;
624 default:
625 /* NOT REACHED */
626 break;
627 }
628
629 bind(s, (struct sockaddr FAR *) &ss, len);
630 }
631 #else
632 if (pvar->socket == INVALID_SOCKET) {
633 struct sockaddr_in addr;
634
635 pvar->socket = s;
636
637 addr.sin_family = AF_INET;
638 addr.sin_port = htons(find_local_port(pvar));
639 addr.sin_addr.s_addr = INADDR_ANY;
640 memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
641
642 bind(s, (struct sockaddr FAR *) &addr, sizeof(addr));
643 }
644 #endif /* NO_INET6 */
645
646 return (pvar->Pconnect) (s, name, namelen);
647 }
648
649 static int PASCAL FAR TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
650 long lEvent)
651 {
652 GET_VAR();
653
654 if (s == pvar->socket) {
655 pvar->notification_events = lEvent;
656 pvar->notification_msg = wMsg;
657
658 if (pvar->NotificationWindow == NULL) {
659 pvar->NotificationWindow = hWnd;
660 AUTH_advance_to_next_cred(pvar);
661 }
662 }
663
664 return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
665 }
666
667 static int PASCAL FAR TTXrecv(SOCKET s, char FAR * buf, int len, int flags)
668 {
669 GET_VAR();
670
671 if (s == pvar->socket) {
672 int ret;
673
674 ssh_heartbeat_lock();
675 ret = PKT_recv(pvar, buf, len);
676 ssh_heartbeat_unlock();
677 return (ret);
678
679 } else {
680 return (pvar->Precv) (s, buf, len, flags);
681 }
682 }
683
684 static int PASCAL FAR TTXsend(SOCKET s, char const FAR * buf, int len,
685 int flags)
686 {
687 GET_VAR();
688
689 if (s == pvar->socket) {
690 ssh_heartbeat_lock();
691 SSH_send(pvar, buf, len);
692 ssh_heartbeat_unlock();
693 return len;
694 } else {
695 return (pvar->Psend) (s, buf, len, flags);
696 }
697 }
698
699 void notify_established_secure_connection(PTInstVar pvar)
700 {
701 #ifdef TERATERM32
702 // LoadIcon �������� LoadImage ���g�����������A
703 // 16x16 ���A�C�R���������I�������������������� (2006.8.9 maya)
704 if (SecureLargeIcon == NULL) {
705 SecureLargeIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_SECURETT),
706 IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
707 }
708 if (SecureSmallIcon == NULL) {
709 SecureSmallIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_SECURETT),
710 IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
711 }
712
713 if (SecureLargeIcon != NULL && SecureSmallIcon != NULL) {
714 // �������A�C�R���� WNDCLASS ���Z�b�g�����������������o���������� (2006.8.10 maya)
715 pvar->OldLargeIcon =
716 (HICON) GetClassLong(pvar->NotificationWindow, GCL_HICON);
717 pvar->OldSmallIcon =
718 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
719 ICON_SMALL, 0);
720
721 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
722 (LPARAM) SecureLargeIcon);
723 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
724 (LPARAM) SecureSmallIcon);
725 }
726 #endif
727
728 notify_verbose_message(pvar, "Entering secure mode",
729 LOG_LEVEL_VERBOSE);
730 }
731
732 void notify_closed_connection(PTInstVar pvar)
733 {
734 SSH_notify_disconnecting(pvar, NULL);
735 AUTH_notify_disconnecting(pvar);
736 HOSTS_notify_disconnecting(pvar);
737
738 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
739 pvar->socket, MAKELPARAM(FD_CLOSE, 0));
740
741 }
742
743 static void add_err_msg(PTInstVar pvar, char FAR * msg)
744 {
745 if (pvar->err_msg != NULL) {
746 int buf_len = strlen(pvar->err_msg) + 3 + strlen(msg);
747 char FAR *buf = (char FAR *) malloc(buf_len);
748
749 strncpy_s(buf, buf_len, pvar->err_msg, _TRUNCATE);
750 strncat_s(buf, buf_len, "\n\n", _TRUNCATE);
751 strncat_s(buf, buf_len, msg, _TRUNCATE);
752 free(pvar->err_msg);
753 pvar->err_msg = buf;
754 } else {
755 pvar->err_msg = _strdup(msg);
756 }
757 }
758
759 void notify_nonfatal_error(PTInstVar pvar, char FAR * msg)
760 {
761 if (!pvar->showing_err) {
762 // �������������������m���E�B���h�E�����������A�f�X�N�g�b�v���I�[�i�[������
763 // ���b�Z�[�W�{�b�N�X���o���������B(2006.6.11 yutaka)
764 if (pvar->NotificationWindow == NULL) {
765 #ifndef NO_I18N
766 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Tera Term: not fatal error", _TRUNCATE);
767 UTIL_get_lang_msg("MSG_ERROR_NONFAITAL", pvar);
768 MessageBox(NULL, msg, pvar->ts->UIMsg, MB_OK|MB_ICONINFORMATION);
769 #else
770 MessageBox(NULL, msg, "Tera Term: not fatal error", MB_OK|MB_ICONINFORMATION);
771 #endif
772 msg[0] = '\0';
773
774 } else {
775 PostMessage(pvar->NotificationWindow, WM_COMMAND,
776 ID_SSHASYNCMESSAGEBOX, 0);
777 }
778 }
779 if (msg[0] != 0) {
780 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
781 add_err_msg(pvar, msg);
782 }
783 }
784
785 void notify_fatal_error(PTInstVar pvar, char FAR * msg)
786 {
787 if (msg[0] != 0) {
788 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
789 add_err_msg(pvar, msg);
790 }
791
792 if (!pvar->fatal_error) {
793 pvar->fatal_error = TRUE;
794
795 SSH_notify_disconnecting(pvar, msg);
796 AUTH_notify_disconnecting(pvar);
797 HOSTS_notify_disconnecting(pvar);
798
799 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
800 pvar->socket, MAKELPARAM(FD_CLOSE,
801 (pvar->PWSAGetLastError) ()));
802 }
803 }
804
805 void notify_verbose_message(PTInstVar pvar, char FAR * msg, int level)
806 {
807 if (level <= pvar->session_settings.LogLevel) {
808 char buf[1024];
809 int file;
810
811 get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
812 file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
813 _S_IREAD | _S_IWRITE);
814
815 if (file >= 0) {
816 _write(file, msg, strlen(msg));
817 _write(file, "\n", 1);
818 _close(file);
819 }
820 }
821 }
822
823 static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks)
824 {
825 GET_VAR();
826
827 if (pvar->settings.Enabled) {
828 char buf[1024] = "\n---------------------------------------------------------------------\nInitiating SSH session at ";
829 struct tm FAR *newtime;
830 time_t long_time;
831
832 // TCPLocalEcho/TCPCRSend ������������ (maya 2007.4.25)
833 pvar->ts->DisableTCPEchoCR = TRUE;
834
835 pvar->session_settings = pvar->settings;
836
837 time(&long_time);
838 newtime = localtime(&long_time);
839 strncat_s(buf, sizeof(buf), asctime(newtime), _TRUNCATE);
840 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
841
842 FWDUI_load_settings(pvar);
843
844 pvar->cv->TelAutoDetect = FALSE;
845 /* This next line should not be needed because Teraterm's
846 CommLib should find ts->Telnet == 0 ... but we'll do this
847 just to be on the safe side. */
848 pvar->cv->TelFlag = FALSE;
849
850 pvar->Precv = *hooks->Precv;
851 pvar->Psend = *hooks->Psend;
852 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
853 pvar->Pconnect = *hooks->Pconnect;
854 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
855
856 *hooks->Precv = TTXrecv;
857 *hooks->Psend = TTXsend;
858 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
859 *hooks->Pconnect = TTXconnect;
860
861 SSH_open(pvar);
862 HOSTS_open(pvar);
863 FWDUI_open(pvar);
864
865 // ������ myproposal �����f���������A�������O�����������B (2006.6.26 maya)
866 SSH2_update_cipher_myproposal(pvar);
867 SSH2_update_compression_myproposal(pvar);
868 }
869 }
870
871 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
872 {
873 GET_VAR();
874
875 if (pvar->session_settings.Enabled) {
876 pvar->socket = INVALID_SOCKET;
877
878 notify_verbose_message(pvar, "Terminating SSH session...",
879 LOG_LEVEL_VERBOSE);
880
881 *hooks->Precv = pvar->Precv;
882 *hooks->Psend = pvar->Psend;
883 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
884 *hooks->Pconnect = pvar->Pconnect;
885 }
886
887 uninit_TTSSH(pvar);
888 init_TTSSH(pvar);
889 }
890
891 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
892 {
893 for (; from <= to; from++) {
894 EnableWindow(GetDlgItem(dlg, from), enabled);
895 }
896 }
897
898 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
899 LPARAM lParam)
900 {
901 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
902 PGetHNRec GetHNRec;
903 char EntName[8];
904 char TempHost[HostNameMaxLength + 1];
905 WORD i, j, w;
906 char ComPortTable[MAXCOMPORT];
907 int comports;
908 BOOL Ok;
909 #ifndef NO_I18N
910 LOGFONT logfont;
911 HFONT font;
912 #endif
913
914 GET_VAR();
915
916 switch (msg) {
917 case WM_INITDIALOG:
918 GetHNRec = (PGetHNRec) lParam;
919 SetWindowLong(dlg, DWL_USER, lParam);
920
921 #ifndef NO_I18N
922 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
923 UTIL_get_lang_msg("DLG_HOST_TITLE", pvar);
924 SetWindowText(dlg, pvar->ts->UIMsg);
925
926 GetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
927 UTIL_get_lang_msg("DLG_HOST_TCPIP_HOST", pvar);
928 SetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg);
929
930 GetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
931 UTIL_get_lang_msg("DLG_HOST_TCPIP_HISTORY", pvar);
932 SetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg);
933
934 GetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
935 UTIL_get_lang_msg("DLG_HOST_TCPIP_SERVICE", pvar);
936 SetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg);
937
938 GetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
939 UTIL_get_lang_msg("DLG_HOST_TCPIP_OTHER", pvar);
940 SetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg);
941
942 GetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
943 UTIL_get_lang_msg("DLG_HOST_TCPIP_PORT", pvar);
944 SetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg);
945
946 GetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
947 UTIL_get_lang_msg("DLG_HOST_TCPIP_SSHVERSION", pvar);
948 SetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg);
949
950 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
951 UTIL_get_lang_msg("DLG_HOST_TCPIP_PROTOCOL", pvar);
952 SetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg);
953
954 GetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
955 UTIL_get_lang_msg("DLG_HOST_SERIAL", pvar);
956 SetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg);
957
958 GetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
959 UTIL_get_lang_msg("DLG_HOST_SERIAL_PORT", pvar);
960 SetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg);
961
962 GetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
963 UTIL_get_lang_msg("DLG_HOST_HELP", pvar);
964 SetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg);
965
966 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
967 UTIL_get_lang_msg("BTN_OK", pvar);
968 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
969
970 GetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
971 UTIL_get_lang_msg("BTN_CANCEL", pvar);
972 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
973 #endif
974
975 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
976 if (pvar->ts->HistoryList > 0) {
977 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
978 } else {
979 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
980 }
981
982 if (GetHNRec->PortType == IdFile)
983 GetHNRec->PortType = IdTCPIP;
984
985 strncpy_s(EntName, sizeof(EntName), "Host", _TRUNCATE);
986
987 i = 1;
988 do {
989 _snprintf_s(&EntName[4], sizeof(EntName)-4, _TRUNCATE, "%d", i);
990 GetPrivateProfileString("Hosts", EntName, "",
991 TempHost, sizeof(TempHost),
992 GetHNRec->SetupFN);
993 if (strlen(TempHost) > 0)
994 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
995 0, (LPARAM) TempHost);
996 i++;
997 } while ((i <= 99) && (strlen(TempHost) > 0));
998
999 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
1000 HostNameMaxLength - 1, 0);
1001
1002 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
1003
1004 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1005 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1006 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1007 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1008 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1009 #ifndef NO_INET6
1010 for (i = 0; ProtocolFamilyList[i]; ++i) {
1011 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1012 0, (LPARAM) ProtocolFamilyList[i]);
1013 }
1014 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1015 ProtocolFamilyMaxLength - 1, 0);
1016 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1017 #endif /* NO_INET6 */
1018
1019 /////// SSH version
1020 for (i = 0; ssh_version[i]; ++i) {
1021 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1022 0, (LPARAM) ssh_version[i]);
1023 }
1024 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1025 NUM_ELEM(ssh_version) - 1, 0);
1026
1027 if (pvar->settings.ssh_protocol_version == 1) {
1028 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1029 } else {
1030 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1031 }
1032
1033 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1034 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1035 } else {
1036 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1037 }
1038 /////// SSH version
1039
1040
1041 j = 0;
1042 w = 1;
1043 strncpy_s(EntName, sizeof(EntName), "COM", _TRUNCATE);
1044 if ((comports=DetectComPorts(ComPortTable, GetHNRec->MaxComPort)) >= 0) {
1045 for (i=0; i<comports; i++) {
1046 _snprintf_s(&EntName[3], sizeof(EntName)-3, _TRUNCATE, "%d", ComPortTable[i]);
1047 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1048 0, (LPARAM)EntName);
1049 j++;
1050 if (GetHNRec->ComPort == ComPortTable[i])
1051 w = j;
1052 }
1053
1054 } else {
1055 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1056 _snprintf_s(&EntName[3], sizeof(EntName)-3, _TRUNCATE, "%d", i);
1057 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1058 0, (LPARAM) EntName);
1059 j++;
1060 if (GetHNRec->ComPort == i)
1061 w = j;
1062 }
1063 }
1064
1065 if (j > 0)
1066 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1067 else { /* All com ports are already used */
1068 GetHNRec->PortType = IdTCPIP;
1069 enable_dlg_items(dlg, IDC_HOSTSERIAL, IDC_HOSTSERIAL, FALSE);
1070 }
1071
1072 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
1073 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
1074
1075 if (GetHNRec->PortType == IdTCPIP) {
1076 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1077
1078 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1079 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1080 }
1081 #ifndef NO_INET6
1082 else {
1083 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1084 FALSE);
1085 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1086 IDC_HOSTTCPPROTOCOL, FALSE);
1087
1088 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1089 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1090 }
1091 #else
1092 else
1093 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1094 FALSE);
1095 #endif /* NO_INET6 */
1096
1097 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1098 if (GetHNRec->PortType == IdTCPIP) {
1099 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1100 SetFocus(hwnd);
1101 } else {
1102 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1103 SetFocus(hwnd);
1104 }
1105
1106 #ifndef NO_I18N
1107 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1108 GetObject(font, sizeof(LOGFONT), &logfont);
1109 if (UTIL_get_lang_font("DLG_SYSTEM_FONT", dlg, &logfont, &DlgHostFont, pvar)) {
1110 SendDlgItemMessage(dlg, IDC_HOSTTCPIP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1111 SendDlgItemMessage(dlg, IDC_HOSTNAMELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1112 SendDlgItemMessage(dlg, IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1113 SendDlgItemMessage(dlg, IDC_HISTORY, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1114 SendDlgItemMessage(dlg, IDC_SERVICELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1115 SendDlgItemMessage(dlg, IDC_HOSTTELNET, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1116 SendDlgItemMessage(dlg, IDC_HOSTSSH, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1117 SendDlgItemMessage(dlg, IDC_HOSTOTHER, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1118 SendDlgItemMessage(dlg, IDC_HOSTTCPPORTLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1119 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1120 SendDlgItemMessage(dlg, IDC_SSH_VERSION_LABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1121 SendDlgItemMessage(dlg, IDC_SSH_VERSION, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1122 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOLLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1123 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1124 SendDlgItemMessage(dlg, IDC_HOSTSERIAL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1125 SendDlgItemMessage(dlg, IDC_HOSTCOMLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1126 SendDlgItemMessage(dlg, IDC_HOSTCOM, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1127 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1128 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1129 SendDlgItemMessage(dlg, IDC_HOSTHELP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1130 }
1131 else {
1132 DlgHostFont = NULL;
1133 }
1134 #endif
1135
1136 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1137 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1138 // (2004.11.23 yutaka)
1139 return FALSE;
1140 //return TRUE;
1141
1142 case WM_COMMAND:
1143 switch (LOWORD(wParam)) {
1144 case IDOK:
1145 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1146 if (GetHNRec != NULL) {
1147 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1148 #ifndef NO_INET6
1149 char afstr[BUFSIZ];
1150 #endif /* NO_INET6 */
1151 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1152 if (Ok) {
1153 GetHNRec->TCPPort = i;
1154 } else {
1155 #ifndef NO_I18N
1156 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "The TCP port must be a number.", _TRUNCATE);
1157 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar);
1158 MessageBox(dlg, pvar->ts->UIMsg,
1159 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1160 #else
1161 MessageBox(dlg, "The TCP port must be a number.",
1162 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1163 #endif
1164 return TRUE;
1165 }
1166 #ifndef NO_INET6
1167 #define getaf(str) \
1168 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1169 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1170 memset(afstr, 0, sizeof(afstr));
1171 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1172 sizeof(afstr));
1173 GetHNRec->ProtocolFamily = getaf(afstr);
1174 #endif /* NO_INET6 */
1175 GetHNRec->PortType = IdTCPIP;
1176 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1177 HostNameMaxLength);
1178 GetHNRec->Telnet = FALSE;
1179 pvar->hostdlg_activated = TRUE;
1180 pvar->hostdlg_Enabled = FALSE;
1181 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1182 GetHNRec->Telnet = TRUE;
1183 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1184 pvar->hostdlg_Enabled = TRUE;
1185
1186 // check SSH protocol version
1187 memset(afstr, 0, sizeof(afstr));
1188 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1189 if (_stricmp(afstr, "SSH1") == 0) {
1190 pvar->settings.ssh_protocol_version = 1;
1191 } else {
1192 pvar->settings.ssh_protocol_version = 2;
1193 }
1194 }
1195
1196 // host history check button
1197 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1198 pvar->ts->HistoryList = 1;
1199 } else {
1200 pvar->ts->HistoryList = 0;
1201 }
1202
1203 } else {
1204 GetHNRec->PortType = IdSerial;
1205 GetHNRec->HostName[0] = 0;
1206 memset(EntName, 0, sizeof(EntName));
1207 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1208 sizeof(EntName) - 1);
1209 if (strncmp(EntName, "COM", 3) == 0 && EntName[3] != '\0') {
1210 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1211 if (strlen(EntName) > 4)
1212 GetHNRec->ComPort =
1213 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1214 0x30;
1215 if (GetHNRec->ComPort > GetHNRec->MaxComPort)
1216 GetHNRec->ComPort = 1;
1217 } else {
1218 GetHNRec->ComPort = 1;
1219 }
1220 }
1221 }
1222 EndDialog(dlg, 1);
1223
1224 #ifndef NO_I18N
1225 if (DlgHostFont != NULL) {
1226 DeleteObject(DlgHostFont);
1227 }
1228 #endif
1229
1230 return TRUE;
1231
1232 case IDCANCEL:
1233 EndDialog(dlg, 0);
1234
1235 #ifndef NO_I18N
1236 if (DlgHostFont != NULL) {
1237 DeleteObject(DlgHostFont);
1238 }
1239 #endif
1240
1241 return TRUE;
1242
1243 case IDC_HOSTTCPIP:
1244 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1245 TRUE);
1246 #ifndef NO_INET6
1247 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1248 IDC_HOSTTCPPROTOCOL, TRUE);
1249 #endif /* NO_INET6 */
1250 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1251
1252 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1253 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1254 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1255 } else {
1256 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1257 }
1258
1259 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1260
1261 return TRUE;
1262
1263 case IDC_HOSTSERIAL:
1264 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1265 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1266 FALSE);
1267 #ifndef NO_INET6
1268 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1269 IDC_HOSTTCPPROTOCOL, FALSE);
1270 #endif /* NO_INET6 */
1271 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1272 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1273
1274 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1275
1276 return TRUE;
1277
1278 case IDC_HOSTSSH:
1279 enable_dlg_items(dlg, IDC_SSH_VERSION,
1280 IDC_SSH_VERSION, TRUE);
1281 goto hostssh_enabled;
1282
1283 case IDC_HOSTTELNET:
1284 case IDC_HOSTOTHER:
1285 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1286 hostssh_enabled:
1287
1288 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1289
1290 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1291 if (GetHNRec != NULL)
1292 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1293 FALSE);
1294 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1295 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1296 }
1297 return TRUE;
1298
1299 case IDC_HOSTHELP:
1300 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1301 }
1302 }
1303 return FALSE;
1304 }
1305
1306 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1307 {
1308 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1309 parent, TTXHostDlg, (LONG) rec);
1310 }
1311
1312 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1313 {
1314 GET_VAR();
1315
1316 *hooks->GetHostName = TTXGetHostName;
1317 }
1318
1319 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1320 {
1321 GET_VAR();
1322
1323 (pvar->ReadIniFile) (fileName, ts);
1324 read_ssh_options(pvar, fileName);
1325 pvar->settings = *pvar->ts_SSH;
1326 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1327 FWDUI_load_settings(pvar);
1328 }
1329
1330 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1331 {
1332 GET_VAR();
1333
1334 (pvar->WriteIniFile) (fileName, ts);
1335 *pvar->ts_SSH = pvar->settings;
1336 clear_local_settings(pvar);
1337 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1338 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1339 }
1340
1341 static void read_ssh_options_from_user_file(PTInstVar pvar,
1342 char FAR * user_file_name)
1343 {
1344 if (user_file_name[0] == '.') {
1345 read_ssh_options(pvar, user_file_name);
1346 } else {
1347 char buf[1024];
1348
1349 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1350 read_ssh_options(pvar, buf);
1351 }
1352
1353 pvar->settings = *pvar->ts_SSH;
1354 FWDUI_load_settings(pvar);
1355 }
1356
1357
1358 // @���u�����N���u�������B (2005.1.26 yutaka)
1359 static void replace_to_blank(char *src, char *dst, int dst_len)
1360 {
1361 int len, i;
1362
1363 len = strlen(src);
1364 if (dst_len < len) // buffer overflow check
1365 return;
1366
1367 for (i = 0 ; i < len ; i++) {
1368 if (src[i] == '@') { // @ ���o��������
1369 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1370 *dst++ = '@';
1371 i++;
1372 } else {
1373 *dst++ = ' '; // �������u��������
1374 }
1375 } else {
1376 *dst++ = src[i];
1377 }
1378 }
1379 *dst = '\0';
1380 }
1381
1382 /* returns 1 if the option text must be deleted */
1383 static int parse_option(PTInstVar pvar, char FAR * option)
1384 {
1385 if ((option[0] == '-' || option[0] == '/')) {
1386 if (MATCH_STR(option + 1, "ssh") == 0) {
1387 if (option[4] == 0) {
1388 pvar->settings.Enabled = 1;
1389 } else if (MATCH_STR(option + 4, "-L") == 0
1390 || MATCH_STR(option + 4, "-R") == 0
1391 || _stricmp(option + 4, "-X") == 0) {
1392 if (pvar->settings.DefaultForwarding[0] == 0) {
1393 strncpy_s(pvar->settings.DefaultForwarding,
1394 sizeof(pvar->settings.DefaultForwarding),
1395 option + 5, _TRUNCATE);
1396 } else {
1397 strncat_s(pvar->settings.DefaultForwarding,
1398 sizeof(pvar->settings.DefaultForwarding),
1399 ";", _TRUNCATE);
1400 strncat_s(pvar->settings.DefaultForwarding,
1401 sizeof(pvar->settings.DefaultForwarding),
1402 option + 5, _TRUNCATE);
1403 }
1404 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1405 read_ssh_options_from_user_file(pvar, option + 7);
1406 } else if (MATCH_STR(option + 4, "-v") == 0) {
1407 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1408 } else if (_stricmp(option + 4, "-autologin") == 0
1409 || _stricmp(option + 4, "-autologon") == 0) {
1410 pvar->settings.TryDefaultAuth = TRUE;
1411
1412 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1413 read_ssh_options_from_user_file(pvar, option + 13);
1414 DeleteFile(option + 13);
1415
1416 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1417 } else if (MATCH_STR(option + 4, "1") == 0) {
1418 pvar->settings.ssh_protocol_version = 1;
1419 } else if (MATCH_STR(option + 4, "2") == 0) {
1420 pvar->settings.ssh_protocol_version = 2;
1421
1422 } else {
1423 char buf[1024];
1424
1425 #ifndef NO_I18N
1426 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Unrecognized command-line option: %s", _TRUNCATE);
1427 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar);
1428 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, option);
1429 #else
1430 _snprintf(buf, sizeof(buf),
1431 "Unrecognized command-line option: %s", option);
1432 #endif
1433 buf[sizeof(buf) - 1] = 0;
1434
1435 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1436 }
1437
1438 return 1;
1439
1440 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1441 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1442 if (strcmp(option + 3, "2") == 0) {
1443 pvar->settings.Enabled = 1;
1444 return 1;
1445 } else {
1446 pvar->settings.Enabled = 0;
1447 }
1448
1449 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1450 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1451 read_ssh_options_from_user_file(pvar, option + 3);
1452
1453 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1454 } else if (MATCH_STR(option + 1, "1") == 0) {
1455 // command line: /ssh /1 is SSH1 only
1456 pvar->settings.ssh_protocol_version = 1;
1457
1458 } else if (MATCH_STR(option + 1, "2") == 0) {
1459 // command line: /ssh /2 is SSH2 & SSH1
1460 pvar->settings.ssh_protocol_version = 2;
1461
1462 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1463 // '/nossh' �I�v�V�����������B
1464 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1465 // �����������������B(2004.10.11 yutaka)
1466 pvar->settings.Enabled = 0;
1467
1468 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1469 // '/telnet' ���w�������������������� '/nossh' ��������
1470 // SSH������������ (2006.9.16 maya)
1471 pvar->settings.Enabled = 0;
1472
1473 } else if (MATCH_STR(option + 1, "auth") == 0) {
1474 // SSH2�������O�C���I�v�V����������
1475 //
1476 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1477 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1478 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1479 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1480 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1481 //
1482 // (2004.11.30 yutaka)
1483 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1484 //
1485 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1486
1487 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h/keyboard-interactive�F��
1488 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1489 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1490
1491 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1492 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1493 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1494
1495 } else {
1496 // TODO:
1497
1498 }
1499
1500 } else if (MATCH_STR(option + 1, "user=") == 0) {
1501 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1502 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1503
1504 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1505 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1506 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1507
1508 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1509 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1510
1511 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1512 // �p�X���[�h������ (2006.9.18 maya)
1513 pvar->ask4passwd = 1;
1514
1515 }
1516
1517 // �p�X���[�h�������������������O�C��������������
1518 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1519 if (pvar->ask4passwd == 1) {
1520 pvar->ssh2_autologin = 0;
1521 }
1522
1523 }
1524
1525 return 0;
1526 }
1527
1528 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1529 PCHAR DDETopic)
1530 {
1531 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1532 int i;
1533 BOOL inParam = FALSE;
1534 BOOL inQuotes = FALSE;
1535 BOOL inFileParam = FALSE;
1536 PCHAR option = NULL;
1537 GET_VAR();
1538
1539 if (pvar->hostdlg_activated) {
1540 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1541 }
1542
1543 for (i = 0; param[i] != 0; i++) {
1544 if (inQuotes ? param[i] == '"'
1545 : (param[i] == ' ' || param[i] == '\t')) {
1546 if (option != NULL) {
1547 char ch = param[i];
1548 PCHAR Equal;
1549
1550 param[i] = 0;
1551 Equal = strchr(option, '=');
1552 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1553 int buf_len = strlen(option) * sizeof(char);
1554 char *buf = (char *)calloc(strlen(option), sizeof(char));
1555 char c = option[Equal - option + 1];
1556 option[Equal - option + 1] = 0;
1557 strncat_s(buf, buf_len, option, _TRUNCATE);
1558 option[Equal - option + 1] = c;
1559 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1560 if (parse_option
1561 (pvar, *buf == '"' ? buf + 1 : buf)) {
1562 memset(option, ' ', i + 1 - (option - param));
1563 } else {
1564 param[i] = ch;
1565 }
1566 free(buf);
1567 }
1568 else {
1569 if (parse_option
1570 (pvar, *option == '"' ? option + 1 : option)) {
1571 memset(option, ' ', i + 1 - (option - param));
1572 } else {
1573 param[i] = ch;
1574 }
1575 }
1576 option = NULL;
1577 }
1578 inParam = FALSE;
1579 inQuotes = FALSE;
1580 inFileParam = FALSE;
1581 } else if (!inParam) {
1582 if (param[i] == '"') {
1583 inQuotes = TRUE;
1584 inParam = TRUE;
1585 option = param + i;
1586 } else if (param[i] != ' ' && param[i] != '\t') {
1587 inParam = TRUE;
1588 option = param + i;
1589 }
1590 } else {
1591 if (option == NULL) {
1592 continue;
1593 }
1594 if ((option[0] == '-' || option[0] == '/') &&
1595 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1596 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1597 MATCH_STR_I(option + 1, "f=") == 0 ||
1598 MATCH_STR(option + 1, "keyfile=") == 0)) {
1599 if (param[i] == '"') {
1600 inQuotes = TRUE;
1601 }
1602 inFileParam = TRUE;
1603 }
1604 }
1605 }
1606
1607 if (option != NULL) {
1608 PCHAR Equal = strchr(option, '=');
1609 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1610 int buf_len = strlen(option) * sizeof(char);
1611 char *buf = (char *)calloc(strlen(option), sizeof(char));
1612 char c = option[Equal - option + 1];
1613 option[Equal - option + 1] = 0;
1614 strncat_s(buf, buf_len, option, _TRUNCATE);
1615 option[Equal - option + 1] = c;
1616 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1617 if (parse_option
1618 (pvar, *buf == '"' ? buf + 1 : buf)) {
1619 memset(option, ' ', i + 1 - (option - param));
1620 }
1621 free(buf);
1622 }
1623 else {
1624 if (parse_option(pvar, option)) {
1625 memset(option, ' ', i - (option - param));
1626 }
1627 }
1628 }
1629
1630 FWDUI_load_settings(pvar);
1631
1632 (pvar->ParseParam) (param, ts, DDETopic);
1633
1634 }
1635
1636 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1637 {
1638 GET_VAR();
1639
1640 pvar->ReadIniFile = *hooks->ReadIniFile;
1641 pvar->WriteIniFile = *hooks->WriteIniFile;
1642 pvar->ParseParam = *hooks->ParseParam;
1643
1644 *hooks->ReadIniFile = TTXReadINIFile;
1645 *hooks->WriteIniFile = TTXWriteINIFile;
1646 *hooks->ParseParam = TTXParseParam;
1647 }
1648
1649 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1650 {
1651 GET_VAR();
1652
1653 SSH_notify_win_size(pvar, cols, rows);
1654 }
1655
1656 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1657 WORD newItemID, char FAR * text)
1658 {
1659 int i, j;
1660
1661 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1662 HMENU submenu = GetSubMenu(menu, i);
1663
1664 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1665 if (GetMenuItemID(submenu, j) == beforeItemID) {
1666 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1667 text);
1668 return;
1669 }
1670 }
1671 }
1672 }
1673
1674 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1675 {
1676 GET_VAR();
1677
1678 /* inserts before ID_HELP_ABOUT */
1679 #ifndef NO_I18N
1680 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "About &TTSSH...", _TRUNCATE);
1681 UTIL_get_lang_msg("MENU_ABOUT", pvar);
1682 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1683 #else
1684 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1685 "About &TTSSH...");
1686 #endif
1687
1688 /* inserts before ID_SETUP_TCPIP */
1689 #ifndef NO_I18N
1690 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "SS&H...", _TRUNCATE);
1691 UTIL_get_lang_msg("MENU_SSH", pvar);
1692 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1693 #else
1694 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1695 "SS&H...");
1696 #endif
1697 /* inserts before ID_SETUP_TCPIP */
1698 #ifndef NO_I18N
1699 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "SSH &Authentication...", _TRUNCATE);
1700 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar);
1701 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1702 #else
1703 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1704 "SSH &Authentication...");
1705 #endif
1706 /* inserts before ID_SETUP_TCPIP */
1707 #ifndef NO_I18N
1708 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "SSH F&orwarding...", _TRUNCATE);
1709 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar);
1710 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1711 #else
1712 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1713 "SSH F&orwarding...");
1714 #endif
1715
1716 #ifndef NO_I18N
1717 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "SSH KeyGe&nerator...", _TRUNCATE);
1718 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar);
1719 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1720 #else
1721 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU,
1722 "SSH KeyGenerator...");
1723 #endif
1724 }
1725
1726 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1727 {
1728 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1729 (LPARAM) prefix);
1730 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1731 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1732 (LPARAM) (char FAR *) "\r\n");
1733 }
1734
1735 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1736 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1737 {
1738 typedef struct {
1739 WORD wLanguage;
1740 WORD wCodePage;
1741 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1742 LPLANGANDCODEPAGE lplgcode;
1743 UINT unLen;
1744 DWORD size;
1745 char *buf = NULL;
1746 BOOL ret;
1747 int i;
1748 char fmt[80];
1749 char *pbuf;
1750
1751 size = GetFileVersionInfoSize(exefile, NULL);
1752 if (size == 0) {
1753 goto error;
1754 }
1755 buf = malloc(size);
1756 ZeroMemory(buf, size);
1757
1758 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1759 goto error;
1760 }
1761
1762 ret = VerQueryValue(buf,
1763 "\\VarFileInfo\\Translation",
1764 (LPVOID *)&lplgcode, &unLen);
1765 if (ret == FALSE)
1766 goto error;
1767
1768 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1769 _snprintf_s(fmt, sizeof(fmt), _TRUNCATE,
1770 "\\StringFileInfo\\%04x%04x\\FileVersion",
1771 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1772 VerQueryValue(buf, fmt, &pbuf, &unLen);
1773 if (unLen > 0) { // get success
1774 int n, a, b, c, d;
1775
1776 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1777 if (n == 4) { // convert success
1778 *major = a;
1779 *minor = b;
1780 *release = c;
1781 *build = d;
1782 break;
1783 }
1784 }
1785 }
1786
1787 free(buf);
1788 return;
1789
1790 error:
1791 free(buf);
1792 *major = *minor = *release = *build = 0;
1793 }
1794
1795 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1796 {
1797 char buf[1024];
1798 int a, b, c, d;
1799
1800 #ifndef NO_I18N
1801 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1802 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar);
1803 SetWindowText(dlg, pvar->ts->UIMsg);
1804
1805 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1806 UTIL_get_lang_msg("BTN_OK", pvar);
1807 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1808 #endif
1809
1810 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1811 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1812 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1813 "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1814 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1815
1816 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1817 // ���������� (2005.5.11 yutaka)
1818 #ifdef OPENSSL_VERSION_TEXT
1819 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1820 #else
1821 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1822 #endif
1823
1824 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1825 #ifdef ZLIB_VERSION
1826 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
1827 #else
1828 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1829 #endif
1830 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1831
1832
1833 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1834 if (pvar->socket != INVALID_SOCKET) {
1835 if (SSHv1(pvar)) {
1836 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1837 #ifndef NO_I18N
1838 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Server ID: ", _TRUNCATE);
1839 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar);
1840 append_about_text(dlg, pvar->ts->UIMsg, buf);
1841 #else
1842 append_about_text(dlg, "Server ID: ", buf);
1843 #endif
1844 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1845 #ifndef NO_I18N
1846 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Using protocol: ", _TRUNCATE);
1847 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar);
1848 append_about_text(dlg, pvar->ts->UIMsg, buf);
1849 #else
1850 append_about_text(dlg, "Using protocol: ", buf);
1851 #endif
1852 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1853 #ifndef NO_I18N
1854 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Encryption: ", _TRUNCATE);
1855 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar);
1856 append_about_text(dlg, pvar->ts->UIMsg, buf);
1857 #else
1858 append_about_text(dlg, "Encryption: ", buf);
1859 #endif
1860 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1861 #ifndef NO_I18N
1862 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Server keys: ", _TRUNCATE);
1863 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar);
1864 append_about_text(dlg, pvar->ts->UIMsg, buf);
1865 #else
1866 append_about_text(dlg, "Server keys: ", buf);
1867 #endif
1868 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1869 #ifndef NO_I18N
1870 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Authentication: ", _TRUNCATE);
1871 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar);
1872 append_about_text(dlg, pvar->ts->UIMsg, buf);
1873 #else
1874 append_about_text(dlg, "Authentication: ", buf);
1875 #endif
1876 SSH_get_compression_info(pvar, buf, sizeof(buf));
1877 #ifndef NO_I18N
1878 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Compression: ", _TRUNCATE);
1879 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar);
1880 append_about_text(dlg, pvar->ts->UIMsg, buf);
1881 #else
1882 append_about_text(dlg, "Compression: ", buf);
1883 #endif
1884
1885 } else { // SSH2
1886 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1887 #ifndef NO_I18N
1888 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Server ID: ", _TRUNCATE);
1889 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar);
1890 append_about_text(dlg, pvar->ts->UIMsg, buf);
1891 #else
1892 append_about_text(dlg, "Server ID: ", buf);
1893 #endif
1894
1895 #ifndef NO_I18N
1896 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Client ID: ", _TRUNCATE);
1897 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar);
1898 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1899 #else
1900 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1901 #endif
1902
1903 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1904 #ifndef NO_I18N
1905 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Using protocol: ", _TRUNCATE);
1906 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar);
1907 append_about_text(dlg, pvar->ts->UIMsg, buf);
1908 #else
1909 append_about_text(dlg, "Using protocol: ", buf);
1910 #endif
1911
1912 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1913 strncpy_s(buf, sizeof(buf), KEX_DH1, _TRUNCATE);
1914 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1915 strncpy_s(buf, sizeof(buf), KEX_DH14, _TRUNCATE);
1916 } else {
1917 strncpy_s(buf, sizeof(buf), KEX_DHGEX, _TRUNCATE);
1918 }
1919 append_about_text(dlg, "KEX: ", buf);
1920
1921 if (pvar->hostkey_type == KEY_DSA) {
1922 strncpy_s(buf, sizeof(buf), "ssh-dss", _TRUNCATE);
1923 } else {
1924 strncpy_s(buf, sizeof(buf), "ssh-rsa", _TRUNCATE);
1925 }
1926 #ifndef NO_I18N
1927 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Host Key: ", _TRUNCATE);
1928 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar);
1929 append_about_text(dlg, pvar->ts->UIMsg, buf);
1930 #else
1931 append_about_text(dlg, "Host Key: ", buf);
1932 #endif
1933
1934 // add HMAC algorithm (2004.12.17 yutaka)
1935 buf[0] = '\0';
1936 if (pvar->ctos_hmac == HMAC_SHA1) {
1937 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1938 } else if (pvar->ctos_hmac == HMAC_MD5) {
1939 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1940 }
1941 #ifndef NO_I18N
1942 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), " to server, ", _TRUNCATE);
1943 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar);
1944 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1945 #else
1946 strcat(buf, " to server, ");
1947 #endif
1948 if (pvar->stoc_hmac == HMAC_SHA1) {
1949 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1950 } else if (pvar->stoc_hmac == HMAC_MD5) {
1951 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1952 }
1953 #ifndef NO_I18N
1954 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), " from server", _TRUNCATE);
1955 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar);
1956 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1957 #else
1958 strcat(buf, " from server");
1959 #endif
1960 append_about_text(dlg, "HMAC: ", buf);
1961
1962 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1963 #ifndef NO_I18N
1964 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Encryption: ", _TRUNCATE);
1965 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar);
1966 append_about_text(dlg, pvar->ts->UIMsg, buf);
1967 #else
1968 append_about_text(dlg, "Encryption: ", buf);
1969 #endif
1970 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1971 #ifndef NO_I18N
1972 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Server keys: ", _TRUNCATE);
1973 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar);
1974 append_about_text(dlg, pvar->ts->UIMsg, buf);
1975 #else
1976 append_about_text(dlg, "Server keys: ", buf);
1977 #endif
1978 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1979 #ifndef NO_I18N
1980 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Authentication: ", _TRUNCATE);
1981 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar);
1982 append_about_text(dlg, pvar->ts->UIMsg, buf);
1983 #else
1984 append_about_text(dlg, "Authentication: ", buf);
1985 #endif
1986
1987 SSH_get_compression_info(pvar, buf, sizeof(buf));
1988 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1989 #ifndef NO_I18N
1990 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Delayed Compression: ", _TRUNCATE);
1991 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar);
1992 append_about_text(dlg, pvar->ts->UIMsg, buf);
1993 #else
1994 append_about_text(dlg, "Delayed Compression: ", buf);
1995 #endif
1996 } else {
1997 #ifndef NO_I18N
1998 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Compression: ", _TRUNCATE);
1999 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar);
2000 append_about_text(dlg, pvar->ts->UIMsg, buf);
2001 #else
2002 append_about_text(dlg, "Compression: ", buf);
2003 #endif
2004 }
2005
2006 }
2007 }
2008 }
2009
2010 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
2011 LPARAM lParam)
2012 {
2013 #ifndef NO_I18N
2014 LOGFONT logfont;
2015 HFONT font;
2016 #endif
2017 switch (msg) {
2018 case WM_INITDIALOG:
2019 #ifndef NO_I18N
2020 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2021 GetObject(font, sizeof(LOGFONT), &logfont);
2022 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
2023 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2024 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2025 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2026 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2027 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2028 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2029 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2030 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2031 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2032 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2033 }
2034 else {
2035 DlgAboutFont = NULL;
2036 }
2037 #endif
2038 init_about_dlg((PTInstVar) lParam, dlg);
2039 return TRUE;
2040 case WM_COMMAND:
2041 switch (LOWORD(wParam)) {
2042 case IDOK:
2043 EndDialog(dlg, 1);
2044 #ifndef NO_I18N
2045 if (DlgAboutFont != NULL) {
2046 DeleteObject(DlgAboutFont);
2047 }
2048 #endif
2049 return TRUE;
2050 case IDCANCEL: /* there isn't a cancel button, but other Windows
2051 UI things can send this message */
2052 EndDialog(dlg, 0);
2053 #ifndef NO_I18N
2054 if (DlgAboutFont != NULL) {
2055 DeleteObject(DlgAboutFont);
2056 }
2057 #endif
2058 return TRUE;
2059 }
2060 break;
2061 }
2062
2063 return FALSE;
2064 }
2065
2066 static char FAR *get_cipher_name(int cipher)
2067 {
2068 switch (cipher) {
2069 case SSH_CIPHER_NONE:
2070 #ifndef NO_I18N
2071 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "<ciphers below this line are disabled>", _TRUNCATE);
2072 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar);
2073 return pvar->ts->UIMsg;
2074 #else
2075 return "<ciphers below this line are disabled>";
2076 #endif
2077 case SSH_CIPHER_RC4:
2078 return "RC4";
2079 case SSH_CIPHER_3DES:
2080 return "3DES";
2081 case SSH_CIPHER_DES:
2082 return "DES";
2083 case SSH_CIPHER_IDEA:
2084 return "IDEA";
2085 case SSH_CIPHER_TSS:
2086 return "TSS";
2087 case SSH_CIPHER_BLOWFISH:
2088 return "Blowfish";
2089
2090 // for SSH2(yutaka)
2091 case SSH_CIPHER_AES128:
2092 return "AES128(SSH2)";
2093 case SSH_CIPHER_3DES_CBC:
2094 return "3DES-CBC(SSH2)";
2095
2096 default:
2097 return NULL;
2098 }
2099 }
2100
2101 static void set_move_button_status(HWND dlg)
2102 {
2103 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2104 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2105 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2106
2107 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
2108 && curPos <= maxPos);
2109 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
2110 && curPos < maxPos);
2111 }
2112
2113 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2114 {
2115 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2116 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2117 int i;
2118 int ch;
2119
2120 #ifndef NO_I18N
2121 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2122 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar);
2123 SetWindowText(dlg, pvar->ts->UIMsg);
2124
2125 GetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2126 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar);
2127 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
2128
2129 GetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2130 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar);
2131 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
2132
2133 GetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2134 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar);
2135 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
2136
2137 GetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2138 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar);
2139 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
2140
2141 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2142 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar);
2143 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
2144
2145 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2146 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar);
2147 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2148
2149 GetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2150 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar);
2151 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2152
2153 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2154 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar);
2155 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2156
2157 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2158 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar);
2159 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2160
2161 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2162 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar);
2163 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2164
2165 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2166 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar);
2167 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2168
2169 GetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2170 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar);
2171 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2172
2173 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "OK", _TRUNCATE);
2174 UTIL_get_lang_msg("BTN_OK", pvar);
2175 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2176
2177 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Cancel", _TRUNCATE);
2178 UTIL_get_lang_msg("BTN_CANCEL", pvar);
2179 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2180 #endif
2181
2182 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2183 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2184 pvar->settings.CompressionLevel);
2185
2186 normalize_cipher_order(pvar->settings.CipherOrder);
2187
2188 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2189 int cipher = pvar->settings.CipherOrder[i] - '0';
2190 char FAR *name = get_cipher_name(cipher);
2191
2192 if (name != NULL) {
2193 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2194 }
2195 }
2196
2197 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2198 set_move_button_status(dlg);
2199
2200 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2201 i++) {
2202 }
2203 if (ch != 0) {
2204 pvar->settings.KnownHostsFiles[i] = 0;
2205 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2206 pvar->settings.KnownHostsFiles);
2207 pvar->settings.KnownHostsFiles[i] = ch;
2208 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2209 pvar->settings.KnownHostsFiles + i + 1);
2210 } else {
2211 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2212 pvar->settings.KnownHostsFiles);
2213 }
2214
2215 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2216 {
2217 char buf[10];
2218 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2219 "%d", pvar->settings.ssh_heartbeat_overtime);
2220 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2221 }
2222
2223 }
2224
2225 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2226 char FAR * basename)
2227 {
2228 int filename_start = 0;
2229 int i;
2230 int ch;
2231
2232 if (basename[0] == '\\' || basename[0] == '/'
2233 || (basename[0] != 0 && basename[1] == ':')) {
2234 strncpy_s(buf, bufsize, basename, _TRUNCATE);
2235 return;
2236 }
2237
2238 GetModuleFileName(NULL, buf, bufsize);
2239 for (i = 0; (ch = buf[i]) != 0; i++) {
2240 if (ch == '\\' || ch == '/' || ch == ':') {
2241 filename_start = i + 1;
2242 }
2243 }
2244
2245 if (bufsize > filename_start) {
2246 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
2247 }
2248 }
2249
2250 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2251 char FAR * basename)
2252 {
2253 char buf[1024];
2254 int filename_start = 0;
2255 int i;
2256 int ch, ch2;
2257
2258 if (basename[0] != '\\' && basename[0] != '/'
2259 && (basename[0] == 0 || basename[1] != ':')) {
2260 strncpy_s(dest, destsize, basename, _TRUNCATE);
2261 return strlen(dest);
2262 }
2263
2264 GetModuleFileName(NULL, buf, sizeof(buf));
2265 for (i = 0; (ch = buf[i]) != 0; i++) {
2266 if (ch == '\\' || ch == '/' || ch == ':') {
2267 filename_start = i + 1;
2268 }
2269 }
2270
2271 for (i = 0; i < filename_start; i++) {
2272 ch = toupper(buf[i]);
2273 ch2 = toupper(basename[i]);
2274
2275 if (ch == ch2
2276 || ((ch == '\\' || ch == '/')
2277 && (ch2 == '\\' || ch2 == '/'))) {
2278 } else {
2279 break;
2280 }
2281 }
2282
2283 if (i == filename_start) {
2284 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2285 } else {
2286 strncpy_s(dest, destsize, basename, _TRUNCATE);
2287 }
2288 return strlen(dest);
2289 }
2290
2291 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2292 {
2293 char buf[4096];
2294 char buf2[1024];
2295 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2296 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2297 int i, j, buf2index, bufindex;
2298 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2299
2300 pvar->settings.CompressionLevel =
2301 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2302
2303 buf2index = 0;
2304 for (i = 0; i < count; i++) {
2305 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2306
2307 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2308 buf[0] = 0;
2309 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2310 for (j = 0;
2311 j <= SSH_CIPHER_MAX
2312 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2313 }
2314 if (j <= SSH_CIPHER_MAX) {
2315 buf2[buf2index] = '0' + j;
2316 buf2index++;
2317 }
2318 }
2319 }
2320 buf2[buf2index] = 0;
2321 normalize_cipher_order(buf2);
2322 strncpy_s(pvar->settings.CipherOrder, sizeof(pvar->settings.CipherOrder), buf2, _TRUNCATE);
2323
2324 buf[0] = 0;
2325 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2326 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2327 sizeof(pvar->settings.
2328 KnownHostsFiles), buf);
2329 buf[0] = 0;
2330 bufindex = 0;
2331 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2332 for (i = 0; buf[i] != 0; i++) {
2333 if (buf[i] == ';') {
2334 buf[i] = 0;
2335 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2336 pvar->settings.KnownHostsFiles[j] = ';';
2337 j++;
2338 j += copy_teraterm_dir_relative_path(pvar->settings.
2339 KnownHostsFiles + j,
2340 sizeof(pvar->settings.
2341 KnownHostsFiles)
2342 - j, buf + bufindex);
2343 }
2344 bufindex = i + 1;
2345 }
2346 }
2347 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2348 pvar->settings.KnownHostsFiles[j] = ';';
2349 j++;
2350 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2351 sizeof(pvar->settings.
2352 KnownHostsFiles) - j,
2353 buf + bufindex);
2354 }
2355
2356 // get SSH HeartBeat(keep-alive)
2357 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2358 i = atoi(buf);
2359 if (i < 0)
2360 i = 60;
2361 pvar->settings.ssh_heartbeat_overtime = i;
2362
2363 }
2364
2365 static void move_cur_sel_delta(HWND listbox, int delta)
2366 {
2367 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2368 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2369 int newPos = curPos + delta;
2370 char buf[1024];
2371
2372 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2373 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2374
2375 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2376 buf[0] = 0;
2377 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2378 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2379 SendMessage(listbox, LB_INSERTSTRING, newPos,
2380 (LPARAM) (char FAR *) buf);
2381 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2382 }
2383 }
2384 }
2385
2386 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2387 int readonly)
2388 {
2389 #ifdef TERATERM32
2390 OPENFILENAME params;
2391 char fullname_buf[2048] = "ssh_known_hosts";
2392
2393 params.lStructSize = sizeof(OPENFILENAME);
2394 params.hwndOwner = parent;
2395 params.lpstrFilter = NULL;
2396 params.lpstrCustomFilter = NULL;
2397 params.nFilterIndex = 0;
2398 buf[0] = 0;
2399 params.lpstrFile = fullname_buf;
2400 params.nMaxFile = sizeof(fullname_buf);
2401 params.lpstrFileTitle = NULL;
2402 params.lpstrInitialDir = NULL;
2403 #ifndef NO_I18N
2404 if (readonly) {
2405 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Choose a read-only known-hosts file to add", _TRUNCATE);
2406 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar);
2407 }
2408 else {
2409 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Choose a read/write known-hosts file", _TRUNCATE);
2410 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar);
2411 }
2412 params.lpstrTitle = pvar->ts->UIMsg;
2413 #else
2414 params.lpstrTitle =
2415 readonly ? "Choose a read-only known-hosts file to add" :
2416 "Choose a read/write known-hosts file";
2417 #endif
2418 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2419 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2420 params.lpstrDefExt = NULL;
2421
2422 if (GetOpenFileName(&params) != 0) {
2423 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2424 return 1;
2425 } else {
2426 int err = CommDlgExtendedError();
2427
2428 if (err != 0) {
2429 char buf[1024];
2430 #ifndef NO_I18N
2431 strncpy_s(pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg), "Unable to display file dialog box: error %d", _TRUNCATE);
2432 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar);
2433 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, err);
2434 #else
2435 _snprintf(buf, sizeof(buf),
2436 "Cannot show file dialog box: error %d", err);
2437 #endif
2438 buf[sizeof(buf) - 1] = 0;
2439 MessageBox(parent, buf, "TTSSH Error",
2440 MB_OK | MB_ICONEXCLAMATION);
2441 }
2442
2443 return 0;
2444 }
2445 #else
2446 return 0;
2447 #endif
2448 }
2449
2450 static void choose_read_write_file(HWND dlg)
2451 {
2452 char buf[1024];
2453
2454 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2455 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2456 }
2457 }
2458
2459 static void choose_read_only_file(HWND dlg)
2460 {
2461 char buf[1024];
2462 char buf2[4096];
2463
2464 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2465 buf2[0] = 0;
2466 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2467 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2468 strncat_s(buf2, sizeof(buf2), ";", _TRUNCATE);
2469 }
2470 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2471 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2472 }
2473 }
2474
2475 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2476 LPARAM lParam)
2477 {
2478 #ifndef NO_I18N
2479 LOGFONT logfont;
2480 HFONT font;
2481 #endif
2482 switch (msg) {
2483 case WM_INITDIALOG:
2484 SetWindowLong(dlg, DWL_USER, lParam);
2485 init_setup_dlg((PTInstVar) lParam, dlg);
2486 #ifndef NO_I18N
2487 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2488 GetObject(font, sizeof(LOGFONT), &logfont);
2489 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2490 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2491 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2492 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2493 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2494 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2495 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2496 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2497 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2498 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2499 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2500 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2501 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2502 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2503 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2504 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2505 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2506 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2507 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2508 }
2509 else {
2510 DlgSetupFont = NULL;
2511 }
2512 #endif
2513 return TRUE;
2514 case WM_COMMAND:
2515 switch (LOWORD(wParam)) {
2516 case IDOK:
2517 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
2518 dlg);
2519 EndDialog(dlg, 1);
2520 #ifndef NO_I18N
2521 if (DlgSetupFont != NULL) {
2522 DeleteObject(DlgSetupFont);
2523 }
2524 #endif
2525 return TRUE;
2526 case IDCANCEL: /* there isn't a cancel button, but other Windows
2527 UI things can send this message */
2528 EndDialog(dlg, 0);
2529 #ifndef NO_I18N
2530 if (DlgSetupFont != NULL) {
2531 DeleteObject(DlgSetupFont);
2532 }
2533 #endif
2534 return TRUE;
2535 case IDC_SSHMOVECIPHERUP:
2536 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2537 set_move_button_status(dlg);
2538 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2539 return TRUE;
2540 case IDC_SSHMOVECIPHERDOWN:
2541 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2542 set_move_button_status(dlg);
2543 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2544 return TRUE;
2545 case IDC_SSHCIPHERPREFS:
2546 set_move_button_status(dlg);
2547 return TRUE;
2548 case IDC_CHOOSEREADWRITEFILE:
2549 choose_read_write_file(dlg);
2550 return TRUE;
2551 case IDC_CHOOSEREADONLYFILE:
2552 choose_read_only_file(dlg);
2553 return TRUE;
2554 }
2555 break;
2556 }
2557
2558 return FALSE;
2559 }
2560
2561
2562 //
2563 // SSH key generator dialog (2005.4.10 yutaka)
2564 //
2565
2566 typedef struct {
2567 RSA *rsa;
2568 DSA *dsa;
2569 } ssh_private_key_t;
2570
2571 static ssh_private_key_t private_key = {NULL, NULL};
2572
2573 typedef struct {
2574 RSA *rsa;
2575 DSA *dsa;
2576 } ssh_public_key_t;
2577
2578 static ssh_public_key_t public_key = {NULL, NULL};;
2579
2580 static void free_ssh_key(void)
2581 {
2582 // DSA_free(), RSA_free()��NULL���n�����������������B
2583 DSA_free(private_key.dsa);
2584 private_key.dsa = NULL;
2585 DSA_free(public_key.dsa);
2586 public_key.dsa = NULL;
2587
2588 RSA_free(private_key.rsa);
2589 private_key.rsa = NULL;
2590 RSA_free(public_key.rsa);
2591 public_key.rsa = NULL;
2592 }
2593
2594
2595 static BOOL generate_ssh_key(enum hostkey_type type)
2596 {
2597 int bits = 1024;
2598
2599 // if SSH key already is generated, should free the resource.
2600 free_ssh_key();
2601
2602 if (type == KEY_RSA1 || type == KEY_RSA) {
2603 RSA *priv = NULL;
2604 RSA *pub = NULL;
2605
2606 // private key
2607 priv = RSA_generate_key(bits, 35, NULL, NULL);
2608 if (priv == NULL)
2609 goto error;
2610 private_key.rsa = priv;
2611
2612 // public key
2613 pub = RSA_new();
2614 pub->n = BN_new();
2615 pub->e = BN_new();
2616 if (pub->n == NULL || pub->e == NULL) {
2617 RSA_free(pub);
2618 goto error;
2619 }
2620
2621 BN_copy(pub->n, priv->n);
2622 BN_copy(pub->e, priv->e);
2623 public_key.rsa = pub;
2624
2625 } else if (type == KEY_DSA) {
2626 DSA *priv = NULL;
2627 DSA *pub = NULL;
2628
2629 // private key
2630 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2631 if (priv == NULL)
2632 goto error;
2633 if (!DSA_generate_key(priv)) {
2634 // TODO: free 'priv'?
2635 goto error;
2636 }
2637 private_key.dsa = priv;
2638
2639 // public key
2640 pub = DSA_new();
2641 if (pub == NULL)
2642 goto error;
2643 pub->p = BN_new();
2644 pub->q = BN_new();
2645 pub->g = BN_new();
2646 pub->pub_key = BN_new();
2647 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2648 DSA_free(pub);
2649 goto error;
2650 }
2651
2652 BN_copy(pub->p, priv->p);
2653 BN_copy(pub->q, priv->q);
2654 BN_copy(pub->g, priv->g);
2655 BN_copy(pub->pub_key, priv->pub_key);
2656 public_key.dsa = pub;
2657
2658 } else {
2659 goto error;
2660 }
2661
2662 return TRUE;
2663
2664 error:
2665 free_ssh_key();
2666 return FALSE;
2667 }
2668
2669
2670 //
2671 // RC4
2672 //
2673
2674 /* Size of key to use */
2675 #define SEED_SIZE 20
2676
2677 /* Number of bytes to reseed after */
2678 #define REKEY_BYTES (1 << 24)
2679
2680 static int rc4_ready = 0;
2681 static RC4_KEY rc4;
2682
2683 static void seed_rng(void)
2684 {
2685 if (RAND_status() != 1)
2686 return;
2687 }
2688
2689 static void arc4random_stir(void)
2690 {
2691 unsigned char rand_buf[SEED_SIZE];
2692 int i;
2693
2694 memset(&rc4, 0, sizeof(rc4));
2695 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2696 //fatal("Couldn't obtain random bytes (error %ld)",
2697 // ERR_get_error());
2698 }
2699 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2700
2701 /*
2702 * Discard early keystream, as per recommendations in:
2703 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2704 */
2705 for(i = 0; i <= 256; i += sizeof(rand_buf))
2706 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2707
2708 memset(rand_buf, 0, sizeof(rand_buf));
2709
2710 rc4_ready = REKEY_BYTES;
2711 }
2712
2713 static unsigned int arc4random(void)
2714 {
2715 unsigned int r = 0;
2716 static int first_time = 1;
2717
2718 if (rc4_ready <= 0) {
2719 if (first_time) {
2720 seed_rng();
2721 }
2722 first_time = 0;
2723 arc4random_stir();
2724 }
2725
2726 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2727
2728 rc4_ready -= sizeof(r);
2729
2730 return(r);
2731 }
2732
2733 //
2734 // SSH1 3DES
2735 //
2736 /*
2737 * This is used by SSH1:
2738 *
2739 * What kind of triple DES are these 2 routines?
2740 *
2741 * Why is there a redundant initialization vector?
2742 *
2743 * If only iv3 was used, then, this would till effect have been
2744 * outer-cbc. However, there is also a private iv1 == iv2 which
2745 * perhaps makes differential analysis easier. On the other hand, the
2746 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2747 * result of that there is no longer any known iv1 to use when
2748 * choosing the X block.
2749 */
2750 struct ssh1_3des_ctx
2751 {
2752 EVP_CIPHER_CTX k1, k2, k3;
2753 };
2754
2755 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2756 {
2757 struct ssh1_3des_ctx *c;
2758 u_char *k1, *k2, *k3;
2759
2760 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2761 c = malloc(sizeof(*c));
2762 EVP_CIPHER_CTX_set_app_data(ctx, c);
2763 }
2764 if (key == NULL)
2765 return (1);
2766 if (enc == -1)
2767 enc = ctx->encrypt;
2768 k1 = k2 = k3 = (u_char *) key;
2769 k2 += 8;
2770 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2771 if (enc)
2772 k3 += 16;
2773 else
2774 k1 += 16;
2775 }
2776 EVP_CIPHER_CTX_init(&c->k1);
2777 EVP_CIPHER_CTX_init(&c->k2);
2778 EVP_CIPHER_CTX_init(&c->k3);
2779 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2780 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2781 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2782 memset(c, 0, sizeof(*c));
2783 free(c);
2784 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2785 return (0);
2786 }
2787 return (1);
2788 }
2789
2790 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2791 {
2792 struct ssh1_3des_ctx *c;
2793
2794 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2795 //error("ssh1_3des_cbc: no context");
2796 return (0);
2797 }
2798 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2799 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2800 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2801 return (0);
2802 return (1);
2803 }
2804
2805 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2806 {
2807 struct ssh1_3des_ctx *c;
2808
2809 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2810 EVP_CIPHER_CTX_cleanup(&c->k1);
2811 EVP_CIPHER_CTX_cleanup(&c->k2);
2812 EVP_CIPHER_CTX_cleanup(&c->k3);
2813 memset(c, 0, sizeof(*c));
2814 free(c);
2815 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2816 }
2817 return (1);
2818 }
2819
2820 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2821 {
2822 struct ssh1_3des_ctx *c;
2823
2824 if (len != 24)
2825 //fatal("%s: bad 3des iv length: %d", __func__, len);
2826 ;
2827
2828 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2829 //fatal("%s: no 3des context", __func__);
2830 ;
2831
2832 if (doset) {
2833 //debug3("%s: Installed 3DES IV", __func__);
2834 memcpy(c->k1.iv, iv, 8);
2835 memcpy(c->k2.iv, iv + 8, 8);
2836 memcpy(c->k3.iv, iv + 16, 8);
2837 } else {
2838 //debug3("%s: Copying 3DES IV", __func__);
2839 memcpy(iv, c->k1.iv, 8);
2840 memcpy(iv + 8, c->k2.iv, 8);
2841 memcpy(iv + 16, c->k3.iv, 8);
2842 }
2843 }
2844
2845 const EVP_CIPHER *evp_ssh1_3des(void)
2846 {
2847 static EVP_CIPHER ssh1_3des;
2848
2849 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2850 ssh1_3des.nid = NID_undef;
2851 ssh1_3des.block_size = 8;
2852 ssh1_3des.iv_len = 0;
2853 ssh1_3des.key_len = 16;
2854 ssh1_3des.init = ssh1_3des_init;
2855 ssh1_3des.cleanup = ssh1_3des_cleanup;
2856 ssh1_3des.do_cipher = ssh1_3des_cbc;
2857 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2858 return (&ssh1_3des);
2859 }
2860
2861 static void ssh_make_comment(char *comment, int maxlen)
2862 {
2863 char user[UNLEN + 1], host[128];
2864 DWORD dwSize;
2865 WSADATA wsaData;
2866 int ret;
2867
2868 // get Windows logon user name
2869 dwSize = sizeof(user);
2870 if (GetUserName(user, &dwSize) == 0) {
2871 strncpy_s(user, sizeof(user), "yutaka", _TRUNCATE);
2872 }
2873
2874 // get local hostname (by WinSock)
2875 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2876 if (ret == 0) {
2877 if (gethostname(host, sizeof(host)) != 0) {
2878 ret = WSAGetLastError();
2879 }
2880 WSACleanup();
2881 }
2882 if (ret != 0) {
2883 strncpy_s(host, sizeof(host), "sai", _TRUNCATE);
2884 }
2885
2886 _snprintf_s(comment, maxlen, _TRUNCATE, "%s@%s", user, host);
2887 }
2888
2889 // uuencode (rfc1521)
2890 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2891 {
2892 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2893 char pad = '=';
2894 int datalength = 0;
2895 unsigned char input[3];
2896 unsigned char output[4];
2897 int i;
2898
2899 while (srclen > 2) {