Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4367 - (show annotations) (download) (as text)
Sat Mar 5 14:52:45 2011 UTC (13 years, 1 month ago) by yutakapon
Original Path: trunk/ttssh2/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 146999 byte(s)
TTSSHの各種暗号設定に関して、teraterm.iniのエントリでカスタマイズできるようにした。
正式なUIに関しては、これから検討する。

KexOrder=56743210
HostKeyOrder=456230
MacOrder=120
CompOrder=012

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