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