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 2965 - (show annotations) (download) (as text)
Mon Mar 5 08:39:57 2007 UTC (17 years, 1 month ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118564 byte(s)
DetectComPorts を ttpcmn.dll のエクスポート関数に変更した。

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