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 3197 - (show annotations) (download) (as text)
Fri Jan 9 12:17:32 2009 UTC (15 years, 3 months ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 125715 byte(s)
SSHキー生成ダイアログで、鍵のビット数を指定できるようにした。
鍵のビット数のデフォルトは、RSA1とRSAが2048、DSAが1024。

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