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 3210 - (show annotations) (download) (as text)
Tue Feb 17 13:53:42 2009 UTC (15 years, 1 month ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 128625 byte(s)
* Windows 95
- Winsock2 が必須
- ttermpro の起動に IE4 以上が必須
- ヘルプの表示に IE5 以上が必須
- LogMeTTc は動かない
- TTLEdit はボタンの色がうまく出ない

* NT 4.0
- ヘルプの表示に IE5 以上が必須
- LogMeTT, TTLEdit の起動に SP4(?)以上 が必須
- LogMeTTc の起動に SP6 以上が必須

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