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