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 4423 - (show annotations) (download) (as text)
Fri Apr 8 07:34:37 2011 UTC (13 years ago) by doda
Original Path: trunk/ttssh2/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 147511 byte(s)
hmac-ripemd160@openssh.com をサポート。hmac-ripemd160 は IANA に登録されていないのでサポートしない。

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