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 2967 - (show annotations) (download) (as text)
Thu Mar 15 05:09:52 2007 UTC (17 years, 1 month ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118721 byte(s)
/keyfile= パラメータもスペースを含むファイル名を認識するよう修正した。

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