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 3072 - (show annotations) (download) (as text)
Fri Dec 7 18:06:25 2007 UTC (16 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 112344 byte(s)
New Connection ダイアログのホスト名に /ssh1, /ssh2 が含まれている場合、SSH 接続が無効になる問題を修正した。

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