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 3022 - (show annotations) (download) (as text)
Wed Oct 3 12:33:36 2007 UTC (16 years, 6 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 110633 byte(s)
C-d/C-k をサポート。

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