Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11023 - (show annotations) (download) (as text)
Fri Oct 27 14:26:45 2023 UTC (5 months, 2 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 158014 byte(s)
公開鍵認証で接続したSSHセッションを複製できないことがある

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