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 9209 - (show annotations) (download) (as text)
Sat Apr 17 06:32:42 2021 UTC (2 years, 11 months ago) by nmaya
File MIME type: text/x-csrc
File size: 171020 byte(s)
OpenSSL 1.0.2 の API を使っているところを 1.1.0 の API に変更

- EVP_CIPHER_CTX_cleanup() -> EVP_CIPHER_CTX_free()
- EVP_CIPHER_CTX_init() -> EVP_CIPHER_CTX_reset()
- EVP_CIPHER_CTX_new() の中で 0 埋めされるので、EVP_CIPHER_CTX_init() を呼ばなくてよい所を削除

メモリの確保と解放を以下のような対応にした
- EVP_CIPHER_CTX_new() -> cipher_init_SSH2() したものは cipher_free_SSH2() で解放
- EVP_CIPHER_CTX_new() -> して cipher_init_SSH2() を通らないものは EVP_CIPHER_CTX_free() で解放
1 /*
2 * Copyright (c) 1998-2001, Robert O'Callahan
3 * (C) 2004- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* Tera Term extension mechanism
31 Robert O'Callahan (roc+tt@cs.cmu.edu)
32
33 Tera Term by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
34 */
35
36 #include "teraterm_conf.h"
37 #include "ttxssh.h"
38 #include "fwdui.h"
39 #include "util.h"
40 #include "ssh.h"
41 #include "ttcommon.h"
42 #include "ttlib.h"
43 #include "keyfiles.h"
44 #include "arc4random.h"
45 #include "auth.h"
46 #include "helpid.h"
47
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <io.h>
52 #include <fcntl.h>
53 #include <sys/stat.h>
54 #include <time.h>
55 #include <mbstring.h>
56
57 #include "resource.h"
58 #include <commctrl.h>
59 #include <commdlg.h>
60 #include <winsock2.h>
61 static char *ProtocolFamilyList[] = { "AUTO", "IPv6", "IPv4", NULL };
62
63 #include <lmcons.h>
64
65 // include OpenSSL header file
66 #include <openssl/evp.h>
67 #include <openssl/rsa.h>
68 #include <openssl/dsa.h>
69 #include <openssl/bn.h>
70 #include <openssl/pem.h>
71 #include <openssl/rand.h>
72 #include <openssl/rc4.h>
73 #include <openssl/md5.h>
74
75 // include ZLib header file
76 #include <zlib.h>
77
78 #include "buffer.h"
79 #include "cipher.h"
80 #include "key.h"
81 #include "dlglib.h"
82
83 #include "sftp.h"
84
85 #include "compat_w95.h"
86 #include "compat_win.h"
87
88 #include "libputty.h"
89
90 #undef DialogBoxParam
91 #define DialogBoxParam(p1,p2,p3,p4,p5) \
92 TTDialogBoxParam(p1,p2,p3,p4,p5)
93 #undef EndDialog
94 #define EndDialog(p1,p2) \
95 TTEndDialog(p1, p2)
96
97 #define MATCH_STR(s, o) strncmp((s), (o), NUM_ELEM(o) - 1)
98 #define MATCH_STR_I(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
99
100 /* This extension implements SSH, so we choose a load order in the
101 "protocols" range. */
102 #define ORDER 2500
103
104 HANDLE hInst; /* Instance handle of TTXSSH.DLL */
105
106 static HICON SecureLargeIcon = NULL;
107 static HICON SecureSmallIcon = NULL;
108 static HICON SecureNotifyIcon = NULL;
109 static HICON OldNotifyIcon = NULL;
110
111 static TInstVar *pvar;
112
113 typedef struct {
114 int cnt;
115 HWND dlg;
116 ssh_keytype type;
117 } cbarg_t;
118
119 /* WIN32 allows multiple instances of a DLL */
120 static TInstVar InstVar;
121
122 /*
123 This code makes lots of assumptions about the order in which Tera Term
124 does things, and how. A key assumption is that the Notification window
125 passed into WSAAsyncSelect is the main terminal window. We also assume
126 that the socket used in the first WSAconnect is the main session socket.
127 */
128
129 static void init_TTSSH(PTInstVar pvar)
130 {
131 pvar->socket = INVALID_SOCKET;
132 pvar->OldLargeIcon = NULL;
133 pvar->OldSmallIcon = NULL;
134 pvar->NotificationWindow = NULL;
135 pvar->hostdlg_activated = FALSE;
136 pvar->socket = INVALID_SOCKET;
137 pvar->NotificationWindow = NULL;
138 pvar->protocol_major = 0;
139 pvar->protocol_minor = 0;
140
141 /*
142 * pvar->contents_after_known_hosts �����}�I��
143 * init_TTSSH()��uninit_TTSSH()�������������������������B
144 * �����������Aknown_hosts�_�C�A���O���g�p���������������A
145 * �_�C�A���O���\������ TTXCloseTCP() �������o�����������������A
146 * pvar->contents_after_known_hosts �������������������������������������B
147 */
148
149 PKT_init(pvar);
150 SSH_init(pvar);
151 CRYPT_init(pvar);
152 AUTH_init(pvar);
153 HOSTS_init(pvar);
154 FWD_init(pvar);
155 FWDUI_init(pvar);
156
157 ssh_heartbeat_lock_initialize();
158
159 pvar->evpcip[MODE_IN] = EVP_CIPHER_CTX_new();
160 pvar->evpcip[MODE_OUT] = EVP_CIPHER_CTX_new();
161 /*** TODO: OPENSSL1.1.1 ERROR CHECK(ticket#39335�����u�\��) ***/
162 }
163
164 static void uninit_TTSSH(PTInstVar pvar)
165 {
166 halt_ssh_heartbeat_thread(pvar);
167
168 ssh2_channel_free();
169
170 SSH_end(pvar);
171 PKT_end(pvar);
172 AUTH_end(pvar);
173 CRYPT_end(pvar);
174 HOSTS_end(pvar);
175 FWD_end(pvar);
176 FWDUI_end(pvar);
177
178 if (pvar->OldLargeIcon != NULL) {
179 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
180 (LPARAM) pvar->OldLargeIcon);
181 pvar->OldLargeIcon = NULL;
182 }
183 if (pvar->OldSmallIcon != NULL) {
184 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
185 (LPARAM) pvar->OldSmallIcon);
186 pvar->OldSmallIcon = NULL;
187 }
188 if (OldNotifyIcon) {
189 SetCustomNotifyIcon(OldNotifyIcon);
190 }
191
192 ssh_heartbeat_lock_finalize();
193
194 cipher_free_SSH2(pvar->evpcip[MODE_IN]);
195 cipher_free_SSH2(pvar->evpcip[MODE_OUT]);
196 }
197
198 static void PASCAL TTXInit(PTTSet ts, PComVar cv)
199 {
200 pvar->settings = *pvar->ts_SSH;
201 pvar->ts = ts;
202 pvar->cv = cv;
203 pvar->fatal_error = FALSE;
204 pvar->showing_err = FALSE;
205 pvar->err_msg = NULL;
206
207 init_TTSSH(pvar);
208 }
209
210 static void normalize_generic_order(char *buf, char default_strings[], int default_strings_len)
211 {
212 char listed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
213 char allowed[max(KEX_DH_MAX,max(SSH_CIPHER_MAX,max(KEY_MAX,max(HMAC_MAX,COMP_MAX)))) + 1];
214 int i, j, k=-1;
215
216 memset(listed, 0, sizeof(listed));
217 memset(allowed, 0, sizeof(allowed));
218
219 // �����������������������X�g�������B
220 for (i = 0; i < default_strings_len ; i++) {
221 allowed[default_strings[i]] = 1;
222 }
223
224 // �w�����������������������A���������������������A�d���������������������B
225 //
226 // ex. (i=5 ����������������)
227 // i=012345
228 // >:=9<87;A@?B3026(\0)
229 // i+1
230 // <------------>
231 // ��
232 // >:=9<7;A@?B3026(\0)
233 //
234 for (i = 0; buf[i] != 0; i++) {
235 int num = buf[i] - '0';
236
237 if (num < 0 || num > default_strings_len
238 || !allowed[num]
239 || listed[num]) {
240 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
241 i--;
242 } else {
243 listed[num] = 1;
244 }
245
246 // disabled line���������A���u���o���������B
247 if (num == 0) {
248 k = i;
249 }
250 }
251
252 // �w���������������������������Adisabled line�����O���}�������B
253 //
254 // ex. (Z���}������)
255 // k
256 // >:=9<87;A@?B3026(\0)
257 // k+1
258 // <---->
259 // �� k
260 // >:=9<87;A@?B30026(\0)
261 // �� k
262 // >:=9<87;A@?B3Z026(\0)
263 //
264 for (j = 0; j < default_strings_len && default_strings[j] != 0; j++) {
265 int num = default_strings[j];
266
267 if (!listed[num] && k >= 0) {
268 int copylen = strlen(buf + k + 1) + 1;
269
270 memmove(buf + k + 1, buf + k, copylen);
271 buf[k + 1 + copylen] = '\0'; // �I�[���Y�������t�����B
272 buf[k] = num + '0';
273 k++;
274 i++;
275 }
276 }
277 if (k < 0) {
278 j = 0;
279 }
280 else {
281 j++;
282 }
283
284 // disabled line�������������������A�����������������������B
285 for (; j < default_strings_len ; j++) {
286 int num = default_strings[j];
287
288 if (!listed[num]) {
289 buf[i] = num + '0';
290 listed[num] = 1;
291 i++;
292 }
293 }
294
295 buf[i] = 0;
296 }
297
298 /*
299 * Remove unsupported cipher or duplicated cipher.
300 * Add unspecified ciphers at the end of list.
301 */
302 static void normalize_cipher_order(char *buf)
303 {
304 /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
305 We *never* allow no encryption. */
306 static char default_strings[] = {
307 SSH2_CIPHER_AES256_GCM,
308 SSH2_CIPHER_CAMELLIA256_CTR,
309 SSH2_CIPHER_AES256_CTR,
310 SSH2_CIPHER_CAMELLIA256_CBC,
311 SSH2_CIPHER_AES256_CBC,
312 SSH2_CIPHER_CAMELLIA192_CTR,
313 SSH2_CIPHER_AES192_CTR,
314 SSH2_CIPHER_CAMELLIA192_CBC,
315 SSH2_CIPHER_AES192_CBC,
316 SSH2_CIPHER_AES128_GCM,
317 SSH2_CIPHER_CAMELLIA128_CTR,
318 SSH2_CIPHER_AES128_CTR,
319 SSH2_CIPHER_CAMELLIA128_CBC,
320 SSH2_CIPHER_AES128_CBC,
321 SSH2_CIPHER_3DES_CTR,
322 SSH2_CIPHER_3DES_CBC,
323 SSH2_CIPHER_BLOWFISH_CTR,
324 SSH2_CIPHER_BLOWFISH_CBC,
325 SSH2_CIPHER_CAST128_CTR,
326 SSH2_CIPHER_CAST128_CBC,
327 SSH_CIPHER_3DES,
328 SSH_CIPHER_NONE,
329 SSH2_CIPHER_ARCFOUR256,
330 SSH2_CIPHER_ARCFOUR128,
331 SSH2_CIPHER_ARCFOUR,
332 SSH_CIPHER_BLOWFISH,
333 SSH_CIPHER_DES,
334 0, 0, 0 // Dummy for SSH_CIPHER_IDEA, SSH_CIPHER_TSS, SSH_CIPHER_RC4
335 };
336
337 normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
338 }
339
340 static void normalize_kex_order(char *buf)
341 {
342 static char default_strings[] = {
343 KEX_ECDH_SHA2_256,
344 KEX_ECDH_SHA2_384,
345 KEX_ECDH_SHA2_521,
346 KEX_DH_GRP18_SHA512,
347 KEX_DH_GRP16_SHA512,
348 KEX_DH_GRP14_SHA256,
349 KEX_DH_GEX_SHA256,
350 KEX_DH_GEX_SHA1,
351 KEX_DH_GRP14_SHA1,
352 KEX_DH_GRP1_SHA1,
353 KEX_DH_NONE,
354 };
355
356 normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
357 }
358
359 static void normalize_host_key_order(char *buf)
360 {
361 static char default_strings[] = {
362 KEY_ECDSA256,
363 KEY_ECDSA384,
364 KEY_ECDSA521,
365 KEY_ED25519,
366 KEY_RSA,
367 KEY_DSA,
368 KEY_NONE,
369 };
370
371 normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
372 }
373
374 static void normalize_mac_order(char *buf)
375 {
376 static char default_strings[] = {
377 HMAC_SHA2_512_EtM,
378 HMAC_SHA2_256_EtM,
379 HMAC_SHA1_EtM,
380 HMAC_SHA2_512,
381 HMAC_SHA2_256,
382 HMAC_SHA1,
383 HMAC_RIPEMD160_EtM,
384 HMAC_RIPEMD160,
385 HMAC_MD5_EtM,
386 HMAC_MD5,
387 HMAC_NONE,
388 HMAC_SHA1_96_EtM,
389 HMAC_MD5_96_EtM,
390 HMAC_SHA1_96,
391 HMAC_MD5_96,
392 0, // Dummy for HMAC_SHA2_512_96,
393 0, // Dummy for HMAC_SHA2_256_96,
394 };
395
396 normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
397 }
398
399 static void normalize_comp_order(char *buf)
400 {
401 static char default_strings[] = {
402 COMP_DELAYED,
403 COMP_ZLIB,
404 COMP_NOCOMP,
405 COMP_NONE,
406 };
407
408 normalize_generic_order(buf, default_strings, NUM_ELEM(default_strings));
409 }
410
411
412 /* Remove local settings from the shared memory block. */
413 static void clear_local_settings(PTInstVar pvar)
414 {
415 pvar->ts_SSH->TryDefaultAuth = FALSE;
416 }
417
418 static BOOL read_BOOL_option(PCHAR fileName, char *keyName, BOOL def)
419 {
420 char buf[1024];
421
422 buf[0] = 0;
423 GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
424 fileName);
425 if (buf[0] == 0) {
426 return def;
427 } else {
428 return atoi(buf) != 0 ||
429 _stricmp(buf, "yes") == 0 ||
430 _stricmp(buf, "y") == 0;
431 }
432 }
433
434 static void read_string_option(PCHAR fileName, char *keyName,
435 char *def, char *buf, int bufSize)
436 {
437
438 buf[0] = 0;
439 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
440 }
441
442 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
443 {
444 char buf[1024];
445 TS_SSH *settings = pvar->ts_SSH;
446
447 #define READ_STD_STRING_OPTION(name) \
448 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
449
450 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
451
452 buf[0] = 0;
453 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
454 fileName);
455 settings->CompressionLevel = atoi(buf);
456 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
457 settings->CompressionLevel = 0;
458 }
459
460 READ_STD_STRING_OPTION(DefaultUserName);
461 settings->DefaultUserType = GetPrivateProfileInt("TTSSH", "DefaultUserType", 1, fileName);
462
463 READ_STD_STRING_OPTION(DefaultForwarding);
464 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
465 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
466 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
467
468 READ_STD_STRING_OPTION(CipherOrder);
469 normalize_cipher_order(settings->CipherOrder);
470
471 // KEX order
472 READ_STD_STRING_OPTION(KexOrder);
473 normalize_kex_order(settings->KexOrder);
474 // Host Key algorithm order
475 READ_STD_STRING_OPTION(HostKeyOrder);
476 normalize_host_key_order(settings->HostKeyOrder);
477 // HMAC order
478 READ_STD_STRING_OPTION(MacOrder);
479 normalize_mac_order(settings->MacOrder);
480 // Compression algorithm order
481 READ_STD_STRING_OPTION(CompOrder);
482 normalize_comp_order(settings->CompOrder);
483
484 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
485 settings->KnownHostsFiles,
486 sizeof(settings->KnownHostsFiles));
487
488 buf[0] = 0;
489 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
490 sizeof(buf), fileName);
491 settings->DefaultAuthMethod = atoi(buf);
492 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
493 && settings->DefaultAuthMethod != SSH_AUTH_RSA
494 && settings->DefaultAuthMethod != SSH_AUTH_TIS // add (2005.3.12 yutaka)
495 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS
496 && settings->DefaultAuthMethod != SSH_AUTH_PAGEANT) {
497 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
498 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
499 when the dialog box has rhosts selected and an host private key file
500 is supplied. */
501 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
502 }
503
504 buf[0] = 0;
505 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
506 fileName);
507 settings->LogLevel = atoi(buf);
508
509 buf[0] = 0;
510 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
511 sizeof(buf), fileName);
512 settings->WriteBufferSize = atoi(buf);
513 if (settings->WriteBufferSize <= 0) {
514 settings->WriteBufferSize = (PACKET_MAX_SIZE / 2); // 2MB
515 }
516
517 // SSH protocol version (2004.10.11 yutaka)
518 // default is SSH2 (2004.11.30 yutaka)
519 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
520
521 // SSH heartbeat time(second) (2004.12.11 yutaka)
522 settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
523
524 // �p�X���[�h�F�����������J���F�����g���p�X���[�h����������������������������������
525 // �\���B(2006.8.5 yutaka)
526 settings->remember_password = GetPrivateProfileInt("TTSSH", "RememberPassword", 1, fileName);
527
528 // �������F���_�C�A���O���T�|�[�g�������������\�b�h���`�F�b�N���A
529 // ���������\�b�h���O���C�A�E�g���� (2007.9.24 maya)
530 settings->CheckAuthListFirst = read_BOOL_option(fileName, "CheckAuthListFirst", FALSE);
531
532 // 768bit ������ RSA ���������T�[�o�����������L�������� (2008.9.11 maya)
533 settings->EnableRsaShortKeyServer = read_BOOL_option(fileName, "EnableRsaShortKeyServer", FALSE);
534
535 // agent forward ���L�������� (2008.11.25 maya)
536 settings->ForwardAgent = read_BOOL_option(fileName, "ForwardAgent", FALSE);
537
538 // agent forward �m�F���L��������
539 settings->ForwardAgentConfirm = read_BOOL_option(fileName, "ForwardAgentConfirm", TRUE);
540
541 // agent forward �m�F���L��������
542 settings->ForwardAgentNotify = read_BOOL_option(fileName, "ForwardAgentNotify", TRUE);
543
544 // �z�X�g���� DNS �����`�F�b�N (RFC 4255)
545 settings->VerifyHostKeyDNS = read_BOOL_option(fileName, "VerifyHostKeyDNS", TRUE);
546
547 // icon
548 GetPrivateProfileString("TTSSH", "SSHIcon", "", buf, sizeof(buf), fileName);
549 if ((_stricmp(buf, "old") == 0) ||
550 (_stricmp(buf, "yellow") == 0) ||
551 (_stricmp(buf, "securett_yellow") == 0)) {
552 settings->IconID = IDI_SECURETT_YELLOW;
553 }
554 else if ((_stricmp(buf, "green") == 0) ||
555 (_stricmp(buf, "securett_green") == 0)) {
556 settings->IconID = IDI_SECURETT_GREEN;
557 }
558 else {
559 settings->IconID = IDI_SECURETT;
560 }
561
562 // �G���[�������x�������|�b�v�A�b�v���b�Z�[�W���}�~���� (2014.6.26 yutaka)
563 settings->DisablePopupMessage = GetPrivateProfileInt("TTSSH", "DisablePopupMessage", 0, fileName);
564
565 READ_STD_STRING_OPTION(X11Display);
566
567 settings->UpdateHostkeys = GetPrivateProfileInt("TTSSH", "UpdateHostkeys", 0, fileName);
568
569 settings->GexMinimalGroupSize = GetPrivateProfileInt("TTSSH", "GexMinimalGroupSize", 0, fileName);
570
571 settings->AuthBanner = GetPrivateProfileInt("TTSSH", "AuthBanner", 1, fileName);
572
573 clear_local_settings(pvar);
574 }
575
576 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
577 TS_SSH *settings, BOOL copy_forward)
578 {
579 char buf[1024];
580
581 WritePrivateProfileString("TTSSH", "Enabled",
582 settings->Enabled ? "1" : "0", fileName);
583
584 _itoa(settings->CompressionLevel, buf, 10);
585 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
586
587 _itoa(settings->DefaultUserType, buf, 10);
588 WritePrivateProfileString("TTSSH", "DefaultUserType", buf, fileName);
589 WritePrivateProfileString("TTSSH", "DefaultUserName",
590 settings->DefaultUserName, fileName);
591
592 if (copy_forward) {
593 WritePrivateProfileString("TTSSH", "DefaultForwarding",
594 settings->DefaultForwarding, fileName);
595 }
596
597 WritePrivateProfileString("TTSSH", "CipherOrder",
598 settings->CipherOrder, fileName);
599
600 WritePrivateProfileString("TTSSH", "KexOrder",
601 settings->KexOrder, fileName);
602
603 WritePrivateProfileString("TTSSH", "HostKeyOrder",
604 settings->HostKeyOrder, fileName);
605
606 WritePrivateProfileString("TTSSH", "MacOrder",
607 settings->MacOrder, fileName);
608
609 WritePrivateProfileString("TTSSH", "CompOrder",
610 settings->CompOrder, fileName);
611
612 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
613 settings->KnownHostsFiles, fileName);
614
615 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
616 settings->DefaultRhostsLocalUserName,
617 fileName);
618
619 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
620 settings->DefaultRhostsHostPrivateKeyFile,
621 fileName);
622
623 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
624 settings->DefaultRSAPrivateKeyFile,
625 fileName);
626
627 _itoa(settings->DefaultAuthMethod, buf, 10);
628 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
629
630 _itoa(settings->LogLevel, buf, 10);
631 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
632
633 _itoa(settings->WriteBufferSize, buf, 10);
634 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
635
636 // SSH protocol version (2004.10.11 yutaka)
637 WritePrivateProfileString("TTSSH", "ProtocolVersion",
638 settings->ssh_protocol_version==2 ? "2" : "1",
639 fileName);
640
641 // SSH heartbeat time(second) (2004.12.11 yutaka)
642 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
643 "%d", settings->ssh_heartbeat_overtime);
644 WritePrivateProfileString("TTSSH", "HeartBeat", buf, fileName);
645
646 // Remember password (2006.8.5 yutaka)
647 WritePrivateProfileString("TTSSH", "RememberPassword",
648 settings->remember_password ? "1" : "0",
649 fileName);
650
651 // �������F���_�C�A���O���T�|�[�g�������������\�b�h���`�F�b�N���A
652 // ���������\�b�h���O���C�A�E�g���� (2007.9.24 maya)
653 WritePrivateProfileString("TTSSH", "CheckAuthListFirst",
654 settings->CheckAuthListFirst ? "1" : "0", fileName);
655
656 // 768bit ������ RSA ���������T�[�o�����������L�������� (2008.9.11 maya)
657 WritePrivateProfileString("TTSSH", "EnableRsaShortKeyServer",
658 settings->EnableRsaShortKeyServer ? "1" : "0", fileName);
659
660 // agent forward ���L�������� (2008.11.25 maya)
661 WritePrivateProfileString("TTSSH", "ForwardAgent",
662 settings->ForwardAgent ? "1" : "0", fileName);
663
664 // agent forward �m�F���L��������
665 WritePrivateProfileString("TTSSH", "ForwardAgentConfirm",
666 settings->ForwardAgentConfirm ? "1" : "0", fileName);
667
668 // agent forward ���m���L��������
669 WritePrivateProfileString("TTSSH", "ForwardAgentNotify",
670 settings->ForwardAgentNotify ? "1" : "0", fileName);
671
672 // �z�X�g���� DNS �����`�F�b�N (RFC 4255)
673 WritePrivateProfileString("TTSSH", "VerifyHostKeyDNS",
674 settings->VerifyHostKeyDNS ? "1" : "0", fileName);
675
676 // SSH �A�C�R��
677 if (settings->IconID==IDI_SECURETT_YELLOW) {
678 WritePrivateProfileString("TTSSH", "SSHIcon", "yellow", fileName);
679 }
680 else if (settings->IconID==IDI_SECURETT_GREEN) {
681 WritePrivateProfileString("TTSSH", "SSHIcon", "green", fileName);
682 }
683 else {
684 WritePrivateProfileString("TTSSH", "SSHIcon", "Default", fileName);
685 }
686
687 _itoa(settings->DisablePopupMessage, buf, 10);
688 WritePrivateProfileString("TTSSH", "DisablePopupMessage", buf, fileName);
689
690 WritePrivateProfileString("TTSSH", "X11Display", settings->X11Display, fileName);
691
692 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
693 "%d", settings->UpdateHostkeys);
694 WritePrivateProfileString("TTSSH", "UpdateHostkeys", buf, fileName);
695
696 _itoa_s(settings->GexMinimalGroupSize, buf, sizeof(buf), 10);
697 WritePrivateProfileString("TTSSH", "GexMinimalGroupSize", buf, fileName);
698
699 _itoa_s(settings->AuthBanner, buf, sizeof(buf), 10);
700 WritePrivateProfileString("TTSSH", "AuthBanner", buf, fileName);
701 }
702
703
704 /* find free port in all protocol family */
705 static unsigned short find_local_port(PTInstVar pvar)
706 {
707 int tries;
708 SOCKET connecter;
709 struct addrinfo hints;
710 struct addrinfo *res;
711 struct addrinfo *res0;
712 unsigned short port;
713 char pname[NI_MAXHOST];
714
715 if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
716 return 0;
717 }
718
719 /* The random numbers here are only used to try to get fresh
720 ports across runs (dangling ports can cause bind errors
721 if we're unlucky). They do not need to be (and are not)
722 cryptographically strong.
723 */
724 srand((unsigned) GetTickCount());
725
726 for (tries = 20; tries > 0; tries--) {
727 memset(&hints, 0, sizeof(hints));
728 hints.ai_family = pvar->ts->ProtocolFamily;
729 hints.ai_flags = AI_PASSIVE;
730 hints.ai_socktype = SOCK_STREAM;
731 port = (unsigned) rand() % 512 + 512;
732 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", (int) port);
733 if (getaddrinfo(NULL, pname, &hints, &res0)) {
734 return 0;
735 /* NOT REACHED */
736 }
737
738 for (res = res0; res; res = res->ai_next) {
739 if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
740 continue;
741
742 connecter =
743 socket(res->ai_family, res->ai_socktype, res->ai_protocol);
744 if (connecter == INVALID_SOCKET) {
745 freeaddrinfo(res0);
746 return 0;
747 }
748
749 if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
750 SOCKET_ERROR) {
751 return port;
752 freeaddrinfo(res0);
753 closesocket(connecter);
754 } else if (WSAGetLastError() != WSAEADDRINUSE) {
755 closesocket(connecter);
756 freeaddrinfo(res0);
757 return 0;
758 }
759
760 closesocket(connecter);
761 }
762 freeaddrinfo(res0);
763 }
764
765 return 0;
766 }
767
768 static int PASCAL TTXconnect(SOCKET s,
769 const struct sockaddr *name,
770 int namelen)
771 {
772 if (pvar->socket == INVALID_SOCKET || pvar->socket != s) {
773 struct sockaddr_storage ss;
774 int len;
775
776 pvar->socket = s;
777
778 memset(&ss, 0, sizeof(ss));
779 switch (pvar->ts->ProtocolFamily) {
780 case AF_INET:
781 len = sizeof(struct sockaddr_in);
782 ((struct sockaddr_in *) &ss)->sin_family = AF_INET;
783 ((struct sockaddr_in *) &ss)->sin_addr.s_addr = INADDR_ANY;
784 ((struct sockaddr_in *) &ss)->sin_port =
785 htons(find_local_port(pvar));
786 break;
787 case AF_INET6:
788 len = sizeof(struct sockaddr_in6);
789 ((struct sockaddr_in6 *) &ss)->sin6_family = AF_INET6;
790 ((struct sockaddr_in6 *) &ss)->sin6_addr = in6addr_any;
791 ((struct sockaddr_in6 *) &ss)->sin6_port =
792 htons(find_local_port(pvar));
793 break;
794 default:
795 /* UNSPEC */
796 len = sizeof(ss);
797 ss.ss_family = AF_UNSPEC;
798 break;
799 }
800
801 bind(s, (struct sockaddr *) &ss, len);
802 }
803
804 return (pvar->Pconnect) (s, name, namelen);
805 }
806
807 static int PASCAL TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
808 long lEvent)
809 {
810 if (s == pvar->socket) {
811 pvar->notification_events = lEvent;
812 pvar->notification_msg = wMsg;
813
814 if (pvar->NotificationWindow == NULL) {
815 pvar->NotificationWindow = hWnd;
816 // AUTH_advance_to_next_cred()�������o�������������B
817 // NotificationWindow���n���h�������������������A�����^�C�~���O����
818 // �F���_�C�A���O���o���������������BProxy��NAT�o�R���T�[�o������
819 // �������������A���������f�����������������A�F���_�C�A���O��
820 // �\�������������������������B
821 }
822 }
823
824 return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
825 }
826
827 static int PASCAL TTXrecv(SOCKET s, char *buf, int len, int flags)
828 {
829 if (s == pvar->socket) {
830 int ret;
831
832 ssh_heartbeat_lock();
833 ret = PKT_recv(pvar, buf, len);
834 ssh_heartbeat_unlock();
835 return (ret);
836
837 } else {
838 return (pvar->Precv) (s, buf, len, flags);
839 }
840 }
841
842 static int PASCAL TTXsend(SOCKET s, char const *buf, int len,
843 int flags)
844 {
845 if (s == pvar->socket) {
846 ssh_heartbeat_lock();
847 SSH_send(pvar, buf, len);
848 ssh_heartbeat_unlock();
849 return len;
850 } else {
851 return (pvar->Psend) (s, buf, len, flags);
852 }
853 }
854
855 void notify_established_secure_connection(PTInstVar pvar)
856 {
857 int fuLoad = LR_DEFAULTCOLOR;
858
859 if (IsWindowsNT4()) {
860 fuLoad = LR_VGACOLOR;
861 }
862
863 // LoadIcon �������� LoadImage ���g�����������A
864 // 16x16 ���A�C�R���������I�������������������� (2006.8.9 maya)
865 if (SecureLargeIcon == NULL) {
866 SecureLargeIcon = LoadImage(hInst, MAKEINTRESOURCE(pvar->settings.IconID),
867 IMAGE_ICON, 0, 0, fuLoad);
868 }
869 if (SecureSmallIcon == NULL) {
870 SecureSmallIcon = LoadImage(hInst, MAKEINTRESOURCE(pvar->settings.IconID),
871 IMAGE_ICON, 16, 16, fuLoad);
872 }
873
874 if (SecureLargeIcon != NULL && SecureSmallIcon != NULL) {
875 pvar->OldLargeIcon =
876 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
877 ICON_BIG, 0);
878 pvar->OldSmallIcon =
879 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
880 ICON_SMALL, 0);
881
882 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
883 (LPARAM) SecureLargeIcon);
884 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
885 (LPARAM) SecureSmallIcon);
886 }
887
888 if (IsWindows2000()) {
889 if (SecureNotifyIcon == NULL) {
890 SecureNotifyIcon = LoadImage(hInst, MAKEINTRESOURCE(pvar->settings.IconID),
891 IMAGE_ICON, 0, 0, LR_VGACOLOR | LR_SHARED);
892 }
893 OldNotifyIcon = GetCustomNotifyIcon();
894 SetCustomNotifyIcon(SecureNotifyIcon);
895 }
896
897 logputs(LOG_LEVEL_VERBOSE, "Entering secure mode");
898 }
899
900 void notify_closed_connection(PTInstVar pvar, char *send_msg)
901 {
902 SSH_notify_disconnecting(pvar, send_msg);
903 AUTH_notify_disconnecting(pvar);
904 HOSTS_notify_disconnecting(pvar);
905
906 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
907 pvar->socket, MAKELPARAM(FD_CLOSE, 0));
908 }
909
910 // non-fatal������fatal�����G���[���b�Z�[�W���o���������B
911 // ���x�A�o�������b�Z�[�W���������A���s���������������������B
912 static void add_err_msg(PTInstVar pvar, char *msg)
913 {
914 if (pvar->err_msg != NULL) {
915 int buf_len;
916 char *buf;
917
918 // �������������b�Z�[�W���o�^�����������������������B
919 if (strstr(pvar->err_msg, msg))
920 return;
921
922 buf_len = strlen(pvar->err_msg) + 3 + strlen(msg);
923 buf = malloc(buf_len);
924 // ���������m���������������������������B
925 if (buf == NULL)
926 return;
927
928 strncpy_s(buf, buf_len, pvar->err_msg, _TRUNCATE);
929 strncat_s(buf, buf_len, "\n\n", _TRUNCATE);
930 strncat_s(buf, buf_len, msg, _TRUNCATE);
931 free(pvar->err_msg);
932 pvar->err_msg = buf;
933 } else {
934 // ���������m�����������������A_strdup()��NULL�������B
935 pvar->err_msg = _strdup(msg);
936 }
937 }
938
939 void notify_nonfatal_error(PTInstVar pvar, char *msg)
940 {
941 if (!pvar->showing_err) {
942 // �������������������m���E�B���h�E�����������A�f�X�N�g�b�v���I�[�i�[������
943 // ���b�Z�[�W�{�b�N�X���o���������B(2006.6.11 yutaka)
944 if (pvar->NotificationWindow == NULL) {
945 UTIL_get_lang_msg("MSG_NONFATAL_ERROR", pvar,
946 "Tera Term: not fatal error");
947 MessageBox(NULL, msg, pvar->ts->UIMsg, MB_OK|MB_ICONINFORMATION);
948 msg[0] = '\0';
949
950 } else {
951 PostMessage(pvar->NotificationWindow, WM_COMMAND,
952 ID_SSHASYNCMESSAGEBOX, 0);
953 }
954 }
955 if (msg[0] != 0) {
956 logputs(LOG_LEVEL_ERROR, msg);
957 add_err_msg(pvar, msg);
958 }
959 }
960
961 void notify_fatal_error(PTInstVar pvar, char *msg, BOOL send_disconnect)
962 {
963 if (msg[0] != 0) {
964 logputs(LOG_LEVEL_FATAL, msg);
965 add_err_msg(pvar, msg);
966 }
967
968 if (!pvar->fatal_error) {
969 pvar->fatal_error = TRUE;
970
971 if (send_disconnect) {
972 SSH_notify_disconnecting(pvar, msg);
973 }
974 AUTH_notify_disconnecting(pvar);
975 HOSTS_notify_disconnecting(pvar);
976
977 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
978 pvar->socket, MAKELPARAM(FD_CLOSE,
979 (pvar->PWSAGetLastError) ()));
980 }
981 }
982
983 void logputs(int level, char *msg)
984 {
985 if (level <= pvar->settings.LogLevel) {
986 char buf[4096];
987 int file;
988
989 get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
990 file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
991 _S_IREAD | _S_IWRITE);
992
993 if (file >= 0) {
994 char *strtime = mctimelocal("%Y-%m-%d %H:%M:%S.%NZ", TRUE);
995 DWORD processid;
996 char tmp[26];
997
998 _write(file, strtime, strlen(strtime));
999 processid = GetCurrentProcessId();
1000 _snprintf_s(tmp, sizeof(tmp), _TRUNCATE, " [%lu] ",processid);
1001 _write(file, tmp, strlen(tmp));
1002 _write(file, msg, strlen(msg));
1003 _write(file, "\n", 1);
1004 _close(file);
1005 }
1006 }
1007 }
1008
1009 #if defined(_MSC_VER)
1010 void logprintf(int level, _Printf_format_string_ const char *fmt, ...)
1011 #else
1012 void logprintf(int level, const char *fmt, ...)
1013 #endif
1014 {
1015 char buff[4096];
1016 va_list params;
1017
1018 if (level <= pvar->settings.LogLevel) {
1019 va_start(params, fmt);
1020 vsnprintf_s(buff, sizeof(buff), _TRUNCATE, fmt, params);
1021 va_end(params);
1022
1023 logputs(level, buff);
1024 }
1025 }
1026
1027 static void format_line_hexdump(char *buf, int buflen, int addr, int *bytes, int byte_cnt)
1028 {
1029 int i, c;
1030 char tmp[128];
1031
1032 buf[0] = 0;
1033
1034 /* �������A�h���X�\�� */
1035 _snprintf_s(tmp, sizeof(tmp), _TRUNCATE, "%08X : ", addr);
1036 strncat_s(buf, buflen, tmp, _TRUNCATE);
1037
1038 /* �o�C�i���\���i4�o�C�g�������������}���j*/
1039 for (i = 0; i < byte_cnt; i++) {
1040 if (i > 0 && i % 4 == 0) {
1041 strncat_s(buf, buflen, " ", _TRUNCATE);
1042 }
1043
1044 _snprintf_s(tmp, sizeof(tmp), _TRUNCATE, "%02X", bytes[i]);
1045 strncat_s(buf, buflen, tmp, _TRUNCATE);
1046 }
1047
1048 /* ASCII�\���������������������� */
1049 _snprintf_s(tmp, sizeof(tmp), _TRUNCATE, " %*s%*s", (16 - byte_cnt) * 2 + 1, " ", (16 - byte_cnt + 3) / 4, " ");
1050 strncat_s(buf, buflen, tmp, _TRUNCATE);
1051
1052 /* ASCII�\�� */
1053 for (i = 0; i < byte_cnt; i++) {
1054 c = bytes[i];
1055 if (isprint(c)) {
1056 _snprintf_s(tmp, sizeof(tmp), _TRUNCATE, "%c", c);
1057 strncat_s(buf, buflen, tmp, _TRUNCATE);
1058 }
1059 else {
1060 strncat_s(buf, buflen, ".", _TRUNCATE);
1061 }
1062 }
1063
1064 //strncat_s(buf, buflen, "\n", _TRUNCATE);
1065 }
1066
1067 #if defined(_MSC_VER)
1068 void logprintf_hexdump(int level, const char *data, int len, _Printf_format_string_ const char *fmt, ...)
1069 #else
1070 void logprintf_hexdump(int level, const char *data, int len, const char *fmt, ...)
1071 #endif
1072 {
1073 char buff[4096];
1074 va_list params;
1075 int c, addr;
1076 int bytes[16], *ptr;
1077 int byte_cnt;
1078 int i;
1079
1080 if (level <= pvar->settings.LogLevel) {
1081 va_start(params, fmt);
1082 vsnprintf_s(buff, sizeof(buff), _TRUNCATE, fmt, params);
1083 va_end(params);
1084
1085 logputs(level, buff);
1086
1087 addr = 0;
1088 byte_cnt = 0;
1089 ptr = bytes;
1090 for (i = 0; i < len; i++) {
1091 c = data[i];
1092 *ptr++ = c & 0xff;
1093 byte_cnt++;
1094
1095 if (byte_cnt == 16) {
1096 format_line_hexdump(buff, sizeof(buff), addr, bytes, byte_cnt);
1097 logputs(level, buff);
1098
1099 addr += 16;
1100 byte_cnt = 0;
1101 ptr = bytes;
1102 }
1103 }
1104
1105 if (byte_cnt > 0) {
1106 format_line_hexdump(buff, sizeof(buff), addr, bytes, byte_cnt);
1107 logputs(level, buff);
1108 }
1109 }
1110 }
1111
1112 static void PASCAL TTXOpenTCP(TTXSockHooks *hooks)
1113 {
1114 if (pvar->settings.Enabled) {
1115 // TCPLocalEcho/TCPCRSend ������������ (maya 2007.4.25)
1116 pvar->origDisableTCPEchoCR = pvar->ts->DisableTCPEchoCR;
1117 pvar->ts->DisableTCPEchoCR = TRUE;
1118
1119 pvar->session_settings = pvar->settings;
1120
1121 logputs(LOG_LEVEL_VERBOSE, "---------------------------------------------------------------------");
1122 logputs(LOG_LEVEL_VERBOSE, "Initiating SSH session");
1123
1124 FWDUI_load_settings(pvar);
1125
1126 pvar->cv->TelAutoDetect = FALSE;
1127 /* This next line should not be needed because Tera Term's
1128 CommLib should find ts->Telnet == 0 ... but we'll do this
1129 just to be on the safe side. */
1130 pvar->cv->TelFlag = FALSE;
1131 pvar->cv->TelLineMode = FALSE;
1132
1133 pvar->Precv = *hooks->Precv;
1134 pvar->Psend = *hooks->Psend;
1135 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
1136 pvar->Pconnect = *hooks->Pconnect;
1137 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
1138
1139 *hooks->Precv = TTXrecv;
1140 *hooks->Psend = TTXsend;
1141 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
1142 *hooks->Pconnect = TTXconnect;
1143
1144 SSH_open(pvar);
1145 HOSTS_open(pvar);
1146 FWDUI_open(pvar);
1147
1148 // ������ myproposal �����f���������A�������O�����������B (2006.6.26 maya)
1149 SSH2_update_kex_myproposal(pvar);
1150 SSH2_update_host_key_myproposal(pvar);
1151 SSH2_update_cipher_myproposal(pvar);
1152 SSH2_update_hmac_myproposal(pvar);
1153 SSH2_update_compression_myproposal(pvar);
1154 }
1155 }
1156
1157 static void PASCAL TTXCloseTCP(TTXSockHooks *hooks)
1158 {
1159 if (pvar->session_settings.Enabled) {
1160 pvar->socket = INVALID_SOCKET;
1161
1162 logputs(LOG_LEVEL_VERBOSE, "Terminating SSH session...");
1163
1164 // �F���_�C�A���O���c�����������������B
1165 HOSTS_notify_closing_on_exit(pvar);
1166 AUTH_notify_closing_on_exit(pvar);
1167
1168 *hooks->Precv = pvar->Precv;
1169 *hooks->Psend = pvar->Psend;
1170 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
1171 *hooks->Pconnect = pvar->Pconnect;
1172
1173 pvar->ts->DisableTCPEchoCR = pvar->origDisableTCPEchoCR;
1174 }
1175
1176 uninit_TTSSH(pvar);
1177 init_TTSSH(pvar);
1178 }
1179
1180 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
1181 {
1182 for (; from <= to; from++) {
1183 EnableWindow(GetDlgItem(dlg, from), enabled);
1184 }
1185 }
1186
1187 // C-p/C-n/C-b/C-f/C-a/C-e ���T�|�[�g (2007.9.5 maya)
1188 // C-d/C-k ���T�|�[�g (2007.10.3 yutaka)
1189 // �h���b�v�_�E���������G�f�B�b�g�R���g���[����
1190 // �T�u�N���X�������������E�C���h�E�v���V�[�W��
1191 WNDPROC OrigHostnameEditProc; // Original window procedure
1192 LRESULT CALLBACK HostnameEditProc(HWND dlg, UINT msg,
1193 WPARAM wParam, LPARAM lParam)
1194 {
1195 HWND parent;
1196 int max, select, len;
1197 char *str, *orgstr;
1198
1199 switch (msg) {
1200 // �L�[�����������������m����
1201 case WM_KEYDOWN:
1202 if (GetKeyState(VK_CONTROL) < 0) {
1203 switch (wParam) {
1204 case 0x50: // Ctrl+p ... up
1205 parent = GetParent(dlg);
1206 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
1207 if (select > 0) {
1208 PostMessage(parent, CB_SETCURSEL, select - 1, 0);
1209 }
1210 return 0;
1211 case 0x4e: // Ctrl+n ... down
1212 parent = GetParent(dlg);
1213 max = SendMessage(parent, CB_GETCOUNT, 0, 0);
1214 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
1215 if (select < max - 1) {
1216 PostMessage(parent, CB_SETCURSEL, select + 1, 0);
1217 }
1218 return 0;
1219 case 0x42: // Ctrl+b ... left
1220 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
1221 PostMessage(dlg, EM_SETSEL, select-1, select-1);
1222 return 0;
1223 case 0x46: // Ctrl+f ... right
1224 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
1225 max = GetWindowTextLength(dlg) ;
1226 PostMessage(dlg, EM_SETSEL, select+1, select+1);
1227 return 0;
1228 case 0x41: // Ctrl+a ... home
1229 PostMessage(dlg, EM_SETSEL, 0, 0);
1230 return 0;
1231 case 0x45: // Ctrl+e ... end
1232 max = GetWindowTextLength(dlg) ;
1233 PostMessage(dlg, EM_SETSEL, max, max);
1234 return 0;
1235
1236 case 0x44: // Ctrl+d
1237 case 0x4b: // Ctrl+k
1238 case 0x55: // Ctrl+u
1239 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
1240 max = GetWindowTextLength(dlg);
1241 max++; // '\0'
1242 orgstr = str = malloc(max);
1243 if (str != NULL) {
1244 len = GetWindowText(dlg, str, max);
1245 if (select >= 0 && select < len) {
1246 if (wParam == 0x44) { // �J�[�\���z����������������������
1247 memmove(&str[select], &str[select + 1], len - select - 1);
1248 str[len - 1] = '\0';
1249
1250 } else if (wParam == 0x4b) { // �J�[�\�������s��������������
1251 str[select] = '\0';
1252
1253 }
1254 }
1255
1256 if (wParam == 0x55) { // �J�[�\����������������������
1257 if (select >= len) {
1258 str[0] = '\0';
1259 } else {
1260 str = &str[select];
1261 }
1262 select = 0;
1263 }
1264
1265 SetWindowText(dlg, str);
1266 SendMessage(dlg, EM_SETSEL, select, select);
1267 free(orgstr);
1268 return 0;
1269 }
1270 break;
1271 }
1272 }
1273 break;
1274
1275 // �����L�[��������������������������������������������
1276 case WM_CHAR:
1277 switch (wParam) {
1278 case 0x01:
1279 case 0x02:
1280 case 0x04:
1281 case 0x05:
1282 case 0x06:
1283 case 0x0b:
1284 case 0x0e:
1285 case 0x10:
1286 case 0x15:
1287 return 0;
1288 }
1289 }
1290
1291 return CallWindowProc(OrigHostnameEditProc, dlg, msg, wParam, lParam);
1292 }
1293
1294 static INT_PTR CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
1295 LPARAM lParam)
1296 {
1297 const static DlgTextInfo text_info[] = {
1298 { 0, "DLG_HOST_TITLE" },
1299 { IDC_HOSTNAMELABEL, "DLG_HOST_TCPIPHOST" },
1300 { IDC_HISTORY, "DLG_HOST_TCPIPHISTORY" },
1301 { IDC_SERVICELABEL, "DLG_HOST_TCPIPSERVICE" },
1302 { IDC_HOSTOTHER, "DLG_HOST_TCPIPOTHER" },
1303 { IDC_HOSTTCPPORTLABEL, "DLG_HOST_TCPIPPORT" },
1304 { IDC_SSH_VERSION_LABEL, "DLG_HOST_TCPIPSSHVERSION" },
1305 { IDC_HOSTTCPPROTOCOLLABEL, "DLG_HOST_TCPIPPROTOCOL" },
1306 { IDC_HOSTSERIAL, "DLG_HOST_SERIAL" },
1307 { IDC_HOSTCOMLABEL, "DLG_HOST_SERIALPORT" },
1308 { IDC_HOSTHELP, "DLG_HOST_HELP" },
1309 { IDOK, "BTN_OK" },
1310 { IDCANCEL, "BTN_CANCEL" },
1311 };
1312 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
1313 PGetHNRec GetHNRec;
1314 char EntName[128];
1315 char TempHost[HostNameMaxLength + 1];
1316 WORD i, j, w;
1317 WORD ComPortTable[MAXCOMPORT];
1318 static char *ComPortDesc[MAXCOMPORT];
1319 int comports;
1320 BOOL Ok;
1321 static HWND hwndHostname = NULL; // HOSTNAME dropdown
1322 static HWND hwndHostnameEdit = NULL; // Edit control on HOSTNAME dropdown
1323
1324 switch (msg) {
1325 case WM_INITDIALOG:
1326 GetHNRec = (PGetHNRec) lParam;
1327 SetWindowLongPtr(dlg, DWLP_USER, lParam);
1328
1329 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
1330
1331 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
1332 if (pvar->ts->HistoryList > 0) {
1333 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
1334 } else {
1335 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
1336 }
1337
1338 // �t�@�C�����������O�t���p�C�v�������ATCP/IP�����������B
1339 if (GetHNRec->PortType == IdFile ||
1340 GetHNRec->PortType == IdNamedPipe
1341 )
1342 GetHNRec->PortType = IdTCPIP;
1343
1344 strncpy_s(EntName, sizeof(EntName), "Host", _TRUNCATE);
1345
1346 i = 1;
1347 do {
1348 _snprintf_s(&EntName[4], sizeof(EntName)-4, _TRUNCATE, "%d", i);
1349 GetPrivateProfileString("Hosts", EntName, "",
1350 TempHost, sizeof(TempHost),
1351 GetHNRec->SetupFN);
1352 if (strlen(TempHost) > 0)
1353 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
1354 0, (LPARAM) TempHost);
1355 i++;
1356 } while (i <= MAXHOSTLIST);
1357
1358 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
1359 HostNameMaxLength - 1, 0);
1360
1361 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
1362
1363 // C-n/C-p ���������T�u�N���X�� (2007.9.4 maya)
1364 hwndHostname = GetDlgItem(dlg, IDC_HOSTNAME);
1365 hwndHostnameEdit = GetWindow(hwndHostname, GW_CHILD);
1366 OrigHostnameEditProc = (WNDPROC)GetWindowLongPtr(hwndHostnameEdit, GWLP_WNDPROC);
1367 SetWindowLongPtr(hwndHostnameEdit, GWLP_WNDPROC, (LONG_PTR)HostnameEditProc);
1368
1369 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1370 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1371 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1372 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1373 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1374 for (i = 0; ProtocolFamilyList[i]; ++i) {
1375 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1376 0, (LPARAM) ProtocolFamilyList[i]);
1377 }
1378 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1379 ProtocolFamilyMaxLength - 1, 0);
1380 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1381
1382 /////// SSH version
1383 for (i = 0; ssh_version[i]; ++i) {
1384 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1385 0, (LPARAM) ssh_version[i]);
1386 }
1387 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1388 NUM_ELEM(ssh_version) - 1, 0);
1389
1390 if (pvar->settings.ssh_protocol_version == 1) {
1391 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1392 } else {
1393 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1394 }
1395
1396 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1397 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1398 } else {
1399 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1400 }
1401 /////// SSH version
1402
1403
1404 j = 0;
1405 w = 1;
1406 if ((comports=DetectComPorts(ComPortTable, GetHNRec->MaxComPort, ComPortDesc)) >= 0) {
1407 for (i=0; i<comports; i++) {
1408 // MaxComPort ���z�����|�[�g���\��������
1409 if (ComPortTable[i] > GetHNRec->MaxComPort) {
1410 continue;
1411 }
1412
1413 // �g�p�����|�[�g���\��������
1414 if (CheckCOMFlag(ComPortTable[i]) == 1) {
1415 continue;
1416 }
1417
1418 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", ComPortTable[i]);
1419 if (ComPortDesc[i] != NULL) {
1420 strncat_s(EntName, sizeof(EntName), ": ", _TRUNCATE);
1421 strncat_s(EntName, sizeof(EntName), ComPortDesc[i], _TRUNCATE);
1422 }
1423 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1424 0, (LPARAM)EntName);
1425 j++;
1426 if (GetHNRec->ComPort == ComPortTable[i])
1427 w = j;
1428 }
1429
1430 } else {
1431 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1432 // �g�p�����|�[�g���\��������
1433 if (CheckCOMFlag(i) == 1) {
1434 continue;
1435 }
1436
1437 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", i);
1438 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1439 0, (LPARAM) EntName);
1440 j++;
1441 if (GetHNRec->ComPort == i)
1442 w = j;
1443 }
1444 }
1445
1446 if (j > 0)
1447 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1448 else { /* All com ports are already used */
1449 GetHNRec->PortType = IdTCPIP;
1450 enable_dlg_items(dlg, IDC_HOSTSERIAL, IDC_HOSTSERIAL, FALSE);
1451 }
1452
1453 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
1454 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
1455
1456 if (GetHNRec->PortType == IdTCPIP) {
1457 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1458
1459 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1460 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1461
1462 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // enabled
1463 }
1464 else {
1465 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1466 FALSE);
1467 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1468 IDC_HOSTTCPPROTOCOL, FALSE);
1469
1470 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1471 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1472
1473 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1474 }
1475
1476 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1477 if (GetHNRec->PortType == IdTCPIP) {
1478 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1479 SetFocus(hwnd);
1480 } else {
1481 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1482 SetFocus(hwnd);
1483 }
1484
1485 CenterWindow(dlg, GetParent(dlg));
1486
1487 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1488 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1489 // (2004.11.23 yutaka)
1490 return FALSE;
1491 //return TRUE;
1492
1493 case WM_COMMAND:
1494 switch (LOWORD(wParam)) {
1495 case IDOK:
1496 GetHNRec = (PGetHNRec) GetWindowLongPtr(dlg, DWLP_USER);
1497 if (GetHNRec != NULL) {
1498 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1499 char afstr[BUFSIZ];
1500 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1501 if (Ok) {
1502 GetHNRec->TCPPort = i;
1503 } else {
1504 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar,
1505 "The TCP port must be a number.");
1506 MessageBox(dlg, pvar->ts->UIMsg,
1507 "Tera Term", MB_OK | MB_ICONEXCLAMATION);
1508 return TRUE;
1509 }
1510 #define getaf(str) \
1511 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1512 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1513 memset(afstr, 0, sizeof(afstr));
1514 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1515 sizeof(afstr));
1516 GetHNRec->ProtocolFamily = getaf(afstr);
1517 GetHNRec->PortType = IdTCPIP;
1518 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1519 HostNameMaxLength);
1520 pvar->hostdlg_activated = TRUE;
1521 pvar->hostdlg_Enabled = FALSE;
1522 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1523 GetHNRec->Telnet = TRUE;
1524 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1525 pvar->hostdlg_Enabled = TRUE;
1526
1527 // check SSH protocol version
1528 memset(afstr, 0, sizeof(afstr));
1529 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1530 if (_stricmp(afstr, "SSH1") == 0) {
1531 pvar->settings.ssh_protocol_version = 1;
1532 } else {
1533 pvar->settings.ssh_protocol_version = 2;
1534 }
1535 }
1536 else { // IDC_HOSTOTHER
1537 GetHNRec->Telnet = FALSE;
1538 }
1539
1540 // host history check button
1541 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1542 pvar->ts->HistoryList = 1;
1543 } else {
1544 pvar->ts->HistoryList = 0;
1545 }
1546
1547 } else {
1548 GetHNRec->PortType = IdSerial;
1549 GetHNRec->HostName[0] = 0;
1550 memset(EntName, 0, sizeof(EntName));
1551 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1552 sizeof(EntName) - 1);
1553 if (strncmp(EntName, "COM", 3) == 0 && EntName[3] != '\0') {
1554 GetHNRec->ComPort = atoi(&EntName[3]);
1555 if (GetHNRec->ComPort > GetHNRec->MaxComPort)
1556 GetHNRec->ComPort = 1;
1557 } else {
1558 GetHNRec->ComPort = 1;
1559 }
1560 }
1561 }
1562 SetWindowLongPtr(hwndHostnameEdit, GWLP_WNDPROC, (LONG_PTR)OrigHostnameEditProc);
1563 EndDialog(dlg, 1);
1564 return TRUE;
1565
1566 case IDCANCEL:
1567 SetWindowLongPtr(hwndHostnameEdit, GWLP_WNDPROC, (LONG_PTR)OrigHostnameEditProc);
1568 EndDialog(dlg, 0);
1569 return TRUE;
1570
1571 case IDC_HOSTTCPIP:
1572 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1573 TRUE);
1574 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1575 IDC_HOSTTCPPROTOCOL, TRUE);
1576 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1577
1578 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1579 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1580 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1581 } else {
1582 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1583 }
1584
1585 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1586
1587 return TRUE;
1588
1589 case IDC_HOSTSERIAL:
1590 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1591 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1592 FALSE);
1593 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1594 IDC_HOSTTCPPROTOCOL, FALSE);
1595 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1596 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1597
1598 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1599
1600 return TRUE;
1601
1602 case IDC_HOSTSSH:
1603 enable_dlg_items(dlg, IDC_SSH_VERSION,
1604 IDC_SSH_VERSION, TRUE);
1605 goto hostssh_enabled;
1606
1607 case IDC_HOSTTELNET:
1608 case IDC_HOSTOTHER:
1609 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1610 hostssh_enabled:
1611
1612 GetHNRec = (PGetHNRec) GetWindowLongPtr(dlg, DWLP_USER);
1613
1614 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1615 if (GetHNRec != NULL)
1616 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1617 FALSE);
1618 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1619 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1620 }
1621 return TRUE;
1622
1623 case IDC_HOSTCOM:
1624 if(HIWORD(wParam) == CBN_DROPDOWN) {
1625 HWND hostcom = GetDlgItem(dlg, IDC_HOSTCOM);
1626 int count = SendMessage(hostcom, CB_GETCOUNT, 0, 0);
1627 int i, len, max_len = 0;
1628 char *lbl;
1629 HDC TmpDC = GetDC(hostcom);
1630 SIZE s;
1631 for (i=0; i<count; i++) {
1632 len = SendMessage(hostcom, CB_GETLBTEXTLEN, i, 0);
1633 lbl = (char *)calloc(len+1, sizeof(char));
1634 SendMessage(hostcom, CB_GETLBTEXT, i, (LPARAM)lbl);
1635 GetTextExtentPoint32(TmpDC, lbl, len, &s);
1636 if (s.cx > max_len)
1637 max_len = s.cx;
1638 free(lbl);
1639 }
1640 SendMessage(hostcom, CB_SETDROPPEDWIDTH,
1641 max_len + GetSystemMetrics(SM_CXVSCROLL), 0);
1642 }
1643 break;
1644
1645 case IDC_HOSTHELP:
1646 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, HlpFileNewConnection, 0);
1647 }
1648 }
1649 return FALSE;
1650 }
1651
1652 static void UTIL_SetDialogFont()
1653 {
1654 SetDialogFont(pvar->ts->DialogFontName, pvar->ts->DialogFontPoint, pvar->ts->DialogFontCharSet,
1655 pvar->ts->UILanguageFile, "TTSSH", "DLG_TAHOMA_FONT");
1656 }
1657
1658 static BOOL PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1659 {
1660 SetDialogFont(pvar->ts->DialogFontName, pvar->ts->DialogFontPoint, pvar->ts->DialogFontCharSet,
1661 pvar->ts->UILanguageFile, "TTSSH", "DLG_SYSTEM_FONT");
1662 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1663 parent, TTXHostDlg, (LPARAM)rec);
1664 }
1665
1666 static void PASCAL TTXGetUIHooks(TTXUIHooks *hooks)
1667 {
1668 *hooks->GetHostName = TTXGetHostName;
1669 }
1670
1671 static void PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1672 {
1673 (pvar->ReadIniFile) (fileName, ts);
1674 read_ssh_options(pvar, fileName);
1675 pvar->settings = *pvar->ts_SSH;
1676 logputs(LOG_LEVEL_VERBOSE, "Reading INI file");
1677 FWDUI_load_settings(pvar);
1678 }
1679
1680 static void PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1681 {
1682 (pvar->WriteIniFile) (fileName, ts);
1683 *pvar->ts_SSH = pvar->settings;
1684 clear_local_settings(pvar);
1685 logputs(LOG_LEVEL_VERBOSE, "Writing INI file");
1686 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1687 }
1688
1689 static void read_ssh_options_from_user_file(PTInstVar pvar,
1690 char *user_file_name)
1691 {
1692 if (user_file_name[0] == '.') {
1693 read_ssh_options(pvar, user_file_name);
1694 } else {
1695 char buf[1024];
1696
1697 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1698 read_ssh_options(pvar, buf);
1699 }
1700
1701 pvar->settings = *pvar->ts_SSH;
1702 FWDUI_load_settings(pvar);
1703 }
1704
1705 // Percent-encode������������src���f�R�[�h����dst���R�s�[�����B
1706 // dstlen��dst���T�C�Y�B�����������������������A�����������������������B
1707 static void percent_decode(char *dst, int dstlen, char *src) {
1708 if (src == NULL || dst == NULL || dstlen < 1) {
1709 return;
1710 }
1711
1712 while (*src != 0 && dstlen > 1) {
1713 if (*src == '%' && isxdigit(*(src+1)) && isxdigit(*(src+2))) {
1714 src++; *dst = (isalpha(*src) ? (*src|0x20) - 'a' + 10 : *src - '0') << 4;
1715 src++; *dst |= (isalpha(*src) ? (*src|0x20) - 'a' + 10 : *src - '0');
1716 src++; dst++;
1717 }
1718 else {
1719 *dst++ = *src++;
1720 }
1721 dstlen--;
1722 }
1723 *dst = 0;
1724 return;
1725 }
1726
1727 void add_forward_param(PTInstVar pvar, char *param)
1728 {
1729 if (pvar->settings.DefaultForwarding[0] == 0) {
1730 strncpy_s(pvar->settings.DefaultForwarding,
1731 sizeof(pvar->settings.DefaultForwarding),
1732 param, _TRUNCATE);
1733 } else {
1734 strncat_s(pvar->settings.DefaultForwarding,
1735 sizeof(pvar->settings.DefaultForwarding),
1736 ";", _TRUNCATE);
1737 strncat_s(pvar->settings.DefaultForwarding,
1738 sizeof(pvar->settings.DefaultForwarding),
1739 param, _TRUNCATE);
1740 }
1741 }
1742
1743 static void PASCAL TTXParseParam(PCHAR param, PTTSet ts, PCHAR DDETopic) {
1744 int param_len=strlen(param);
1745 int opt_len = param_len+1;
1746 char *option = (char *)calloc(opt_len, sizeof(char));
1747 char *option2 = (char *)calloc(opt_len, sizeof(char));
1748 int action;
1749 PCHAR start, cur, next;
1750 size_t i;
1751
1752 if (pvar->hostdlg_activated) {
1753 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1754 }
1755
1756 /* the first term shuld be executable filename of Tera Term */
1757 start = GetParam(option, opt_len, param);
1758
1759 cur = start;
1760 while (next = GetParam(option, opt_len, cur)) {
1761 DequoteParam(option, opt_len, option);
1762 action = OPTION_NONE;
1763
1764 if ((option[0] == '-' || option[0] == '/')) {
1765 if (MATCH_STR(option + 1, "ssh") == 0) {
1766 if (MATCH_STR(option + 4, "-f=") == 0) {
1767 strncpy_s(option2, opt_len, option + 7, _TRUNCATE);
1768 read_ssh_options_from_user_file(pvar, option2);
1769 action = OPTION_CLEAR;
1770 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1771 strncpy_s(option2, opt_len, option + 13, _TRUNCATE);
1772 read_ssh_options_from_user_file(pvar, option2);
1773 DeleteFile(option2);
1774 action = OPTION_CLEAR;
1775 }
1776
1777 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1778 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1779 strncpy_s(option2, opt_len, option + 3, _TRUNCATE);
1780 read_ssh_options_from_user_file(pvar, option2);
1781 // Tera Term���������������K�v������������������
1782 }
1783 }
1784
1785 switch (action) {
1786 case OPTION_CLEAR:
1787 memset(cur, ' ', next-cur);
1788 break;
1789 case OPTION_REPLACE:
1790 memset(cur, ' ', next-cur);
1791 memcpy(cur+1, option, strlen(option));
1792 break;
1793 }
1794
1795 cur = next;
1796 }
1797
1798 cur = start;
1799 while (next = GetParam(option, opt_len, cur)) {
1800 DequoteParam(option, opt_len, option);
1801 action = OPTION_NONE;
1802
1803 if ((option[0] == '-' || option[0] == '/')) {
1804 action = OPTION_CLEAR;
1805 if (MATCH_STR(option + 1, "ssh") == 0) {
1806 if (option[4] == 0) {
1807 pvar->settings.Enabled = 1;
1808 } else if (MATCH_STR(option + 4, "-L") == 0 ||
1809 MATCH_STR(option + 4, "-R") == 0 ||
1810 MATCH_STR(option + 4, "-D") == 0) {
1811 char *p = option + 5;
1812 option2[0] = *p;
1813 i = 1;
1814 while (*++p) {
1815 if (*p == ';' || *p == ',') {
1816 option2[i] = 0;
1817 add_forward_param(pvar, option2);
1818 i = 1;
1819 }
1820 else {
1821 option2[i++] = *p;
1822 }
1823 }
1824 if (i > 1) {
1825 option2[i] = 0;
1826 add_forward_param(pvar, option2);
1827 }
1828 } else if (MATCH_STR(option + 4, "-X") == 0) {
1829 add_forward_param(pvar, "X");
1830 if (option+6 != 0) {
1831 strncpy_s(pvar->settings.X11Display,
1832 sizeof(pvar->settings.X11Display),
1833 option + 6, _TRUNCATE);
1834 }
1835 } else if (strcmp(option + 4, "-v") == 0) {
1836 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1837 } else if (_stricmp(option + 4, "-autologin") == 0 ||
1838 _stricmp(option + 4, "-autologon") == 0) {
1839 pvar->settings.TryDefaultAuth = TRUE;
1840 } else if (MATCH_STR_I(option + 4, "-agentconfirm=") == 0) {
1841 if ((_stricmp(option+18, "off") == 0) ||
1842 (_stricmp(option+18, "no") == 0) ||
1843 (_stricmp(option+18, "false") == 0) ||
1844 (_stricmp(option+18, "0") == 0) ||
1845 (_stricmp(option+18, "n") == 0)) {
1846 pvar->settings.ForwardAgentConfirm = 0;
1847 }
1848 else {
1849 pvar->settings.ForwardAgentConfirm = 1;
1850 }
1851 } else if (strcmp(option + 4, "-a") == 0) {
1852 pvar->settings.ForwardAgent = FALSE;
1853 } else if (strcmp(option + 4, "-A") == 0) {
1854 pvar->settings.ForwardAgent = TRUE;
1855
1856 } else if (MATCH_STR(option + 4, "-C=") == 0) {
1857 pvar->settings.CompressionLevel = atoi(option+7);
1858 if (pvar->settings.CompressionLevel < 0) {
1859 pvar->settings.CompressionLevel = 0;
1860 }
1861 else if (pvar->settings.CompressionLevel > 9) {
1862 pvar->settings.CompressionLevel = 9;
1863 }
1864 } else if (strcmp(option + 4, "-C") == 0) {
1865 pvar->settings.CompressionLevel = 6;
1866 } else if (strcmp(option + 4, "-c") == 0) {
1867 pvar->settings.CompressionLevel = 0;
1868 } else if (MATCH_STR_I(option + 4, "-icon=") == 0) {
1869 if ((_stricmp(option+10, "old") == 0) ||
1870 (_stricmp(option+10, "yellow") == 0) ||
1871 (_stricmp(option+10, "securett_yellow") == 0)) {
1872 pvar->settings.IconID = IDI_SECURETT_YELLOW;
1873 }
1874 else if ((_stricmp(option+10, "green") == 0) ||
1875 (_stricmp(option+10, "securett_green") == 0)) {
1876 pvar->settings.IconID = IDI_SECURETT_GREEN;
1877 }
1878 else {
1879 pvar->settings.IconID = IDI_SECURETT;
1880 }
1881 } else if (MATCH_STR(option + 4, "-subsystem=") == 0) {
1882 pvar->use_subsystem = TRUE;
1883 strncpy_s(pvar->subsystem_name,
1884 sizeof(pvar->subsystem_name),
1885 option + 15, _TRUNCATE);
1886 } else if (strcmp(option + 4, "-N") == 0) {
1887 pvar->nosession = TRUE;
1888
1889 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1890 } else if (strcmp(option + 4, "1") == 0) {
1891 pvar->settings.Enabled = 1;
1892 pvar->settings.ssh_protocol_version = 1;
1893 } else if (strcmp(option + 4, "2") == 0) {
1894 pvar->settings.Enabled = 1;
1895 pvar->settings.ssh_protocol_version = 2;
1896
1897 } else {
1898 char buf[1024];
1899
1900 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar,
1901 "Unrecognized command-line option: %s");
1902 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, option);
1903
1904 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1905 }
1906
1907 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1908 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1909 if (strcmp(option + 3, "2") == 0) {
1910 pvar->settings.Enabled = 1;
1911 // /t=2��ttssh�������g������������
1912 } else {
1913 pvar->settings.Enabled = 0;
1914 action = OPTION_NONE; // Tera Term������������������������
1915 }
1916
1917 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1918 } else if (strcmp(option + 1, "1") == 0) {
1919 // command line: /ssh /1 is SSH1 only
1920 pvar->settings.ssh_protocol_version = 1;
1921
1922 } else if (strcmp(option + 1, "2") == 0) {
1923 // command line: /ssh /2 is SSH2 & SSH1
1924 pvar->settings.ssh_protocol_version = 2;
1925
1926 } else if (strcmp(option + 1, "nossh") == 0) {
1927 // '/nossh' �I�v�V�����������B
1928 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1929 // �����������������B(2004.10.11 yutaka)
1930 pvar->settings.Enabled = 0;
1931
1932 } else if (strcmp(option + 1, "telnet") == 0) {
1933 // '/telnet' ���w�������������������� '/nossh' ��������
1934 // SSH������������ (2006.9.16 maya)
1935 pvar->settings.Enabled = 0;
1936 // Tera Term �� Telnet �t���O���t����
1937 pvar->ts->Telnet = 1;
1938
1939 } else if (MATCH_STR(option + 1, "auth=") == 0) {
1940 // SSH2�������O�C���I�v�V����������
1941 //
1942 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1943 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1944 // EXAMPLE: /ssh /auth=password /user=nike /passwd="a b""c" ; �p�X���[�h: �ua b"c�v
1945 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1946 // NOTICE: �p�X���[�h���p�X���������Z�~�R���������������������_�u���N�H�[�g " ������
1947 // �p�X���[�h���_�u���N�H�[�g�����������������A�������_�u���N�H�[�g "" ���u��������
1948 //
1949 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1950
1951 if (_stricmp(option + 6, "password") == 0) { // �p�X���[�h
1952 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1953 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1954
1955 } else if (_stricmp(option + 6, "keyboard-interactive") == 0) { // keyboard-interactive�F��
1956 //pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
1957 pvar->ssh2_authmethod = SSH_AUTH_TIS;
1958
1959 } else if (_stricmp(option + 6, "challenge") == 0) { // keyboard-interactive�F��
1960 //pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
1961 pvar->ssh2_authmethod = SSH_AUTH_TIS;
1962
1963 } else if (_stricmp(option + 6, "publickey") == 0) { // ���J���F��
1964 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1965 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1966
1967 } else if (_stricmp(option + 6, "pageant") == 0) { // ���J���F�� by Pageant
1968 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1969 pvar->ssh2_authmethod = SSH_AUTH_PAGEANT;
1970
1971 } else {
1972 // TODO:
1973 }
1974
1975 } else if (MATCH_STR(option + 1, "user=") == 0) {
1976 _snprintf_s(pvar->ssh2_username, sizeof(pvar->ssh2_username), _TRUNCATE, "%s", option+6);
1977
1978 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1979 _snprintf_s(pvar->ssh2_password, sizeof(pvar->ssh2_password), _TRUNCATE, "%s", option+8);
1980
1981 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1982 _snprintf_s(pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile), _TRUNCATE, "%s", option+9);
1983
1984 } else if (strcmp(option + 1, "ask4passwd") == 0) {
1985 // �p�X���[�h������ (2006.9.18 maya)
1986 pvar->ask4passwd = 1;
1987
1988 } else if (strcmp(option + 1, "nosecuritywarning") == 0) {
1989 // known_hosts�`�F�b�N���������B���Y�I�v�V�������g�����A�Z�L�����e�B������������
1990 // �����A�B���I�v�V���������������B
1991 // (2009.10.4 yutaka)
1992 pvar->nocheck_known_hosts = TRUE;
1993
1994 }
1995 else { // Other (not ttssh) option
1996 action = OPTION_NONE; // ttssh���I�v�V������������������������
1997 }
1998
1999 // �p�X���[�h�������������������O�C��������������
2000 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
2001 if (pvar->ask4passwd == 1) {
2002 pvar->ssh2_autologin = 0;
2003 }
2004
2005 }
2006 else if ((MATCH_STR_I(option, "ssh://") == 0) ||
2007 (MATCH_STR_I(option, "ssh1://") == 0) ||
2008 (MATCH_STR_I(option, "ssh2://") == 0) ||
2009 (MATCH_STR_I(option, "slogin://") == 0) ||
2010 (MATCH_STR_I(option, "slogin1://") == 0) ||
2011 (MATCH_STR_I(option, "slogin2://") == 0)) {
2012 //
2013 // ssh://user@host/ ����URL�`�����T�|�[�g
2014 // ���{�I�������� telnet:// URL��������
2015 //
2016 // �Q�l:
2017 // RFC3986: Uniform Resource Identifier (URI): Generic Syntax
2018 // RFC4248: The telnet URI Scheme
2019 //
2020 char *p, *p2, *p3;
2021 int optlen, hostlen;
2022
2023 optlen = strlen(option);
2024
2025 // ������':'���O�����������������������A������ssh�v���g�R���o�[�W������������
2026 p = _mbschr(option, ':');
2027 switch (*(p-1)) {
2028 case '1':
2029 pvar->settings.ssh_protocol_version = 1;
2030 break;
2031 case '2':
2032 pvar->settings.ssh_protocol_version = 2;
2033 break;
2034 }
2035
2036 // authority part �����|�C���^������
2037 p += 3;
2038
2039 // path part ������������
2040 if ((p2 = _mbschr(p, '/')) != NULL) {
2041 *p2 = 0;
2042 }
2043
2044 // '@'�������������A���������O�����[�U����
2045 if ((p2 = _mbschr(p, '@')) != NULL) {
2046 *p2 = 0;
2047 // ':'���~���p�X���[�h
2048 if ((p3 = _mbschr(p, ':')) != NULL) {
2049 *p3 = 0;
2050 percent_decode(pvar->ssh2_password, sizeof(pvar->ssh2_password), p3 + 1);
2051 }
2052 percent_decode(pvar->ssh2_username, sizeof(pvar->ssh2_username), p);
2053 // p �� host part ������('@'����������)����������������
2054 p = p2 + 1;
2055 }
2056
2057 // host part �� option �����������������Ascheme part ������
2058 // port�w����������������port���������������������m��������������
2059 hostlen = strlen(p);
2060 memmove_s(option, optlen, p, hostlen);
2061 option[hostlen] = 0;
2062
2063 // �|�[�g�w������������":22"������
2064 if (option[0] == '[' && option[hostlen-1] == ']' || // IPv6 raw address without port
2065 option[0] != '[' && _mbschr(option, ':') == NULL) { // hostname or IPv4 raw address without port
2066 memcpy_s(option+hostlen, optlen-hostlen, ":22", 3);
2067 hostlen += 3;
2068 }
2069
2070 // �|�[�g�w�����������������X�y�[�X������
2071 memset(option+hostlen, ' ', optlen-hostlen);
2072
2073 pvar->settings.Enabled = 1;
2074
2075 action = OPTION_REPLACE;
2076 }
2077 else if (_mbschr(option, '@') != NULL) {
2078 //
2079 // user@host �`�����T�|�[�g
2080 // ����������ssh�������T�|�[�g�����A���[�U����ttssh���������B
2081 // (ssh�������O -- ttssh�������W������������)
2082 // �����I��telnet authentication option���T�|�[�g��������
2083 // Tera Term�{�����������������������\���B
2084 //
2085 char *p;
2086 p = _mbschr(option, '@');
2087 *p = 0;
2088
2089 strncpy_s(pvar->ssh2_username, sizeof(pvar->ssh2_username), option, _TRUNCATE);
2090
2091 // ���[�U���������X�y�[�X�������B
2092 // ������TTX��Tera Term�{�������������������X�y�[�X�����������������A
2093 // �z�X�g�����������l�����K�v�������B
2094 memset(option, ' ', p-option+1);
2095
2096 action = OPTION_REPLACE;
2097 }
2098
2099
2100 switch (action) {
2101 case OPTION_CLEAR:
2102 memset(cur, ' ', next-cur);
2103 break;
2104 case OPTION_REPLACE:
2105 memset(cur, ' ', next-cur);
2106 memcpy(cur+1, option, strlen(option));
2107 break;
2108 }
2109
2110 cur = next;
2111 }
2112
2113 free(option);
2114
2115 FWDUI_load_settings(pvar);
2116
2117 (pvar->ParseParam) (param, ts, DDETopic);
2118 }
2119
2120 static void PASCAL TTXGetSetupHooks(TTXSetupHooks *hooks)
2121 {
2122 pvar->ReadIniFile = *hooks->ReadIniFile;
2123 pvar->WriteIniFile = *hooks->WriteIniFile;
2124 pvar->ParseParam = *hooks->ParseParam;
2125
2126 *hooks->ReadIniFile = TTXReadINIFile;
2127 *hooks->WriteIniFile = TTXWriteINIFile;
2128 *hooks->ParseParam = TTXParseParam;
2129 }
2130
2131 static void PASCAL TTXSetWinSize(int rows, int cols)
2132 {
2133 SSH_notify_win_size(pvar, cols, rows);
2134 }
2135
2136 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
2137 WORD newItemID, char *text)
2138 {
2139 int i, j;
2140
2141 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
2142 HMENU submenu = GetSubMenu(menu, i);
2143
2144 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
2145 if (GetMenuItemID(submenu, j) == beforeItemID) {
2146 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID, text);
2147 return;
2148 }
2149 }
2150 }
2151 }
2152
2153 #define GetFileMenu(menu) GetSubMenuByChildID(menu, 50110) // ID_FILE_NEWCONNECTION
2154 #define GetEditMenu(menu) GetSubMenuByChildID(menu, 50210) // ID_EDIT_COPY2
2155 #define GetSetupMenu(menu) GetSubMenuByChildID(menu, 50310) // ID_SETUP_TERMINAL
2156 #define GetControlMenu(menu) GetSubMenuByChildID(menu, 50410) // ID_CONTROL_RESETTERMINAL
2157 #define GetHelpMenu(menu) GetSubMenuByChildID(menu, 50990) // ID_HELP_ABOUT
2158
2159 HMENU GetSubMenuByChildID(HMENU menu, UINT id) {
2160 int i, j, items, subitems, cur_id;
2161 HMENU m;
2162
2163 items = GetMenuItemCount(menu);
2164
2165 for (i=0; i<items; i++) {
2166 if (m = GetSubMenu(menu, i)) {
2167 subitems = GetMenuItemCount(m);
2168 for (j=0; j<subitems; j++) {
2169 cur_id = GetMenuItemID(m, j);
2170 if (cur_id == id) {
2171 return m;
2172 }
2173 }
2174 }
2175 }
2176 return NULL;
2177 }
2178
2179 static void PASCAL TTXModifyMenu(HMENU menu)
2180 {
2181 pvar->FileMenu = GetFileMenu(menu);
2182
2183 /* inserts before ID_HELP_ABOUT */
2184 UTIL_get_lang_msg("MENU_ABOUT", pvar, "About &TTSSH...");
2185 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
2186
2187 /* inserts before ID_SETUP_TCPIP */
2188 UTIL_get_lang_msg("MENU_SSH", pvar, "SS&H...");
2189 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
2190 /* inserts before ID_SETUP_TCPIP */
2191 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar, "SSH &Authentication...");
2192 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
2193 /* inserts before ID_SETUP_TCPIP */
2194 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar, "SSH F&orwarding...");
2195 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
2196 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar, "SSH KeyGe&nerator...");
2197 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
2198
2199 /* inserts before ID_FILE_CHANGEDIR */
2200 UTIL_get_lang_msg("MENU_SSH_SCP", pvar, "SS&H SCP...");
2201 insertMenuBeforeItem(menu, 50170, MF_GRAYED, ID_SSHSCPMENU, pvar->ts->UIMsg);
2202 }
2203
2204 static void PASCAL TTXModifyPopupMenu(HMENU menu) {
2205 if (menu == pvar->FileMenu) {
2206 if (pvar->cv->Ready && pvar->socket != INVALID_SOCKET)
2207 EnableMenuItem(menu, ID_SSHSCPMENU, MF_BYCOMMAND | MF_ENABLED);
2208 else
2209 EnableMenuItem(menu, ID_SSHSCPMENU, MF_BYCOMMAND | MF_GRAYED);
2210 }
2211 }
2212
2213 static void about_dlg_set_abouttext(PTInstVar pvar, HWND dlg, digest_algorithm dgst_alg)
2214 {
2215 char buf[1024], buf2[2048];
2216 char *fp = NULL;
2217
2218 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
2219 if (pvar->socket != INVALID_SOCKET) {
2220 buf2[0] = '\0';
2221
2222 if (SSHv1(pvar)) {
2223 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID:");
2224 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2225 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2226 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
2227 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2228 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2229
2230 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol:");
2231 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2232 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2233 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
2234 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2235 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2236
2237 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption:");
2238 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2239 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2240 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
2241 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2242 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2243
2244 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys:");
2245 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2246 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2247 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
2248 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2249 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2250
2251 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication:");
2252 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2253 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2254 AUTH_get_auth_info(pvar, buf, sizeof(buf));
2255 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2256 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2257
2258 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression:");
2259 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2260 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2261 SSH_get_compression_info(pvar, buf, sizeof(buf));
2262 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2263 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2264
2265 } else { // SSH2
2266 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID:");
2267 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2268 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2269 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
2270 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2271 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2272
2273 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar, "Client ID:");
2274 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2275 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2276 strncat_s(buf2, sizeof(buf2), pvar->client_version_string, _TRUNCATE);
2277 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2278
2279 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol:");
2280 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2281 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2282 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
2283 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2284 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2285
2286 UTIL_get_lang_msg("DLG_ABOUT_KEX", pvar, "Key exchange algorithm:");
2287 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2288 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2289 strncat_s(buf2, sizeof(buf2), get_kex_algorithm_name(pvar->kex_type), _TRUNCATE);
2290 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2291
2292 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key:");
2293 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2294 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2295 strncat_s(buf2, sizeof(buf2), get_ssh_keytype_name(pvar->hostkey_type), _TRUNCATE);
2296 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2297
2298 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption:");
2299 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2300 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2301 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
2302 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2303 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2304
2305 UTIL_get_lang_msg("DLG_ABOUT_MAC", pvar, "MAC algorithm:");
2306 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2307 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2308 SSH_get_mac_info(pvar, buf, sizeof(buf));
2309 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2310 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2311
2312 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
2313 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar, "Delayed Compression:");
2314 }
2315 else {
2316 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression:");
2317 }
2318 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2319 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2320 SSH_get_compression_info(pvar, buf, sizeof(buf));
2321 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2322 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2323
2324 UTIL_get_lang_msg("DLG_ABOUT_KEXKEY", pvar, "Key exchange keys:");
2325 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2326 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2327 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
2328 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2329 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2330
2331 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication:");
2332 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2333 strncat_s(buf2, sizeof(buf2), " ", _TRUNCATE);
2334 AUTH_get_auth_info(pvar, buf, sizeof(buf));
2335 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2336 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2337 }
2338
2339 // �z�X�g���J����fingerprint���\�������B
2340 // (2014.5.1 yutaka)
2341 UTIL_get_lang_msg("DLG_ABOUT_FINGERPRINT", pvar, "Host key's fingerprint:");
2342 strncat_s(buf2, sizeof(buf2), pvar->ts->UIMsg, _TRUNCATE);
2343 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2344
2345 switch (dgst_alg) {
2346 case SSH_DIGEST_MD5:
2347 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_HEX, dgst_alg);
2348 strncat_s(buf2, sizeof(buf2), fp, _TRUNCATE);
2349 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2350 free(fp);
2351 break;
2352 case SSH_DIGEST_SHA256:
2353 default:
2354 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_BASE64, SSH_DIGEST_SHA256);
2355 if (fp != NULL) {
2356 strncat_s(buf2, sizeof(buf2), fp, _TRUNCATE);
2357 free(fp);
2358 }
2359 strncat_s(buf2, sizeof(buf2), "\r\n", _TRUNCATE);
2360 break;
2361 }
2362
2363 fp = key_fingerprint(&pvar->hosts_state.hostkey, SSH_FP_RANDOMART, dgst_alg);
2364 strncat_s(buf2, sizeof(buf2), fp, _TRUNCATE);
2365 free(fp);
2366
2367 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETTEXT, 0, (LPARAM)(char *)buf2);
2368 }
2369 }
2370
2371 static void init_about_dlg(PTInstVar pvar, HWND dlg)
2372 {
2373 char buf[1024];
2374 const static DlgTextInfo text_info[] = {
2375 { 0, "DLG_ABOUT_TITLE" },
2376 { IDC_FP_HASH_ALG, "DLG_ABOUT_FP_HASH_ALGORITHM" },
2377 { IDOK, "BTN_OK" },
2378 };
2379 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
2380
2381 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
2382 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2383 "TTSSH\r\nTera Term Secure Shell extension, %d.%d\r\nCompatible with SSH protocol version 1.5 and 2.0", TTSSH_VERSION_MAJOR, TTSSH_VERSION_MINOR);
2384 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
2385
2386 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
2387 // ���������� (2005.5.11 yutaka)
2388 // OPENSSL_VERSION_TEXT �}�N�����`���������A�������g�����o�[�W���������������B(2013.11.24 yutaka)
2389 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)SSLeay_version(SSLEAY_VERSION));
2390
2391 // zlib���o�[�W�������������� (2005.5.11 yutaka)
2392 #ifdef ZLIB_VERSION
2393 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
2394 #else
2395 _snprintf(buf, sizeof(buf), "ZLib Unknown");
2396 #endif
2397 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
2398
2399 // PuTTY���o�[�W�������������� (2011.7.26 yutaka)
2400 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "PuTTY %s", putty_get_version());
2401 SendMessage(GetDlgItem(dlg, IDC_PUTTY_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
2402 }
2403
2404 #if 0
2405 // WM_MOUSEWHEEL �� winuser.h �w�b�_���������������������A#define _WIN32_WINNT 0x0400 ���������������������F�������������B
2406 #define WM_MOUSEWHEEL 0x020A1
2407 #define WHEEL_DELTA 120
2408 #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
2409 #define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
2410 #endif
2411
2412 static WNDPROC g_defAboutDlgEditWndProc; // Edit Control���T�u�N���X���p
2413 static int g_deltaSumAboutDlg = 0; // �}�E�X�z�C�[����Delta�����p
2414
2415 static LRESULT CALLBACK AboutDlgEditWindowProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
2416 {
2417 WORD keys;
2418 short delta;
2419 BOOL page;
2420
2421 switch (msg) {
2422 case WM_KEYDOWN:
2423 // Edit control���� CTRL+A �������������A�e�L�X�g���S�I�������B
2424 if (wp == 'A' && GetKeyState(VK_CONTROL) < 0) {
2425 PostMessage(hWnd, EM_SETSEL, 0, -1);
2426 return 0;
2427 }
2428 break;
2429
2430 case WM_MOUSEWHEEL:
2431 // CTRLorSHIFT + �}�E�X�z�C�[���������A���X�N���[���������B
2432 keys = GET_KEYSTATE_WPARAM(wp);
2433 delta = GET_WHEEL_DELTA_WPARAM(wp);
2434 page = keys & (MK_CONTROL | MK_SHIFT);
2435
2436 if (page == 0)
2437 break;
2438
2439 g_deltaSumAboutDlg += delta;
2440
2441 if (g_deltaSumAboutDlg >= WHEEL_DELTA) {
2442 g_deltaSumAboutDlg -= WHEEL_DELTA;
2443 SendMessage(hWnd, WM_HSCROLL, SB_PAGELEFT , 0);
2444 } else if (g_deltaSumAboutDlg <= -WHEEL_DELTA) {
2445 g_deltaSumAboutDlg += WHEEL_DELTA;
2446 SendMessage(hWnd, WM_HSCROLL, SB_PAGERIGHT, 0);
2447 }
2448
2449 break;
2450 }
2451 return CallWindowProc(g_defAboutDlgEditWndProc, hWnd, msg, wp, lp);
2452 }
2453
2454 static INT_PTR CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
2455 LPARAM lParam)
2456 {
2457 static HFONT DlgAboutTextFont;
2458
2459 switch (msg) {
2460 case WM_INITDIALOG:
2461 // Edit control�������t�H���g���\�������������A���������������t�H���g���Z�b�g�����B
2462 // (2014.5.5. yutaka)
2463 DlgAboutTextFont = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2464 if (DlgAboutTextFont != NULL) {
2465 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutTextFont, MAKELPARAM(TRUE,0));
2466 }
2467
2468 // �A�C�R�������I���Z�b�g
2469 {
2470 int fuLoad = LR_DEFAULTCOLOR;
2471 HICON hicon;
2472
2473 if (IsWindowsNT4()) {
2474 fuLoad = LR_VGACOLOR;
2475 }
2476
2477 hicon = LoadImage(hInst, MAKEINTRESOURCE(pvar->settings.IconID),
2478 IMAGE_ICON, 32, 32, fuLoad);
2479 SendDlgItemMessage(dlg, IDC_TTSSH_ICON, STM_SETICON, (WPARAM)hicon, 0);
2480 }
2481
2482 init_about_dlg(pvar, dlg);
2483 CheckDlgButton(dlg, IDC_FP_HASH_ALG_SHA256, TRUE);
2484 about_dlg_set_abouttext(pvar, dlg, SSH_DIGEST_SHA256);
2485 SetFocus(GetDlgItem(dlg, IDOK));
2486
2487 // Edit control���T�u�N���X�������B
2488 g_deltaSumAboutDlg = 0;
2489 g_defAboutDlgEditWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(dlg, IDC_ABOUTTEXT), GWLP_WNDPROC, (LONG_PTR)AboutDlgEditWindowProc);
2490
2491 CenterWindow(dlg, GetParent(dlg));
2492
2493 return FALSE;
2494
2495 case WM_COMMAND:
2496 switch (LOWORD(wParam)) {
2497 case IDOK:
2498 EndDialog(dlg, 1);
2499 return TRUE;
2500 case IDCANCEL: /* there isn't a cancel button, but other Windows
2501 UI things can send this message */
2502 EndDialog(dlg, 0);
2503 return TRUE;
2504 case IDC_FP_HASH_ALG_MD5:
2505 about_dlg_set_abouttext(pvar, dlg, SSH_DIGEST_MD5);
2506 return TRUE;
2507 case IDC_FP_HASH_ALG_SHA256:
2508 about_dlg_set_abouttext(pvar, dlg, SSH_DIGEST_SHA256);
2509 return TRUE;
2510 }
2511 break;
2512
2513 case WM_DESTROY:
2514 if (DlgAboutTextFont != NULL) {
2515 DeleteObject(DlgAboutTextFont);
2516 DlgAboutTextFont = NULL;
2517 }
2518 break;
2519
2520 case WM_DPICHANGED:
2521 if (DlgAboutTextFont != NULL) {
2522 DeleteObject(DlgAboutTextFont);
2523 }
2524 DlgAboutTextFont = UTIL_get_lang_fixedfont(dlg, pvar->ts->UILanguageFile);
2525 if (DlgAboutTextFont != NULL) {
2526 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutTextFont, MAKELPARAM(TRUE,0));
2527 }
2528 return FALSE;
2529 }
2530
2531 return FALSE;
2532 }
2533
2534 static char *get_cipher_name(int cipher)
2535 {
2536 switch (cipher) {
2537 case SSH_CIPHER_NONE:
2538 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
2539 "<ciphers below this line are disabled>");
2540 return pvar->ts->UIMsg;
2541 case SSH_CIPHER_3DES:
2542 return "3DES(SSH1)";
2543 case SSH_CIPHER_DES:
2544 return "DES(SSH1)";
2545 case SSH_CIPHER_BLOWFISH:
2546 return "Blowfish(SSH1)";
2547
2548 // for SSH2(yutaka)
2549 case SSH2_CIPHER_AES128_CBC:
2550 return "aes128-cbc(SSH2)";
2551 case SSH2_CIPHER_AES192_CBC:
2552 return "aes192-cbc(SSH2)";
2553 case SSH2_CIPHER_AES256_CBC:
2554 return "aes256-cbc(SSH2)";
2555 case SSH2_CIPHER_3DES_CBC:
2556 return "3des-cbc(SSH2)";
2557 case SSH2_CIPHER_BLOWFISH_CBC:
2558 return "blowfish-cbc(SSH2)";
2559 case SSH2_CIPHER_AES128_CTR:
2560 return "aes128-ctr(SSH2)";
2561 case SSH2_CIPHER_AES192_CTR:
2562 return "aes192-ctr(SSH2)";
2563 case SSH2_CIPHER_AES256_CTR:
2564 return "aes256-ctr(SSH2)";
2565 case SSH2_CIPHER_ARCFOUR:
2566 return "arcfour(SSH2)";
2567 case SSH2_CIPHER_ARCFOUR128:
2568 return "arcfour128(SSH2)";
2569 case SSH2_CIPHER_ARCFOUR256:
2570 return "arcfour256(SSH2)";
2571 case SSH2_CIPHER_CAST128_CBC:
2572 return "cast128-cbc(SSH2)";
2573 case SSH2_CIPHER_3DES_CTR:
2574 return "3des-ctr(SSH2)";
2575 case SSH2_CIPHER_BLOWFISH_CTR:
2576 return "blowfish-ctr(SSH2)";
2577 case SSH2_CIPHER_CAST128_CTR:
2578 return "cast128-ctr(SSH2)";
2579 case SSH2_CIPHER_CAMELLIA128_CBC:
2580 return "camellia128-cbc(SSH2)";
2581 case SSH2_CIPHER_CAMELLIA192_CBC:
2582 return "camellia192-cbc(SSH2)";
2583 case SSH2_CIPHER_CAMELLIA256_CBC:
2584 return "camellia256-cbc(SSH2)";
2585 case SSH2_CIPHER_CAMELLIA128_CTR:
2586 return "camellia128-ctr(SSH2)";
2587 case SSH2_CIPHER_CAMELLIA192_CTR:
2588 return "camellia192-ctr(SSH2)";
2589 case SSH2_CIPHER_CAMELLIA256_CTR:
2590 return "camellia256-ctr(SSH2)";
2591 case SSH2_CIPHER_AES128_GCM:
2592 return "aes128-gcm@openssh.com(SSH2)";
2593 case SSH2_CIPHER_AES256_GCM:
2594 return "aes256-gcm@openssh.com(SSH2)";
2595
2596 default:
2597 return NULL;
2598 }
2599 }
2600
2601 static void set_move_button_status(HWND dlg, int type, int up, int down)
2602 {
2603 HWND cipherControl = GetDlgItem(dlg, type);
2604 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2605 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2606
2607 EnableWindow(GetDlgItem(dlg, up),
2608 curPos > 0 && curPos <= maxPos);
2609 EnableWindow(GetDlgItem(dlg, down),
2610 curPos >= 0 && curPos < maxPos);
2611 }
2612
2613 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2614 {
2615 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2616 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2617 HWND kexControl = GetDlgItem(dlg, IDC_SSHKEX_LIST);
2618 HWND hostkeyControl = GetDlgItem(dlg, IDC_SSHHOST_KEY_LIST);
2619 HWND macControl = GetDlgItem(dlg, IDC_SSHMAC_LIST);
2620 HWND compControl = GetDlgItem(dlg, IDC_SSHCOMP_LIST);
2621 HWND hostkeyRotationControl = GetDlgItem(dlg, IDC_HOSTKEY_ROTATION_STATIC);
2622 HWND hostkeyRotationControlList = GetDlgItem(dlg, IDC_HOSTKEY_ROTATION_COMBO);
2623 int i;
2624 int ch;
2625 static const char *rotationItem[SSH_UPDATE_HOSTKEYS_MAX] = {
2626 "No",
2627 "Yes",
2628 "Ask",
2629 };
2630 static const char *rotationItemKey[SSH_UPDATE_HOSTKEYS_MAX] = {
2631 "DLG_SSHSETUP_HOSTKEY_ROTATION_NO",
2632 "DLG_SSHSETUP_HOSTKEY_ROTATION_YES",
2633 "DLG_SSHSETUP_HOSTKEY_ROTATION_ASK",
2634 };
2635
2636 const static DlgTextInfo text_info[] = {
2637 { 0, "DLG_SSHSETUP_TITLE" },
2638 { IDC_COMPRESSLABEL, "DLG_SSHSETUP_COMPRESS" },
2639 { IDC_COMPRESSNONE, "DLG_SSHSETUP_COMPRESS_NONE" },
2640 { IDC_COMPRESSHIGH, "DLG_SSHSETUP_COMPRESS_HIGHEST" },
2641 { IDC_COMPRESSNOTE, "DLG_SSHSETUP_COMPRESS_NOTE" },
2642
2643 { IDC_CIPHERORDER, "DLG_SSHSETUP_CIPHER" },
2644 { IDC_SSHMOVECIPHERUP, "DLG_SSHSETUP_CIPHER_UP" },
2645 { IDC_SSHMOVECIPHERDOWN, "DLG_SSHSETUP_CIPHER_DOWN" },
2646
2647 { IDC_KEX_ORDER, "DLG_SSHSETUP_KEX" },
2648 { IDC_SSHKEX_MOVEUP, "DLG_SSHSETUP_KEX_UP" },
2649 { IDC_SSHKEX_MOVEDOWN, "DLG_SSHSETUP_KEX_DOWN" },
2650
2651 { IDC_HOST_KEY_ORDER, "DLG_SSHSETUP_HOST_KEY" },
2652 { IDC_SSHHOST_KEY_MOVEUP, "DLG_SSHSETUP_HOST_KEY_UP" },
2653 { IDC_SSHHOST_KEY_MOVEDOWN, "DLG_SSHSETUP_HOST_KEY_DOWN" },
2654
2655 { IDC_MAC_ORDER, "DLG_SSHSETUP_MAC" },
2656 { IDC_SSHMAC_MOVEUP, "DLG_SSHSETUP_MAC_UP" },
2657 { IDC_SSHMAC_MOVEDOWN, "DLG_SSHSETUP_MAC_DOWN" },
2658
2659 { IDC_COMP_ORDER, "DLG_SSHSETUP_COMP" },
2660 { IDC_SSHCOMP_MOVEUP, "DLG_SSHSETUP_COMP_UP" },
2661 { IDC_SSHCOMP_MOVEDOWN, "DLG_SSHSETUP_COMP_DOWN" },
2662
2663 { IDC_KNOWNHOSTS, "DLG_SSHSETUP_KNOWNHOST" },
2664 { IDC_CHOOSEREADWRITEFILE, "DLG_SSHSETUP_KNOWNHOST_RW" },
2665 { IDC_CHOOSEREADONLYFILE, "DLG_SSHSETUP_KNOWNHOST_RO" },
2666 { IDC_HEARTBEATLABEL, "DLG_SSHSETUP_HEARTBEAT" },
2667 { IDC_HEARTBEATLABEL2, "DLG_SSHSETUP_HEARTBEAT_UNIT" },
2668 { IDC_REMEMBERPASSWORD, "DLG_SSHSETUP_PASSWORD" },
2669 { IDC_FORWARDAGENT, "DLG_SSHSETUP_FORWARDAGENT" },
2670 { IDC_FORWARDAGENTCONFIRM, "DLG_SSHSETUP_FORWARDAGENTCONFIRM" },
2671 { IDC_FORWARDAGENTNOTIFY, "DLG_SSHSETUP_FORWARDAGENTNOTIFY" },
2672 { IDC_VERIFYHOSTKEYDNS, "DLG_SSHSETUP_VERIFYHOSTKEYDNS" },
2673 { IDC_NOTICEBANNER, "DLG_SSHSETUP_NOTICE" },
2674 { IDOK, "BTN_OK" },
2675 { IDCANCEL, "BTN_CANCEL" },
2676 { IDC_SSHSETUP_HELP, "BTN_HELP" },
2677
2678 { IDC_HOSTKEY_ROTATION_STATIC, "DLG_SSHSETUP_HOSTKEY_ROTATION" },
2679 { IDC_LOGLEVEL, "DLG_SSHSETUP_LOGLEVEL" },
2680 { IDC_LOGLEVEL_UNIT, "DLG_SSHSETUP_LOGLEVEL_UNIT" },
2681 };
2682 SetI18DlgStrs("TTSSH", dlg, text_info, _countof(text_info), pvar->ts->UILanguageFile);
2683
2684 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2685 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2686 pvar->settings.CompressionLevel);
2687
2688 // Cipher order
2689 normalize_cipher_order(pvar->settings.CipherOrder);
2690
2691 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2692 int cipher = pvar->settings.CipherOrder[i] - '0';
2693 char *name = get_cipher_name(cipher);
2694
2695 if (name != NULL) {
2696 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2697 }
2698 }
2699
2700 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2701 set_move_button_status(dlg, IDC_SSHCIPHERPREFS, IDC_SSHMOVECIPHERUP, IDC_SSHMOVECIPHERDOWN);
2702
2703 // KEX order
2704 normalize_kex_order(pvar->settings.KexOrder);
2705 for (i = 0; pvar->settings.KexOrder[i] != 0; i++) {
2706 int index = pvar->settings.KexOrder[i] - '0';
2707 char *name = NULL;
2708
2709 if (index == 0) {
2710 UTIL_get_lang_msg("DLG_SSHSETUP_KEX_BORDER", pvar,
2711 "<KEXs below this line are disabled>");
2712 name = pvar->ts->UIMsg;
2713 } else {
2714 name = get_kex_algorithm_name(index);
2715 }
2716
2717 if (name != NULL) {
2718 SendMessage(kexControl, LB_ADDSTRING, 0, (LPARAM) name);
2719 }
2720 }
2721 SendMessage(kexControl, LB_SETCURSEL, 0, 0);
2722 set_move_button_status(dlg, IDC_SSHKEX_LIST, IDC_SSHKEX_MOVEUP, IDC_SSHKEX_MOVEDOWN);
2723
2724 // Host Key order
2725 normalize_host_key_order(pvar->settings.HostKeyOrder);
2726 for (i = 0; pvar->settings.HostKeyOrder[i] != 0; i++) {
2727 int index = pvar->settings.HostKeyOrder[i] - '0';
2728 char *name = NULL;
2729
2730 if (index == 0) {
2731 UTIL_get_lang_msg("DLG_SSHSETUP_HOST_KEY_BORDER", pvar,
2732 "<Host Keys below this line are disabled>");
2733 name = pvar->ts->UIMsg;
2734 } else {
2735 name = get_ssh_keytype_name(index);
2736 }
2737
2738 if (name != NULL) {
2739 SendMessage(hostkeyControl, LB_ADDSTRING, 0, (LPARAM) name);
2740 }
2741 }
2742 SendMessage(hostkeyControl, LB_SETCURSEL, 0, 0);
2743 set_move_button_status(dlg, IDC_SSHHOST_KEY_LIST, IDC_SSHHOST_KEY_MOVEUP, IDC_SSHHOST_KEY_MOVEDOWN);
2744
2745 // MAC order
2746 normalize_mac_order(pvar->settings.MacOrder);
2747 for (i = 0; pvar->settings.MacOrder[i] != 0; i++) {
2748 int index = pvar->settings.MacOrder[i] - '0';
2749 char *name = NULL;
2750
2751 if (index == 0) {
2752 UTIL_get_lang_msg("DLG_SSHSETUP_MAC_BORDER", pvar,
2753 "<MACs below this line are disabled>");
2754 name = pvar->ts->UIMsg;
2755 } else {
2756 name = get_ssh2_mac_name_by_id(index);
2757 }
2758
2759 if (name != NULL) {
2760 SendMessage(macControl, LB_ADDSTRING, 0, (LPARAM) name);
2761 }
2762 }
2763 SendMessage(macControl, LB_SETCURSEL, 0, 0);
2764 set_move_button_status(dlg, IDC_SSHMAC_LIST, IDC_SSHMAC_MOVEUP, IDC_SSHMAC_MOVEDOWN);
2765
2766 // Compression order
2767 normalize_comp_order(pvar->settings.CompOrder);
2768 for (i = 0; pvar->settings.CompOrder[i] != 0; i++) {
2769 int index = pvar->settings.CompOrder[i] - '0';
2770 char *name = NULL;
2771
2772 if (index == 0) {
2773 UTIL_get_lang_msg("DLG_SSHSETUP_COMP_BORDER", pvar,
2774 "<Compression methods below this line are disabled>");
2775 name = pvar->ts->UIMsg;
2776 } else {
2777 name = get_ssh2_comp_name(index);
2778 }
2779
2780 if (name != NULL) {
2781 SendMessage(compControl, LB_ADDSTRING, 0, (LPARAM) name);
2782 }
2783 }
2784 SendMessage(compControl, LB_SETCURSEL, 0, 0);
2785 set_move_button_status(dlg, IDC_SSHCOMP_LIST, IDC_SSHCOMP_MOVEUP, IDC_SSHCOMP_MOVEDOWN);
2786
2787 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2788 i++) {
2789 }
2790 if (ch != 0) {
2791 pvar->settings.KnownHostsFiles[i] = 0;
2792 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2793 pvar->settings.KnownHostsFiles);
2794 pvar->settings.KnownHostsFiles[i] = ch;
2795 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2796 pvar->settings.KnownHostsFiles + i + 1);
2797 } else {
2798 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2799 pvar->settings.KnownHostsFiles);
2800 }
2801
2802 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2803 {
2804 char buf[10];
2805 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2806 "%d", pvar->settings.ssh_heartbeat_overtime);
2807 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2808 }
2809
2810 if (pvar->settings.remember_password) {
2811 CheckDlgButton(dlg, IDC_REMEMBERPASSWORD, TRUE);
2812 }
2813 if (pvar->settings.ForwardAgent) {
2814 CheckDlgButton(dlg, IDC_FORWARDAGENT, TRUE);
2815 }
2816 else {
2817 EnableWindow(GetDlgItem(dlg, IDC_FORWARDAGENTCONFIRM), FALSE);
2818 EnableWindow(GetDlgItem(dlg, IDC_FORWARDAGENTNOTIFY), FALSE);
2819 }
2820 if (pvar->settings.ForwardAgentConfirm) {
2821 CheckDlgButton(dlg, IDC_FORWARDAGENTCONFIRM, TRUE);
2822 }
2823
2824 if (pvar->settings.ForwardAgentNotify) {
2825 CheckDlgButton(dlg, IDC_FORWARDAGENTNOTIFY, TRUE);
2826 }
2827 if (!HasBalloonTipSupport()) {
2828 EnableWindow(GetDlgItem(dlg, IDC_FORWARDAGENTNOTIFY), FALSE);
2829 }
2830
2831 if (pvar->settings.VerifyHostKeyDNS) {
2832 CheckDlgButton(dlg, IDC_VERIFYHOSTKEYDNS, TRUE);
2833 }
2834
2835 // hostkey rotation(OpenSSH 6.8)
2836 for (i = 0; i < SSH_UPDATE_HOSTKEYS_MAX; i++) {
2837 UTIL_get_lang_msg(rotationItemKey[i], pvar, rotationItem[i]);
2838 SendMessage(hostkeyRotationControlList, CB_INSERTSTRING, i, (LPARAM)pvar->ts->UIMsg);
2839 }
2840 ch = pvar->settings.UpdateHostkeys;
2841 if (!(ch >= 0 && ch < SSH_UPDATE_HOSTKEYS_MAX))
2842 ch = 0;
2843 SendMessage(hostkeyRotationControlList, CB_SETCURSEL, ch, 0);
2844
2845 // LogLevel
2846 {
2847 char buf[10];
2848 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2849 "%d", pvar->settings.LogLevel);
2850 SetDlgItemText(dlg, IDC_LOGLEVEL_VALUE, buf);
2851 }
2852
2853
2854 }
2855
2856 void get_teraterm_dir_relative_name(char *buf, int bufsize,
2857 char *basename)
2858 {
2859 int filename_start = 0;
2860 int i;
2861 int ch;
2862
2863 if (basename[0] == '\\' || basename[0] == '/'
2864 || (basename[0] != 0 && basename[1] == ':')) {
2865 strncpy_s(buf, bufsize, basename, _TRUNCATE);
2866 return;
2867 }
2868
2869 GetModuleFileName(NULL, buf, bufsize);
2870 for (i = 0; (ch = buf[i]) != 0; i++) {
2871 if (ch == '\\' || ch == '/' || ch == ':') {
2872 filename_start = i + 1;
2873 }
2874 }
2875
2876 if (bufsize > filename_start) {
2877 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
2878 }
2879 }
2880
2881 int copy_teraterm_dir_relative_path(char *dest, int destsize,
2882 char *basename)
2883 {
2884 char buf[1024];
2885 int filename_start = 0;
2886 int i;
2887 int ch, ch2;
2888
2889 if (basename[0] != '\\' && basename[0] != '/'
2890 && (basename[0] == 0 || basename[1] != ':')) {
2891 strncpy_s(dest, destsize, basename, _TRUNCATE);
2892 return strlen(dest);
2893 }
2894
2895 GetModuleFileName(NULL, buf, sizeof(buf));
2896 for (i = 0; (ch = buf[i]) != 0; i++) {
2897 if (ch == '\\' || ch == '/' || ch == ':') {
2898 filename_start = i + 1;
2899 }
2900 }
2901
2902 for (i = 0; i < filename_start; i++) {
2903 ch = toupper(buf[i]);
2904 ch2 = toupper(basename[i]);
2905
2906 if (ch == ch2 ||
2907 ((ch == '\\' || ch == '/') && (ch2 == '\\' || ch2 == '/'))) {
2908 } else {
2909 break;
2910 }
2911 }
2912
2913 if (i == filename_start) {
2914 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2915 } else {
2916 strncpy_s(dest, destsize, basename, _TRUNCATE);
2917 }
2918 return strlen(dest);
2919 }
2920
2921 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2922 {
2923 char buf[4096];
2924 char buf2[1024];
2925 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2926 HWND cipherControl;
2927 int i, j, buf2index, bufindex;
2928 int count;
2929
2930 pvar->settings.CompressionLevel =
2931 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2932
2933 // Cipher order
2934 cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2935 count = (int) SendMe