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 3065 - (show annotations) (download) (as text)
Mon Nov 5 00:51:38 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 112165 byte(s)
"New connection" ダイアログのコマンドラインの 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 (MATCH_STR(option + 4, "-consume=") == 0) {
1461 read_ssh_options_from_user_file(pvar, option + 13);
1462 DeleteFile(option + 13);
1463
1464 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1465 } else if (MATCH_STR(option + 4, "1") == 0) {
1466 pvar->settings.ssh_protocol_version = 1;
1467 } else if (MATCH_STR(option + 4, "2") == 0) {
1468 pvar->settings.ssh_protocol_version = 2;
1469
1470 } else {
1471 char buf[1024];
1472
1473 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar,
1474 "Unrecognized command-line option: %s");
1475 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, option);
1476
1477 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1478 }
1479
1480 return 1;
1481
1482 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1483 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1484 if (strcmp(option + 3, "2") == 0) {
1485 pvar->settings.Enabled = 1;
1486 return 1;
1487 } else {
1488 pvar->settings.Enabled = 0;
1489 }
1490
1491 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1492 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1493 read_ssh_options_from_user_file(pvar, option + 3);
1494
1495 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1496 } else if (MATCH_STR(option + 1, "1") == 0) {
1497 // command line: /ssh /1 is SSH1 only
1498 pvar->settings.ssh_protocol_version = 1;
1499
1500 } else if (MATCH_STR(option + 1, "2") == 0) {
1501 // command line: /ssh /2 is SSH2 & SSH1
1502 pvar->settings.ssh_protocol_version = 2;
1503
1504 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1505 // '/nossh' �I�v�V�����������B
1506 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1507 // �����������������B(2004.10.11 yutaka)
1508 pvar->settings.Enabled = 0;
1509
1510 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1511 // '/telnet' ���w�������������������� '/nossh' ��������
1512 // SSH������������ (2006.9.16 maya)
1513 pvar->settings.Enabled = 0;
1514
1515 } else if (MATCH_STR(option + 1, "auth") == 0) {
1516 // SSH2�������O�C���I�v�V����������
1517 //
1518 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1519 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1520 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1521 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1522 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1523 //
1524 // (2004.11.30 yutaka)
1525 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1526 //
1527 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1528
1529 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h
1530 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1531 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1532
1533 // /auth=challenge ������ (2007.10.5 maya)
1534 } else if (MATCH_STR(option + 5, "=challenge") == 0) { // keyboard-interactive�F��
1535 //pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
1536 pvar->ssh2_authmethod = SSH_AUTH_TIS;
1537
1538 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1539 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1540 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1541
1542 } else {
1543 // TODO:
1544
1545 }
1546
1547 } else if (MATCH_STR(option + 1, "user=") == 0) {
1548 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1549 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1550
1551 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1552 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1553 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1554
1555 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1556 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1557
1558 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1559 // �p�X���[�h������ (2006.9.18 maya)
1560 pvar->ask4passwd = 1;
1561
1562 }
1563
1564 // �p�X���[�h�������������������O�C��������������
1565 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1566 if (pvar->ask4passwd == 1) {
1567 pvar->ssh2_autologin = 0;
1568 }
1569
1570 }
1571
1572 return 0;
1573 }
1574
1575 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1576 PCHAR DDETopic)
1577 {
1578 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1579 int i;
1580 BOOL inParam = FALSE;
1581 BOOL inQuotes = FALSE;
1582 BOOL inFileParam = FALSE;
1583 PCHAR option = NULL;
1584 GET_VAR();
1585
1586 if (pvar->hostdlg_activated) {
1587 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1588 }
1589
1590 for (i = 0; param[i] != 0; i++) {
1591 if (inQuotes ? param[i] == '"'
1592 : (param[i] == ' ' || param[i] == '\t')) {
1593 if (option != NULL) {
1594 char ch = param[i];
1595 PCHAR Equal;
1596
1597 param[i] = 0;
1598 Equal = strchr(option, '=');
1599 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1600 int buf_len = strlen(option) * sizeof(char);
1601 char *buf = (char *)calloc(strlen(option), sizeof(char));
1602 char c = option[Equal - option + 1];
1603 option[Equal - option + 1] = 0;
1604 strncat_s(buf, buf_len, option, _TRUNCATE);
1605 option[Equal - option + 1] = c;
1606 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1607 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1608 memset(option, ' ', i + 1 - (option - param));
1609 } else {
1610 param[i] = ch;
1611 }
1612 free(buf);
1613 }
1614 else {
1615 if (parse_option(pvar, *option == '"' ? option + 1 : option)) {
1616 memset(option, ' ', i + 1 - (option - param));
1617 } else {
1618 param[i] = ch;
1619 }
1620 }
1621 option = NULL;
1622 }
1623 inParam = FALSE;
1624 inQuotes = FALSE;
1625 inFileParam = FALSE;
1626 } else if (!inParam) {
1627 if (param[i] == '"') {
1628 inQuotes = TRUE;
1629 inParam = TRUE;
1630 option = param + i;
1631 } else if (param[i] != ' ' && param[i] != '\t') {
1632 inParam = TRUE;
1633 option = param + i;
1634 }
1635 } else {
1636 if (option == NULL) {
1637 continue;
1638 }
1639 if ((option[0] == '-' || option[0] == '/') &&
1640 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1641 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1642 MATCH_STR_I(option + 1, "f=") == 0 ||
1643 MATCH_STR(option + 1, "keyfile=") == 0)) {
1644 if (param[i] == '"') {
1645 inQuotes = TRUE;
1646 }
1647 inFileParam = TRUE;
1648 }
1649 }
1650 }
1651
1652 if (option != NULL) {
1653 PCHAR Equal = strchr(option, '=');
1654 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1655 int buf_len = strlen(option) * sizeof(char);
1656 char *buf = (char *)calloc(strlen(option), sizeof(char));
1657 char c = option[Equal - option + 1];
1658 option[Equal - option + 1] = 0;
1659 strncat_s(buf, buf_len, option, _TRUNCATE);
1660 option[Equal - option + 1] = c;
1661 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1662 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1663 memset(option, ' ', i + 1 - (option - param));
1664 }
1665 free(buf);
1666 }
1667 else {
1668 if (parse_option(pvar, option)) {
1669 memset(option, ' ', i - (option - param));
1670 }
1671 }
1672 }
1673
1674 FWDUI_load_settings(pvar);
1675
1676 (pvar->ParseParam) (param, ts, DDETopic);
1677
1678 }
1679
1680 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1681 {
1682 GET_VAR();
1683
1684 pvar->ReadIniFile = *hooks->ReadIniFile;
1685 pvar->WriteIniFile = *hooks->WriteIniFile;
1686 pvar->ParseParam = *hooks->ParseParam;
1687
1688 *hooks->ReadIniFile = TTXReadINIFile;
1689 *hooks->WriteIniFile = TTXWriteINIFile;
1690 *hooks->ParseParam = TTXParseParam;
1691 }
1692
1693 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1694 {
1695 GET_VAR();
1696
1697 SSH_notify_win_size(pvar, cols, rows);
1698 }
1699
1700 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1701 WORD newItemID, char FAR * text)
1702 {
1703 int i, j;
1704
1705 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1706 HMENU submenu = GetSubMenu(menu, i);
1707
1708 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1709 if (GetMenuItemID(submenu, j) == beforeItemID) {
1710 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID, text);
1711 return;
1712 }
1713 }
1714 }
1715 }
1716
1717 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1718 {
1719 GET_VAR();
1720
1721 /* inserts before ID_HELP_ABOUT */
1722 UTIL_get_lang_msg("MENU_ABOUT", pvar, "About &TTSSH...");
1723 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1724
1725 /* inserts before ID_SETUP_TCPIP */
1726 UTIL_get_lang_msg("MENU_SSH", pvar, "SS&H...");
1727 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1728 /* inserts before ID_SETUP_TCPIP */
1729 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar, "SSH &Authentication...");
1730 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1731 /* inserts before ID_SETUP_TCPIP */
1732 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar, "SSH F&orwarding...");
1733 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1734 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar, "SSH KeyGe&nerator...");
1735 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1736 }
1737
1738 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1739 {
1740 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1741 (LPARAM) prefix);
1742 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1743 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1744 (LPARAM) (char FAR *) "\r\n");
1745 }
1746
1747 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1748 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1749 {
1750 typedef struct {
1751 WORD wLanguage;
1752 WORD wCodePage;
1753 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1754 LPLANGANDCODEPAGE lplgcode;
1755 UINT unLen;
1756 DWORD size;
1757 char *buf = NULL;
1758 BOOL ret;
1759 int i;
1760 char fmt[80];
1761 char *pbuf;
1762
1763 size = GetFileVersionInfoSize(exefile, NULL);
1764 if (size == 0) {
1765 goto error;
1766 }
1767 buf = malloc(size);
1768 ZeroMemory(buf, size);
1769
1770 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1771 goto error;
1772 }
1773
1774 ret = VerQueryValue(buf,
1775 "\\VarFileInfo\\Translation",
1776 (LPVOID *)&lplgcode, &unLen);
1777 if (ret == FALSE)
1778 goto error;
1779
1780 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1781 _snprintf_s(fmt, sizeof(fmt), _TRUNCATE,
1782 "\\StringFileInfo\\%04x%04x\\FileVersion",
1783 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1784 VerQueryValue(buf, fmt, &pbuf, &unLen);
1785 if (unLen > 0) { // get success
1786 int n, a, b, c, d;
1787
1788 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1789 if (n == 4) { // convert success
1790 *major = a;
1791 *minor = b;
1792 *release = c;
1793 *build = d;
1794 break;
1795 }
1796 }
1797 }
1798
1799 free(buf);
1800 return;
1801
1802 error:
1803 free(buf);
1804 *major = *minor = *release = *build = 0;
1805 }
1806
1807 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1808 {
1809 char buf[1024];
1810 int a, b, c, d;
1811 char uimsg[MAX_UIMSG];
1812
1813 GetWindowText(dlg, uimsg, sizeof(uimsg));
1814 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar, uimsg);
1815 SetWindowText(dlg, pvar->ts->UIMsg);
1816 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1817 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
1818 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1819
1820 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1821 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1822 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1823 "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1824 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1825
1826 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1827 // ���������� (2005.5.11 yutaka)
1828 #ifdef OPENSSL_VERSION_TEXT
1829 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1830 #else
1831 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1832 #endif
1833
1834 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1835 #ifdef ZLIB_VERSION
1836 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
1837 #else
1838 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1839 #endif
1840 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1841
1842
1843 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1844 if (pvar->socket != INVALID_SOCKET) {
1845 if (SSHv1(pvar)) {
1846 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1847 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1848 append_about_text(dlg, pvar->ts->UIMsg, buf);
1849 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1850 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1851 append_about_text(dlg, pvar->ts->UIMsg, buf);
1852 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1853 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1854 append_about_text(dlg, pvar->ts->UIMsg, buf);
1855 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1856 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1857 append_about_text(dlg, pvar->ts->UIMsg, buf);
1858 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1859 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1860 append_about_text(dlg, pvar->ts->UIMsg, buf);
1861 SSH_get_compression_info(pvar, buf, sizeof(buf));
1862 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1863 append_about_text(dlg, pvar->ts->UIMsg, buf);
1864
1865 } else { // SSH2
1866 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1867 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1868 append_about_text(dlg, pvar->ts->UIMsg, buf);
1869 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar, "Client ID: ");
1870 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1871
1872 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1873 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1874 append_about_text(dlg, pvar->ts->UIMsg, buf);
1875
1876 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1877 strncpy_s(buf, sizeof(buf), KEX_DH1, _TRUNCATE);
1878 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1879 strncpy_s(buf, sizeof(buf), KEX_DH14, _TRUNCATE);
1880 } else {
1881 strncpy_s(buf, sizeof(buf), KEX_DHGEX, _TRUNCATE);
1882 }
1883 append_about_text(dlg, "KEX: ", buf);
1884
1885 if (pvar->hostkey_type == KEY_DSA) {
1886 strncpy_s(buf, sizeof(buf), "ssh-dss", _TRUNCATE);
1887 } else {
1888 strncpy_s(buf, sizeof(buf), "ssh-rsa", _TRUNCATE);
1889 }
1890 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key: ");
1891 append_about_text(dlg, pvar->ts->UIMsg, buf);
1892
1893 // add HMAC algorithm (2004.12.17 yutaka)
1894 buf[0] = '\0';
1895 if (pvar->ctos_hmac == HMAC_SHA1) {
1896 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1897 } else if (pvar->ctos_hmac == HMAC_MD5) {
1898 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1899 }
1900 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar, " to server, ");
1901 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1902 if (pvar->stoc_hmac == HMAC_SHA1) {
1903 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1904 } else if (pvar->stoc_hmac == HMAC_MD5) {
1905 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1906 }
1907 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar, " from server");
1908 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1909 append_about_text(dlg, "HMAC: ", buf);
1910
1911 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1912 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1913 append_about_text(dlg, pvar->ts->UIMsg, buf);
1914 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1915 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1916 append_about_text(dlg, pvar->ts->UIMsg, buf);
1917
1918 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1919 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1920 append_about_text(dlg, pvar->ts->UIMsg, buf);
1921
1922 SSH_get_compression_info(pvar, buf, sizeof(buf));
1923 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1924 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar, "Delayed Compression: ");
1925 append_about_text(dlg, pvar->ts->UIMsg, buf);
1926 } else {
1927 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1928 append_about_text(dlg, pvar->ts->UIMsg, buf);
1929 }
1930 }
1931 }
1932 }
1933
1934 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1935 LPARAM lParam)
1936 {
1937 LOGFONT logfont;
1938 HFONT font;
1939
1940 switch (msg) {
1941 case WM_INITDIALOG:
1942 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1943 GetObject(font, sizeof(LOGFONT), &logfont);
1944 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1945 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1946 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1947 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1948 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1949 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1950 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1951 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1952 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1953 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1954 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1955 }
1956 else {
1957 DlgAboutFont = NULL;
1958 }
1959 init_about_dlg((PTInstVar) lParam, dlg);
1960 return TRUE;
1961 case WM_COMMAND:
1962 switch (LOWORD(wParam)) {
1963 case IDOK:
1964 EndDialog(dlg, 1);
1965 if (DlgAboutFont != NULL) {
1966 DeleteObject(DlgAboutFont);
1967 }
1968 return TRUE;
1969 case IDCANCEL: /* there isn't a cancel button, but other Windows
1970 UI things can send this message */
1971 EndDialog(dlg, 0);
1972 if (DlgAboutFont != NULL) {
1973 DeleteObject(DlgAboutFont);
1974 }
1975 return TRUE;
1976 }
1977 break;
1978 }
1979
1980 return FALSE;
1981 }
1982
1983 static char FAR *get_cipher_name(int cipher)
1984 {
1985 switch (cipher) {
1986 case SSH_CIPHER_NONE:
1987 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
1988 "<ciphers below this line are disabled>");
1989 return pvar->ts->UIMsg;
1990 case SSH_CIPHER_RC4:
1991 return "RC4(SSH1)";
1992 case SSH_CIPHER_3DES:
1993 return "3DES(SSH1)";
1994 case SSH_CIPHER_DES:
1995 return "DES(SSH1)";
1996 case SSH_CIPHER_IDEA:
1997 return "IDEA(SSH1)";
1998 case SSH_CIPHER_TSS:
1999 return "TSS(SSH1)";
2000 case SSH_CIPHER_BLOWFISH:
2001 return "Blowfish(SSH1)";
2002
2003 // for SSH2(yutaka)
2004 case SSH2_CIPHER_AES128:
2005 return "AES128(SSH2)";
2006 case SSH2_CIPHER_AES192:
2007 return "AES192(SSH2)";
2008 case SSH2_CIPHER_AES256:
2009 return "AES256(SSH2)";
2010 case SSH2_CIPHER_3DES_CBC:
2011 return "3DES-CBC(SSH2)";
2012 case SSH2_CIPHER_BLOWFISH:
2013 return "Blowfish(SSH2)";
2014
2015 default:
2016 return NULL;
2017 }
2018 }
2019
2020 static void set_move_button_status(HWND dlg)
2021 {
2022 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2023 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2024 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2025
2026 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP),
2027 curPos > 0 && curPos <= maxPos);
2028 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN),
2029 curPos >= 0 && curPos < maxPos);
2030 }
2031
2032 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2033 {
2034 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2035 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2036 int i;
2037 int ch;
2038 char uimsg[MAX_UIMSG];
2039
2040 GetWindowText(dlg, uimsg, sizeof(uimsg));
2041 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar, uimsg);
2042 SetWindowText(dlg, pvar->ts->UIMsg);
2043 GetDlgItemText(dlg, IDC_COMPRESSLABEL, uimsg, sizeof(uimsg));
2044 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar, uimsg);
2045 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
2046 GetDlgItemText(dlg, IDC_COMPRESSNONE, uimsg, sizeof(uimsg));
2047 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar, uimsg);
2048 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
2049 GetDlgItemText(dlg, IDC_COMPRESSHIGH, uimsg, sizeof(uimsg));
2050 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar, uimsg);
2051 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
2052 GetDlgItemText(dlg, IDC_CIPHERORDER, uimsg, sizeof(uimsg));
2053 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar, uimsg);
2054 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
2055 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, uimsg, sizeof(uimsg));
2056 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar, uimsg);
2057 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
2058 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, uimsg, sizeof(uimsg));
2059 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar, uimsg);
2060 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2061 GetDlgItemText(dlg, IDC_KNOWNHOSTS, uimsg, sizeof(uimsg));
2062 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar, uimsg);
2063 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2064 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, uimsg, sizeof(uimsg));
2065 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar, uimsg);
2066 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2067 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, uimsg, sizeof(uimsg));
2068 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar, uimsg);
2069 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2070 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, uimsg, sizeof(uimsg));
2071 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar, uimsg);
2072 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2073 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, uimsg, sizeof(uimsg));
2074 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar, uimsg);
2075 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2076 GetDlgItemText(dlg, IDC_NOTICEBANNER, uimsg, sizeof(uimsg));
2077 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar, uimsg);
2078 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2079 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2080 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
2081 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2082 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2083 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
2084 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2085
2086 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2087 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2088 pvar->settings.CompressionLevel);
2089
2090 normalize_cipher_order(pvar->settings.CipherOrder);
2091
2092 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2093 int cipher = pvar->settings.CipherOrder[i] - '0';
2094 char FAR *name = get_cipher_name(cipher);
2095
2096 if (name != NULL) {
2097 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2098 }
2099 }
2100
2101 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2102 set_move_button_status(dlg);
2103
2104 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2105 i++) {
2106 }
2107 if (ch != 0) {
2108 pvar->settings.KnownHostsFiles[i] = 0;
2109 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2110 pvar->settings.KnownHostsFiles);
2111 pvar->settings.KnownHostsFiles[i] = ch;
2112 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2113 pvar->settings.KnownHostsFiles + i + 1);
2114 } else {
2115 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2116 pvar->settings.KnownHostsFiles);
2117 }
2118
2119 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2120 {
2121 char buf[10];
2122 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2123 "%d", pvar->settings.ssh_heartbeat_overtime);
2124 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2125 }
2126
2127 }
2128
2129 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2130 char FAR * basename)
2131 {
2132 int filename_start = 0;
2133 int i;
2134 int ch;
2135
2136 if (basename[0] == '\\' || basename[0] == '/'
2137 || (basename[0] != 0 && basename[1] == ':')) {
2138 strncpy_s(buf, bufsize, basename, _TRUNCATE);
2139 return;
2140 }
2141
2142 GetModuleFileName(NULL, buf, bufsize);
2143 for (i = 0; (ch = buf[i]) != 0; i++) {
2144 if (ch == '\\' || ch == '/' || ch == ':') {
2145 filename_start = i + 1;
2146 }
2147 }
2148
2149 if (bufsize > filename_start) {
2150 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
2151 }
2152 }
2153
2154 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2155 char FAR * basename)
2156 {
2157 char buf[1024];
2158 int filename_start = 0;
2159 int i;
2160 int ch, ch2;
2161
2162 if (basename[0] != '\\' && basename[0] != '/'
2163 && (basename[0] == 0 || basename[1] != ':')) {
2164 strncpy_s(dest, destsize, basename, _TRUNCATE);
2165 return strlen(dest);
2166 }
2167
2168 GetModuleFileName(NULL, buf, sizeof(buf));
2169 for (i = 0; (ch = buf[i]) != 0; i++) {
2170 if (ch == '\\' || ch == '/' || ch == ':') {
2171 filename_start = i + 1;
2172 }
2173 }
2174
2175 for (i = 0; i < filename_start; i++) {
2176 ch = toupper(buf[i]);
2177 ch2 = toupper(basename[i]);
2178
2179 if (ch == ch2 ||
2180 ((ch == '\\' || ch == '/') && (ch2 == '\\' || ch2 == '/'))) {
2181 } else {
2182 break;
2183 }
2184 }
2185
2186 if (i == filename_start) {
2187 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2188 } else {
2189 strncpy_s(dest, destsize, basename, _TRUNCATE);
2190 }
2191 return strlen(dest);
2192 }
2193
2194 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2195 {
2196 char buf[4096];
2197 char buf2[1024];
2198 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2199 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2200 int i, j, buf2index, bufindex;
2201 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2202
2203 pvar->settings.CompressionLevel =
2204 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2205
2206 buf2index = 0;
2207 for (i = 0; i < count; i++) {
2208 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2209
2210 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2211 buf[0] = 0;
2212 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2213 for (j = 0;
2214 j <= SSH_CIPHER_MAX
2215 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2216 }
2217 if (j <= SSH_CIPHER_MAX) {
2218 buf2[buf2index] = '0' + j;
2219 buf2index++;
2220 }
2221 }
2222 }
2223 buf2[buf2index] = 0;
2224 normalize_cipher_order(buf2);
2225 strncpy_s(pvar->settings.CipherOrder, sizeof(pvar->settings.CipherOrder), buf2, _TRUNCATE);
2226
2227 buf[0] = 0;
2228 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2229 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2230 sizeof(pvar->settings.KnownHostsFiles),
2231 buf);
2232 buf[0] = 0;
2233 bufindex = 0;
2234 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2235 for (i = 0; buf[i] != 0; i++) {
2236 if (buf[i] == ';') {
2237 buf[i] = 0;
2238 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2239 pvar->settings.KnownHostsFiles[j] = ';';
2240 j++;
2241 j += copy_teraterm_dir_relative_path(pvar->settings.
2242 KnownHostsFiles + j,
2243 sizeof(pvar->settings.
2244 KnownHostsFiles)
2245 - j, buf + bufindex);
2246 }
2247 bufindex = i + 1;
2248 }
2249 }
2250 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2251 pvar->settings.KnownHostsFiles[j] = ';';
2252 j++;
2253 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2254 sizeof(pvar->settings. KnownHostsFiles) - j,
2255 buf + bufindex);
2256 }
2257
2258 // get SSH HeartBeat(keep-alive)
2259 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2260 i = atoi(buf);
2261 if (i < 0)
2262 i = 60;
2263 pvar->settings.ssh_heartbeat_overtime = i;
2264
2265 }
2266
2267 static void move_cur_sel_delta(HWND listbox, int delta)
2268 {
2269 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2270 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2271 int newPos = curPos + delta;
2272 char buf[1024];
2273
2274 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2275 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2276
2277 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2278 buf[0] = 0;
2279 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2280 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2281 SendMessage(listbox, LB_INSERTSTRING, newPos,
2282 (LPARAM) (char FAR *) buf);
2283 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2284 }
2285 }
2286 }
2287
2288 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2289 int readonly)
2290 {
2291 OPENFILENAME params;
2292 char fullname_buf[2048] = "ssh_known_hosts";
2293
2294 params.lStructSize = sizeof(OPENFILENAME);
2295 params.hwndOwner = parent;
2296 params.lpstrFilter = NULL;
2297 params.lpstrCustomFilter = NULL;
2298 params.nFilterIndex = 0;
2299 buf[0] = 0;
2300 params.lpstrFile = fullname_buf;
2301 params.nMaxFile = sizeof(fullname_buf);
2302 params.lpstrFileTitle = NULL;
2303 params.lpstrInitialDir = NULL;
2304 if (readonly) {
2305 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar,
2306 "Choose a read-only known-hosts file to add");
2307 }
2308 else {
2309 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar,
2310 "Choose a read/write known-hosts file");
2311 }
2312 params.lpstrTitle = pvar->ts->UIMsg;
2313 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2314 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2315 params.lpstrDefExt = NULL;
2316
2317 if (GetOpenFileName(&params) != 0) {
2318 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2319 return 1;
2320 } else {
2321 int err = CommDlgExtendedError();
2322
2323 if (err != 0) {
2324 char buf[1024];
2325 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar,
2326 "Unable to display file dialog box: error %d");
2327 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, err);
2328 MessageBox(parent, buf, "TTSSH Error",
2329 MB_OK | MB_ICONEXCLAMATION);
2330 }
2331
2332 return 0;
2333 }
2334 }
2335
2336 static void choose_read_write_file(HWND dlg)
2337 {
2338 char buf[1024];
2339
2340 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2341 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2342 }
2343 }
2344
2345 static void choose_read_only_file(HWND dlg)
2346 {
2347 char buf[1024];
2348 char buf2[4096];
2349
2350 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2351 buf2[0] = 0;
2352 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2353 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2354 strncat_s(buf2, sizeof(buf2), ";", _TRUNCATE);
2355 }
2356 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2357 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2358 }
2359 }
2360
2361 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2362 LPARAM lParam)
2363 {
2364 LOGFONT logfont;
2365 HFONT font;
2366
2367 switch (msg) {
2368 case WM_INITDIALOG:
2369 SetWindowLong(dlg, DWL_USER, lParam);
2370 init_setup_dlg((PTInstVar) lParam, dlg);
2371
2372 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2373 GetObject(font, sizeof(LOGFONT), &logfont);
2374 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2375 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2376 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2377 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2378 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2379 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2380 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2381 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2382 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2383 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2384 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2385 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2386 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2387 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2388 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2389 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2390 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2391 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2392 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2393 }
2394 else {
2395 DlgSetupFont = NULL;
2396 }
2397
2398 return TRUE;
2399 case WM_COMMAND:
2400 switch (LOWORD(wParam)) {
2401 case IDOK:
2402 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER), dlg);
2403 EndDialog(dlg, 1);
2404 if (DlgSetupFont != NULL) {
2405 DeleteObject(DlgSetupFont);
2406 }
2407 return TRUE;
2408 case IDCANCEL: /* there isn't a cancel button, but other Windows
2409 UI things can send this message */
2410 EndDialog(dlg, 0);
2411 if (DlgSetupFont != NULL) {
2412 DeleteObject(DlgSetupFont);
2413 }
2414 return TRUE;
2415 case IDC_SSHMOVECIPHERUP:
2416 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2417 set_move_button_status(dlg);
2418 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2419 return TRUE;
2420 case IDC_SSHMOVECIPHERDOWN:
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_SSHCIPHERPREFS:
2426 set_move_button_status(dlg);
2427 return TRUE;
2428 case IDC_CHOOSEREADWRITEFILE:
2429 choose_read_write_file(dlg);
2430 return TRUE;
2431 case IDC_CHOOSEREADONLYFILE:
2432 choose_read_only_file(dlg);
2433 return TRUE;
2434 }
2435 break;
2436 }
2437
2438 return FALSE;
2439 }
2440
2441
2442 //
2443 // SSH key generator dialog (2005.4.10 yutaka)
2444 //
2445
2446 typedef struct {
2447 RSA *rsa;
2448 DSA *dsa;
2449 } ssh_private_key_t;
2450
2451 static ssh_private_key_t private_key = {NULL, NULL};
2452
2453 typedef struct {
2454 RSA *rsa;
2455 DSA *dsa;
2456 } ssh_public_key_t;
2457
2458 static ssh_public_key_t public_key = {NULL, NULL};;
2459
2460 static void free_ssh_key(void)
2461 {
2462 // DSA_free(), RSA_free()��NULL���n�����������������B
2463 DSA_free(private_key.dsa);
2464 private_key.dsa = NULL;
2465 DSA_free(public_key.dsa);
2466 public_key.dsa = NULL;
2467
2468 RSA_free(private_key.rsa);
2469 private_key.rsa = NULL;
2470 RSA_free(public_key.rsa);
2471 public_key.rsa = NULL;
2472 }
2473
2474
2475 static BOOL generate_ssh_key(enum hostkey_type type)
2476 {
2477 int bits = 1024;
2478
2479 // if SSH key already is generated, should free the resource.
2480 free_ssh_key();
2481
2482 if (type == KEY_RSA1 || type == KEY_RSA) {
2483 RSA *priv = NULL;
2484 RSA *pub = NULL;
2485
2486 // private key
2487 priv = RSA_generate_key(bits, 35, NULL, NULL);
2488 if (priv == NULL)
2489 goto error;
2490 private_key.rsa = priv;
2491
2492 // public key
2493 pub = RSA_new();
2494 pub->n = BN_new();
2495 pub->e = BN_new();
2496 if (pub->n == NULL || pub->e == NULL) {
2497 RSA_free(pub);
2498 goto error;
2499 }
2500
2501 BN_copy(pub->n, priv->n);
2502 BN_copy(pub->e, priv->e);
2503 public_key.rsa = pub;
2504
2505 } else if (type == KEY_DSA) {
2506 DSA *priv = NULL;
2507 DSA *pub = NULL;
2508
2509 // private key
2510 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2511 if (priv == NULL)
2512 goto error;
2513 if (!DSA_generate_key(priv)) {
2514 // TODO: free 'priv'?
2515 goto error;
2516 }
2517 private_key.dsa = priv;
2518
2519 // public key
2520 pub = DSA_new();
2521 if (pub == NULL)
2522 goto error;
2523 pub->p = BN_new();
2524 pub->q = BN_new();
2525 pub->g = BN_new();
2526 pub->pub_key = BN_new();
2527 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2528 DSA_free(pub);
2529 goto error;
2530 }
2531
2532 BN_copy(pub->p, priv->p);
2533 BN_copy(pub->q, priv->q);
2534 BN_copy(pub->g, priv->g);
2535 BN_copy(pub->pub_key, priv->pub_key);
2536 public_key.dsa = pub;
2537
2538 } else {
2539 goto error;
2540 }
2541
2542 return TRUE;
2543
2544 error:
2545 free_ssh_key();
2546 return FALSE;
2547 }
2548
2549
2550 //
2551 // RC4
2552 //
2553
2554 /* Size of key to use */
2555 #define SEED_SIZE 20
2556
2557 /* Number of bytes to reseed after */
2558 #define REKEY_BYTES (1 << 24)
2559
2560 static int rc4_ready = 0;
2561 static RC4_KEY rc4;
2562
2563 static void seed_rng(void)
2564 {
2565 if (RAND_status() != 1)
2566 return;
2567 }
2568
2569 static void arc4random_stir(void)
2570 {
2571 unsigned char rand_buf[SEED_SIZE];
2572 int i;
2573
2574 memset(&rc4, 0, sizeof(rc4));
2575 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2576 //fatal("Couldn't obtain random bytes (error %ld)",
2577 // ERR_get_error());
2578 }
2579 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2580
2581 /*
2582 * Discard early keystream, as per recommendations in:
2583 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2584 */
2585 for(i = 0; i <= 256; i += sizeof(rand_buf))
2586 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2587
2588 memset(rand_buf, 0, sizeof(rand_buf));
2589
2590 rc4_ready = REKEY_BYTES;
2591 }
2592
2593 static unsigned int arc4random(void)
2594 {
2595 unsigned int r = 0;
2596 static int first_time = 1;
2597
2598 if (rc4_ready <= 0) {
2599 if (first_time) {
2600 seed_rng();
2601 }
2602 first_time = 0;
2603 arc4random_stir();
2604 }
2605
2606 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2607
2608 rc4_ready -= sizeof(r);
2609
2610 return(r);
2611 }
2612
2613 //
2614 // SSH1 3DES
2615 //
2616 /*
2617 * This is used by SSH1:
2618 *
2619 * What kind of triple DES are these 2 routines?
2620 *
2621 * Why is there a redundant initialization vector?
2622 *
2623 * If only iv3 was used, then, this would till effect have been
2624 * outer-cbc. However, there is also a private iv1 == iv2 which
2625 * perhaps makes differential analysis easier. On the other hand, the
2626 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2627 * result of that there is no longer any known iv1 to use when
2628 * choosing the X block.
2629 */
2630 struct ssh1_3des_ctx
2631 {
2632 EVP_CIPHER_CTX k1, k2, k3;
2633 };
2634
2635 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2636 {
2637 struct ssh1_3des_ctx *c;
2638 u_char *k1, *k2, *k3;
2639
2640 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2641 c = malloc(sizeof(*c));
2642 EVP_CIPHER_CTX_set_app_data(ctx, c);
2643 }
2644 if (key == NULL)
2645 return (1);
2646 if (enc == -1)
2647 enc = ctx->encrypt;
2648 k1 = k2 = k3 = (u_char *) key;
2649 k2 += 8;
2650 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2651 if (enc)
2652 k3 += 16;
2653 else
2654 k1 += 16;
2655 }
2656 EVP_CIPHER_CTX_init(&c->k1);
2657 EVP_CIPHER_CTX_init(&c->k2);
2658 EVP_CIPHER_CTX_init(&c->k3);
2659 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2660 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2661 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2662 memset(c, 0, sizeof(*c));
2663 free(c);
2664 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2665 return (0);
2666 }
2667 return (1);
2668 }
2669
2670 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2671 {
2672 struct ssh1_3des_ctx *c;
2673
2674 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2675 //error("ssh1_3des_cbc: no context");
2676 return (0);
2677 }
2678 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2679 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2680 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2681 return (0);
2682 return (1);
2683 }
2684
2685 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2686 {
2687 struct ssh1_3des_ctx *c;
2688
2689 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2690 EVP_CIPHER_CTX_cleanup(&c->k1);
2691 EVP_CIPHER_CTX_cleanup(&c->k2);
2692 EVP_CIPHER_CTX_cleanup(&c->k3);
2693 memset(c, 0, sizeof(*c));
2694 free(c);
2695 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2696 }
2697 return (1);
2698 }
2699
2700 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2701 {
2702 struct ssh1_3des_ctx *c;
2703
2704 if (len != 24)
2705 //fatal("%s: bad 3des iv length: %d", __func__, len);
2706 ;
2707
2708 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2709 //fatal("%s: no 3des context", __func__);
2710 ;
2711
2712 if (doset) {
2713 //debug3("%s: Installed 3DES IV", __func__);
2714 memcpy(c->k1.iv, iv, 8);
2715 memcpy(c->k2.iv, iv + 8, 8);
2716 memcpy(c->k3.iv, iv + 16, 8);
2717 } else {
2718 //debug3("%s: Copying 3DES IV", __func__);
2719 memcpy(iv, c->k1.iv, 8);
2720 memcpy(iv + 8, c->k2.iv, 8);
2721 memcpy(iv + 16, c->k3.iv, 8);
2722 }
2723 }
2724
2725 const EVP_CIPHER *evp_ssh1_3des(void)
2726 {
2727 static EVP_CIPHER ssh1_3des;
2728
2729 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2730 ssh1_3des.nid = NID_undef;
2731 ssh1_3des.block_size = 8;
2732 ssh1_3des.iv_len = 0;
2733 ssh1_3des.key_len = 16;
2734 ssh1_3des.init = ssh1_3des_init;
2735 ssh1_3des.cleanup = ssh1_3des_cleanup;
2736 ssh1_3des.do_cipher = ssh1_3des_cbc;
2737 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2738 return (&ssh1_3des);
2739 }
2740
2741 static void ssh_make_comment(char *comment, int maxlen)
2742 {
2743 char user[UNLEN + 1], host[128];
2744 DWORD dwSize;
2745 WSADATA wsaData;
2746 int ret;
2747
2748 // get Windows logon user name
2749 dwSize = sizeof(user);
2750 if (GetUserName(user, &dwSize) == 0) {
2751 strncpy_s(user, sizeof(user), "yutaka", _TRUNCATE);
2752 }
2753
2754 // get local hostname (by WinSock)
2755 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2756 if (ret == 0) {
2757 if (gethostname(host, sizeof(host)) != 0) {
2758 ret = WSAGetLastError();
2759 }
2760 WSACleanup();
2761 }
2762 if (ret != 0) {
2763 strncpy_s(host, sizeof(host), "sai", _TRUNCATE);
2764 }
2765
2766 _snprintf_s(comment, maxlen, _TRUNCATE, "%s@%s", user, host);
2767 }
2768
2769 // uuencode (rfc1521)
2770 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2771 {
2772 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2773 char pad = '=';
2774 int datalength = 0;
2775 unsigned char input[3];
2776 unsigned char output[4];
2777 int i;
2778
2779 while (srclen > 2) {
2780 input[0] = *src++;
2781 input[1] = *src++;
2782 input[2] = *src++;
2783 srclen -= 3;
2784
2785 output[0] = input[0] >> 2;
2786 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2787 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2788 output[3] = input[2] & 0x3f;
2789 if (output[0] >= 64 ||
2790 output[1] >= 64 ||
2791 output[2] >= 64 ||
2792 output[3] >= 64)
2793 return -1;
2794
2795 if (datalength + 4 > targsize)
2796 return (-1);
2797 target[datalength++] = base64[output[0]];
2798 target[datalength++] = base64[output[1]];
2799 target[datalength++] = base64[output[2]];
2800 target[datalength++] = base64[output[3]];
2801 }
2802
2803 if (srclen != 0) {
2804 /* Get what's left. */
2805 input[0] = input[1] = input[2] = '\0';
2806 for (i = 0; i < srclen; i++)
2807 input[i] = *src++;
2808
2809 output[0] = input[0] >> 2;
2810 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2811 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2812 if (output[0] >= 64 ||
2813 output[1] >= 64 ||
2814 output[2] >= 64)
2815 return -1;
2816
2817 if (datalength + 4 > targsize)
2818 return (-1);
2819 target[datalength++] = base64[output[0]];
2820 target[datalength++] = base64[output[1]];
2821 if (srclen == 1)
2822 target[datalength++] = pad;
2823 else
2824 target[datalength++] = base64[output[2]];
2825 target[datalength++] = pad;
2826 }
2827 if (datalength >= targsize)
2828 return (-1);
2829 target[datalength] = '\0'; /* Returned value doesn't count \0. */
2830
2831 return (datalength); // success
2832 }
2833
2834 static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2835 LPARAM lParam)
2836 {
2837 static enum hostkey_type key_type;
2838 char uimsg[MAX_UIMSG];
2839 LOGFONT logfont;
2840 HFONT font;
2841
2842 switch (msg) {
2843 case WM_INITDIALOG:
2844 {
2845 GetWindowText(dlg, uimsg, sizeof(uimsg));
2846 UTIL_get_lang_msg("DLG_KEYGEN_TITLE", pvar, uimsg);
2847 SetWindowText(dlg, pvar->ts->UIMsg);
2848 GetDlgItemText(dlg, IDC_KEYTYPE, uimsg, sizeof(uimsg));
2849 UTIL_get_lang_msg("DLG_KEYGEN_KEYTYPE", pvar, uimsg);
2850 SetDlgItemText(dlg, IDC_KEYTYPE, pvar->ts->UIMsg);
2851 GetDlgItemText(dlg, IDC_KEY_LABEL, uimsg, sizeof(uimsg));
2852 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE", pvar, uimsg);
2853 SetDlgItemText(dlg, IDC_KEY_LABEL, pvar->ts->UIMsg);
2854 GetDlgItemText(dlg, IDC_CONFIRM_LABEL, uimsg, sizeof(uimsg));
2855 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE2", pvar,