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 3232 - (show annotations) (download) (as text)
Tue Mar 24 20:50:54 2009 UTC (15 years ago) by doda
Original Path: trunk/ttssh2/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 131372 byte(s)
一部の2バイト文字がホスト名に使えなかったのを修正。
[Ttssh2-devel 1407], http://sourceforge.jp/forum/forum.php?thread_id=22115&forum_id=5841

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