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 3205 - (show annotations) (download) (as text)
Sat Jan 24 02:33:22 2009 UTC (15 years, 2 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 127164 byte(s)
鍵生成中に全てのボタンを押せないようにした

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