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 4422 - (show annotations) (download) (as text)
Fri Apr 8 07:13:27 2011 UTC (13 years ago) by doda
Original Path: trunk/ttssh2/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 147492 byte(s)
hmac-sha1-96, hmac-md5-96 をサポート。

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