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 3045 - (show annotations) (download) (as text)
Thu Oct 18 03:49:39 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 111383 byte(s)
SSH2 の暗号化方式として Blowfish をサポートしたい。

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