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 2980 - (show annotations) (download) (as text)
Wed Jun 6 14:10:12 2007 UTC (16 years, 10 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 119376 byte(s)
プリプロセッサにより構造体が変わってしまうので、INET6 と I18N の #define を逆転させた。

1 /*
2 Copyright (c) 1998-2001, Robert O'Callahan
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Teraterm extension mechanism
30 Robert O'Callahan (roc+tt@cs.cmu.edu)
31
32 Teraterm by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33 */
34
35 #include "ttxssh.h"
36 #include "fwdui.h"
37 #include "util.h"
38 #include "ssh.h"
39 #include "ttcommon.h"
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <io.h>
45 #include <fcntl.h>
46 #include <sys/stat.h>
47 #include <time.h>
48
49 #include "resource.h"
50 #include <commctrl.h>
51 #include <commdlg.h>
52 #ifndef NO_INET6
53 #include <winsock2.h>
54 static char FAR *ProtocolFamilyList[] = { "UNSPEC", "IPv6", "IPv4", NULL };
55 #else
56 #include <winsock.h>
57 #endif /* NO_INET6 */
58
59 #include <Lmcons.h>
60
61 // include OpenSSL header file
62 #include <openssl/opensslv.h>
63 #include <openssl/evp.h>
64 #include <openssl/rsa.h>
65 #include <openssl/dsa.h>
66 #include <openssl/bn.h>
67 #include <openssl/pem.h>
68 #include <openssl/rand.h>
69 #include <openssl/rc4.h>
70 #include <openssl/md5.h>
71
72 // include ZLib header file
73 #include <zlib.h>
74
75 #include "buffer.h"
76 #include "cipher.h"
77
78
79 #define MATCH_STR(s, o) strncmp((s), (o), NUM_ELEM(o) - 1)
80 #define MATCH_STR_I(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
81
82 /* This extension implements SSH, so we choose a load order in the
83 "protocols" range. */
84 #define ORDER 2500
85
86 #ifdef TERATERM32
87 static HICON SecureLargeIcon = NULL;
88 static HICON SecureSmallIcon = NULL;
89 #endif
90
91 #ifndef NO_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 #ifndef NO_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 /* NO_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 #ifndef NO_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 /* NO_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 #ifndef NO_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 /* NO_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 #ifndef NO_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 // TCPLocalEcho/TCPCRSend ������������ (maya 2007.4.25)
832 pvar->ts->DisableTCPEchoCR = TRUE;
833
834 pvar->session_settings = pvar->settings;
835
836 time(&long_time);
837 newtime = localtime(&long_time);
838 strcat(buf, asctime(newtime));
839 buf[strlen(buf) - 1] = 0;
840 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
841
842 FWDUI_load_settings(pvar);
843
844 pvar->cv->TelAutoDetect = FALSE;
845 /* This next line should not be needed because Teraterm's
846 CommLib should find ts->Telnet == 0 ... but we'll do this
847 just to be on the safe side. */
848 pvar->cv->TelFlag = FALSE;
849
850 pvar->Precv = *hooks->Precv;
851 pvar->Psend = *hooks->Psend;
852 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
853 pvar->Pconnect = *hooks->Pconnect;
854 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
855
856 *hooks->Precv = TTXrecv;
857 *hooks->Psend = TTXsend;
858 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
859 *hooks->Pconnect = TTXconnect;
860
861 SSH_open(pvar);
862 HOSTS_open(pvar);
863 FWDUI_open(pvar);
864
865 // ������ myproposal �����f���������A�������O�����������B (2006.6.26 maya)
866 SSH2_update_cipher_myproposal(pvar);
867 SSH2_update_compression_myproposal(pvar);
868 }
869 }
870
871 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
872 {
873 GET_VAR();
874
875 if (pvar->session_settings.Enabled) {
876 pvar->socket = INVALID_SOCKET;
877
878 notify_verbose_message(pvar, "Terminating SSH session...",
879 LOG_LEVEL_VERBOSE);
880
881 *hooks->Precv = pvar->Precv;
882 *hooks->Psend = pvar->Psend;
883 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
884 *hooks->Pconnect = pvar->Pconnect;
885 }
886
887 uninit_TTSSH(pvar);
888 init_TTSSH(pvar);
889 }
890
891 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
892 {
893 for (; from <= to; from++) {
894 EnableWindow(GetDlgItem(dlg, from), enabled);
895 }
896 }
897
898 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
899 LPARAM lParam)
900 {
901 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
902 PGetHNRec GetHNRec;
903 char EntName[7];
904 char TempHost[HostNameMaxLength + 1];
905 WORD i, j, w;
906 char ComPortTable[99];
907 int comports;
908 BOOL Ok;
909 #ifndef NO_I18N
910 LOGFONT logfont;
911 HFONT font;
912 #endif
913
914 GET_VAR();
915
916 switch (msg) {
917 case WM_INITDIALOG:
918 GetHNRec = (PGetHNRec) lParam;
919 SetWindowLong(dlg, DWL_USER, lParam);
920
921 #ifndef NO_I18N
922 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
923 UTIL_get_lang_msg("DLG_HOST_TITLE", pvar);
924 SetWindowText(dlg, pvar->ts->UIMsg);
925
926 GetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
927 UTIL_get_lang_msg("DLG_HOST_TCPIP_HOST", pvar);
928 SetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg);
929
930 GetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
931 UTIL_get_lang_msg("DLG_HOST_TCPIP_HISTORY", pvar);
932 SetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg);
933
934 GetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
935 UTIL_get_lang_msg("DLG_HOST_TCPIP_SERVICE", pvar);
936 SetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg);
937
938 GetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
939 UTIL_get_lang_msg("DLG_HOST_TCPIP_OTHER", pvar);
940 SetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg);
941
942 GetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
943 UTIL_get_lang_msg("DLG_HOST_TCPIP_PORT", pvar);
944 SetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg);
945
946 GetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
947 UTIL_get_lang_msg("DLG_HOST_TCPIP_SSHVERSION", pvar);
948 SetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg);
949
950 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
951 UTIL_get_lang_msg("DLG_HOST_TCPIP_PROTOCOL", pvar);
952 SetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg);
953
954 GetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
955 UTIL_get_lang_msg("DLG_HOST_SERIAL", pvar);
956 SetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg);
957
958 GetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
959 UTIL_get_lang_msg("DLG_HOST_SERIAL_PORT", pvar);
960 SetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg);
961
962 GetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
963 UTIL_get_lang_msg("DLG_HOST_HELP", pvar);
964 SetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg);
965
966 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
967 UTIL_get_lang_msg("BTN_OK", pvar);
968 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
969
970 GetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
971 UTIL_get_lang_msg("BTN_CANCEL", pvar);
972 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
973 #endif
974
975 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
976 if (pvar->ts->HistoryList > 0) {
977 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
978 } else {
979 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
980 }
981
982 if (GetHNRec->PortType == IdFile)
983 GetHNRec->PortType = IdTCPIP;
984 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
985 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
986
987 strcpy(EntName, "Host");
988
989 i = 1;
990 do {
991 sprintf(&EntName[4], "%d", i);
992 GetPrivateProfileString("Hosts", EntName, "",
993 TempHost, sizeof(TempHost),
994 GetHNRec->SetupFN);
995 if (strlen(TempHost) > 0)
996 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
997 0, (LPARAM) TempHost);
998 i++;
999 } while ((i <= 99) && (strlen(TempHost) > 0));
1000
1001 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
1002 HostNameMaxLength - 1, 0);
1003
1004 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
1005
1006 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1007 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1008 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1009 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1010 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1011 #ifndef NO_INET6
1012 for (i = 0; ProtocolFamilyList[i]; ++i) {
1013 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1014 0, (LPARAM) ProtocolFamilyList[i]);
1015 }
1016 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1017 ProtocolFamilyMaxLength - 1, 0);
1018 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1019 #endif /* NO_INET6 */
1020
1021 /////// SSH version
1022 for (i = 0; ssh_version[i]; ++i) {
1023 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1024 0, (LPARAM) ssh_version[i]);
1025 }
1026 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1027 NUM_ELEM(ssh_version) - 1, 0);
1028
1029 if (pvar->settings.ssh_protocol_version == 1) {
1030 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1031 } else {
1032 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1033 }
1034
1035 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1036 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1037 } else {
1038 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1039 }
1040 /////// SSH version
1041
1042
1043 j = 0;
1044 w = 1;
1045 strcpy(EntName, "COM");
1046 if ((comports=DetectComPorts(ComPortTable, GetHNRec->MaxComPort)) >= 0) {
1047 for (i=0; i<comports; i++) {
1048 sprintf(&EntName[3], "%d", ComPortTable[i]);
1049 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1050 0, (LPARAM)EntName);
1051 j++;
1052 if (GetHNRec->ComPort == ComPortTable[i])
1053 w = j;
1054 }
1055
1056 } else {
1057 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1058 sprintf(&EntName[3], "%d", i);
1059 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1060 0, (LPARAM) EntName);
1061 j++;
1062 if (GetHNRec->ComPort == i)
1063 w = j;
1064 }
1065 }
1066
1067 if (j > 0)
1068 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1069 else /* All com ports are already used */
1070 GetHNRec->PortType = IdTCPIP;
1071
1072 if (GetHNRec->PortType == IdTCPIP) {
1073 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1074
1075 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1076 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1077 }
1078 #ifndef NO_INET6
1079 else {
1080 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1081 FALSE);
1082 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1083 IDC_HOSTTCPPROTOCOL, FALSE);
1084
1085 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1086 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1087 }
1088 #else
1089 else
1090 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1091 FALSE);
1092 #endif /* NO_INET6 */
1093
1094 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1095 if (GetHNRec->PortType == IdTCPIP) {
1096 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1097 SetFocus(hwnd);
1098 } else {
1099 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1100 SetFocus(hwnd);
1101 }
1102
1103 #ifndef NO_I18N
1104 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1105 GetObject(font, sizeof(LOGFONT), &logfont);
1106 if (UTIL_get_lang_font("DLG_SYSTEM_FONT", dlg, &logfont, &DlgHostFont, pvar)) {
1107 SendDlgItemMessage(dlg, IDC_HOSTTCPIP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1108 SendDlgItemMessage(dlg, IDC_HOSTNAMELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1109 SendDlgItemMessage(dlg, IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1110 SendDlgItemMessage(dlg, IDC_HISTORY, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1111 SendDlgItemMessage(dlg, IDC_SERVICELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1112 SendDlgItemMessage(dlg, IDC_HOSTTELNET, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1113 SendDlgItemMessage(dlg, IDC_HOSTSSH, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1114 SendDlgItemMessage(dlg, IDC_HOSTOTHER, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1115 SendDlgItemMessage(dlg, IDC_HOSTTCPPORTLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1116 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1117 SendDlgItemMessage(dlg, IDC_SSH_VERSION_LABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1118 SendDlgItemMessage(dlg, IDC_SSH_VERSION, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1119 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOLLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1120 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1121 SendDlgItemMessage(dlg, IDC_HOSTSERIAL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1122 SendDlgItemMessage(dlg, IDC_HOSTCOMLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1123 SendDlgItemMessage(dlg, IDC_HOSTCOM, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1124 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1125 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1126 SendDlgItemMessage(dlg, IDC_HOSTHELP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1127 }
1128 else {
1129 DlgHostFont = NULL;
1130 }
1131 #endif
1132
1133 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1134 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1135 // (2004.11.23 yutaka)
1136 return FALSE;
1137 //return TRUE;
1138
1139 case WM_COMMAND:
1140 switch (LOWORD(wParam)) {
1141 case IDOK:
1142 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1143 if (GetHNRec != NULL) {
1144 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1145 #ifndef NO_INET6
1146 char afstr[BUFSIZ];
1147 #endif /* NO_INET6 */
1148 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1149 if (Ok) {
1150 GetHNRec->TCPPort = i;
1151 } else {
1152 #ifndef NO_I18N
1153 strcpy(pvar->ts->UIMsg, "The TCP port must be a number.");
1154 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar);
1155 MessageBox(dlg, pvar->ts->UIMsg,
1156 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1157 #else
1158 MessageBox(dlg, "The TCP port must be a number.",
1159 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1160 #endif
1161 return TRUE;
1162 }
1163 #ifndef NO_INET6
1164 #define getaf(str) \
1165 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1166 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1167 memset(afstr, 0, sizeof(afstr));
1168 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1169 sizeof(afstr));
1170 GetHNRec->ProtocolFamily = getaf(afstr);
1171 #endif /* NO_INET6 */
1172 GetHNRec->PortType = IdTCPIP;
1173 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1174 HostNameMaxLength);
1175 GetHNRec->Telnet = FALSE;
1176 pvar->hostdlg_activated = TRUE;
1177 pvar->hostdlg_Enabled = FALSE;
1178 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1179 GetHNRec->Telnet = TRUE;
1180 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1181 pvar->hostdlg_Enabled = TRUE;
1182
1183 // check SSH protocol version
1184 memset(afstr, 0, sizeof(afstr));
1185 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1186 if (_stricmp(afstr, "SSH1") == 0) {
1187 pvar->settings.ssh_protocol_version = 1;
1188 } else {
1189 pvar->settings.ssh_protocol_version = 2;
1190 }
1191 }
1192
1193 // host history check button
1194 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1195 pvar->ts->HistoryList = 1;
1196 } else {
1197 pvar->ts->HistoryList = 0;
1198 }
1199
1200 } else {
1201 GetHNRec->PortType = IdSerial;
1202 GetHNRec->HostName[0] = 0;
1203 memset(EntName, 0, sizeof(EntName));
1204 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1205 sizeof(EntName) - 1);
1206 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1207 if (strlen(EntName) > 4)
1208 GetHNRec->ComPort =
1209 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1210 0x30;
1211 }
1212 }
1213 EndDialog(dlg, 1);
1214
1215 #ifndef NO_I18N
1216 if (DlgHostFont != NULL) {
1217 DeleteObject(DlgHostFont);
1218 }
1219 #endif
1220
1221 return TRUE;
1222
1223 case IDCANCEL:
1224 EndDialog(dlg, 0);
1225
1226 #ifndef NO_I18N
1227 if (DlgHostFont != NULL) {
1228 DeleteObject(DlgHostFont);
1229 }
1230 #endif
1231
1232 return TRUE;
1233
1234 case IDC_HOSTTCPIP:
1235 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1236 TRUE);
1237 #ifndef NO_INET6
1238 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1239 IDC_HOSTTCPPROTOCOL, TRUE);
1240 #endif /* NO_INET6 */
1241 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1242
1243 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1244 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1245 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1246 } else {
1247 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1248 }
1249
1250 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1251
1252 return TRUE;
1253
1254 case IDC_HOSTSERIAL:
1255 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1256 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1257 FALSE);
1258 #ifndef NO_INET6
1259 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1260 IDC_HOSTTCPPROTOCOL, FALSE);
1261 #endif /* NO_INET6 */
1262 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1263 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1264
1265 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1266
1267 return TRUE;
1268
1269 case IDC_HOSTSSH:
1270 enable_dlg_items(dlg, IDC_SSH_VERSION,
1271 IDC_SSH_VERSION, TRUE);
1272 goto hostssh_enabled;
1273
1274 case IDC_HOSTTELNET:
1275 case IDC_HOSTOTHER:
1276 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1277 hostssh_enabled:
1278
1279 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1280
1281 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1282 if (GetHNRec != NULL)
1283 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1284 FALSE);
1285 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1286 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1287 }
1288 return TRUE;
1289
1290 case IDC_HOSTHELP:
1291 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1292 }
1293 }
1294 return FALSE;
1295 }
1296
1297 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1298 {
1299 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1300 parent, TTXHostDlg, (LONG) rec);
1301 }
1302
1303 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1304 {
1305 GET_VAR();
1306
1307 *hooks->GetHostName = TTXGetHostName;
1308 }
1309
1310 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1311 {
1312 GET_VAR();
1313
1314 (pvar->ReadIniFile) (fileName, ts);
1315 read_ssh_options(pvar, fileName);
1316 pvar->settings = *pvar->ts_SSH;
1317 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1318 FWDUI_load_settings(pvar);
1319 }
1320
1321 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1322 {
1323 GET_VAR();
1324
1325 (pvar->WriteIniFile) (fileName, ts);
1326 *pvar->ts_SSH = pvar->settings;
1327 clear_local_settings(pvar);
1328 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1329 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1330 }
1331
1332 static void read_ssh_options_from_user_file(PTInstVar pvar,
1333 char FAR * user_file_name)
1334 {
1335 if (user_file_name[0] == '.') {
1336 read_ssh_options(pvar, user_file_name);
1337 } else {
1338 char buf[1024];
1339
1340 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1341 read_ssh_options(pvar, buf);
1342 }
1343
1344 pvar->settings = *pvar->ts_SSH;
1345 FWDUI_load_settings(pvar);
1346 }
1347
1348
1349 // @���u�����N���u�������B (2005.1.26 yutaka)
1350 static void replace_to_blank(char *src, char *dst, int dst_len)
1351 {
1352 int len, i;
1353
1354 len = strlen(src);
1355 if (dst_len < len) // buffer overflow check
1356 return;
1357
1358 for (i = 0 ; i < len ; i++) {
1359 if (src[i] == '@') { // @ ���o��������
1360 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1361 *dst++ = '@';
1362 i++;
1363 } else {
1364 *dst++ = ' '; // �������u��������
1365 }
1366 } else {
1367 *dst++ = src[i];
1368 }
1369 }
1370 *dst = '\0';
1371 }
1372
1373 /* returns 1 if the option text must be deleted */
1374 static int parse_option(PTInstVar pvar, char FAR * option)
1375 {
1376 if ((option[0] == '-' || option[0] == '/')) {
1377 if (MATCH_STR(option + 1, "ssh") == 0) {
1378 if (option[4] == 0) {
1379 pvar->settings.Enabled = 1;
1380 } else if (MATCH_STR(option + 4, "-L") == 0
1381 || MATCH_STR(option + 4, "-R") == 0
1382 || _stricmp(option + 4, "-X") == 0) {
1383 if (pvar->settings.DefaultForwarding[0] == 0) {
1384 strcpy(pvar->settings.DefaultForwarding, option + 5);
1385 } else {
1386 strcat(pvar->settings.DefaultForwarding, ";");
1387 strcat(pvar->settings.DefaultForwarding, option + 5);
1388 }
1389 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1390 read_ssh_options_from_user_file(pvar, option + 7);
1391 } else if (MATCH_STR(option + 4, "-v") == 0) {
1392 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1393 } else if (_stricmp(option + 4, "-autologin") == 0
1394 || _stricmp(option + 4, "-autologon") == 0) {
1395 pvar->settings.TryDefaultAuth = TRUE;
1396
1397 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1398 read_ssh_options_from_user_file(pvar, option + 13);
1399 DeleteFile(option + 13);
1400
1401 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1402 } else if (MATCH_STR(option + 4, "1") == 0) {
1403 pvar->settings.ssh_protocol_version = 1;
1404 } else if (MATCH_STR(option + 4, "2") == 0) {
1405 pvar->settings.ssh_protocol_version = 2;
1406
1407 } else {
1408 char buf[1024];
1409
1410 #ifndef NO_I18N
1411 strcpy(pvar->ts->UIMsg, "Unrecognized command-line option: %s");
1412 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar);
1413 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg, option);
1414 #else
1415 _snprintf(buf, sizeof(buf),
1416 "Unrecognized command-line option: %s", option);
1417 #endif
1418 buf[sizeof(buf) - 1] = 0;
1419
1420 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1421 }
1422
1423 return 1;
1424
1425 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1426 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1427 if (strcmp(option + 3, "2") == 0) {
1428 pvar->settings.Enabled = 1;
1429 return 1;
1430 } else {
1431 pvar->settings.Enabled = 0;
1432 }
1433
1434 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1435 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1436 read_ssh_options_from_user_file(pvar, option + 3);
1437
1438 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1439 } else if (MATCH_STR(option + 1, "1") == 0) {
1440 // command line: /ssh /1 is SSH1 only
1441 pvar->settings.ssh_protocol_version = 1;
1442
1443 } else if (MATCH_STR(option + 1, "2") == 0) {
1444 // command line: /ssh /2 is SSH2 & SSH1
1445 pvar->settings.ssh_protocol_version = 2;
1446
1447 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1448 // '/nossh' �I�v�V�����������B
1449 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1450 // �����������������B(2004.10.11 yutaka)
1451 pvar->settings.Enabled = 0;
1452
1453 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1454 // '/telnet' ���w�������������������� '/nossh' ��������
1455 // SSH������������ (2006.9.16 maya)
1456 pvar->settings.Enabled = 0;
1457
1458 } else if (MATCH_STR(option + 1, "auth") == 0) {
1459 // SSH2�������O�C���I�v�V����������
1460 //
1461 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1462 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1463 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1464 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1465 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1466 //
1467 // (2004.11.30 yutaka)
1468 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1469 //
1470 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1471
1472 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h/keyboard-interactive�F��
1473 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1474 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1475
1476 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1477 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1478 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1479
1480 } else {
1481 // TODO:
1482
1483 }
1484
1485 } else if (MATCH_STR(option + 1, "user=") == 0) {
1486 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1487 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1488
1489 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1490 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1491 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1492
1493 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1494 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1495
1496 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1497 // �p�X���[�h������ (2006.9.18 maya)
1498 pvar->ask4passwd = 1;
1499
1500 }
1501
1502 // �p�X���[�h�������������������O�C��������������
1503 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1504 if (pvar->ask4passwd == 1) {
1505 pvar->ssh2_autologin = 0;
1506 }
1507
1508 }
1509
1510 return 0;
1511 }
1512
1513 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1514 PCHAR DDETopic)
1515 {
1516 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1517 int i;
1518 BOOL inParam = FALSE;
1519 BOOL inQuotes = FALSE;
1520 BOOL inFileParam = FALSE;
1521 PCHAR option = NULL;
1522 GET_VAR();
1523
1524 if (pvar->hostdlg_activated) {
1525 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1526 }
1527
1528 for (i = 0; param[i] != 0; i++) {
1529 if (inQuotes ? param[i] == '"'
1530 : (param[i] == ' ' || param[i] == '\t')) {
1531 if (option != NULL) {
1532 char ch = param[i];
1533 PCHAR Equal;
1534
1535 param[i] = 0;
1536 Equal = strchr(option, '=');
1537 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1538 char *buf = (char *)calloc(strlen(option), sizeof(char));
1539 strncat(buf, option, Equal - option + 1);
1540 strcat(buf, Equal + 2);
1541 if (parse_option
1542 (pvar, *buf == '"' ? buf + 1 : buf)) {
1543 memset(option, ' ', i + 1 - (option - param));
1544 } else {
1545 param[i] = ch;
1546 }
1547 free(buf);
1548 }
1549 else {
1550 if (parse_option
1551 (pvar, *option == '"' ? option + 1 : option)) {
1552 memset(option, ' ', i + 1 - (option - param));
1553 } else {
1554 param[i] = ch;
1555 }
1556 }
1557 option = NULL;
1558 }
1559 inParam = FALSE;
1560 inQuotes = FALSE;
1561 inFileParam = FALSE;
1562 } else if (!inParam) {
1563 if (param[i] == '"') {
1564 inQuotes = TRUE;
1565 inParam = TRUE;
1566 option = param + i;
1567 } else if (param[i] != ' ' && param[i] != '\t') {
1568 inParam = TRUE;
1569 option = param + i;
1570 }
1571 } else {
1572 if (option == NULL) {
1573 continue;
1574 }
1575 if ((option[0] == '-' || option[0] == '/') &&
1576 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1577 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1578 MATCH_STR_I(option + 1, "f=") == 0 ||
1579 MATCH_STR(option + 1, "keyfile=") == 0)) {
1580 if (param[i] == '"') {
1581 inQuotes = TRUE;
1582 }
1583 inFileParam = TRUE;
1584 }
1585 }
1586 }
1587
1588 if (option != NULL) {
1589 PCHAR Equal = strchr(option, '=');
1590 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1591 char *buf = (char *)calloc(strlen(option), sizeof(char));
1592 strncat(buf, option, Equal - option + 1);
1593 strcat(buf, Equal + 2);
1594 if (parse_option
1595 (pvar, *buf == '"' ? buf + 1 : buf)) {
1596 memset(option, ' ', i + 1 - (option - param));
1597 }
1598 free(buf);
1599 }
1600 else {
1601 if (parse_option(pvar, option)) {
1602 memset(option, ' ', i - (option - param));
1603 }
1604 }
1605 }
1606
1607 FWDUI_load_settings(pvar);
1608
1609 (pvar->ParseParam) (param, ts, DDETopic);
1610
1611 }
1612
1613 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1614 {
1615 GET_VAR();
1616
1617 pvar->ReadIniFile = *hooks->ReadIniFile;
1618 pvar->WriteIniFile = *hooks->WriteIniFile;
1619 pvar->ParseParam = *hooks->ParseParam;
1620
1621 *hooks->ReadIniFile = TTXReadINIFile;
1622 *hooks->WriteIniFile = TTXWriteINIFile;
1623 *hooks->ParseParam = TTXParseParam;
1624 }
1625
1626 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1627 {
1628 GET_VAR();
1629
1630 SSH_notify_win_size(pvar, cols, rows);
1631 }
1632
1633 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1634 WORD newItemID, char FAR * text)
1635 {
1636 int i, j;
1637
1638 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1639 HMENU submenu = GetSubMenu(menu, i);
1640
1641 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1642 if (GetMenuItemID(submenu, j) == beforeItemID) {
1643 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1644 text);
1645 return;
1646 }
1647 }
1648 }
1649 }
1650
1651 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1652 {
1653 GET_VAR();
1654
1655 /* inserts before ID_HELP_ABOUT */
1656 #ifndef NO_I18N
1657 strcpy(pvar->ts->UIMsg, "About &TTSSH...");
1658 UTIL_get_lang_msg("MENU_ABOUT", pvar);
1659 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1660 #else
1661 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1662 "About &TTSSH...");
1663 #endif
1664
1665 /* inserts before ID_SETUP_TCPIP */
1666 #ifndef NO_I18N
1667 strcpy(pvar->ts->UIMsg, "SS&H...");
1668 UTIL_get_lang_msg("MENU_SSH", pvar);
1669 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1670 #else
1671 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1672 "SS&H...");
1673 #endif
1674 /* inserts before ID_SETUP_TCPIP */
1675 #ifndef NO_I18N
1676 strcpy(pvar->ts->UIMsg, "SSH &Authentication...");
1677 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar);
1678 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1679 #else
1680 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1681 "SSH &Authentication...");
1682 #endif
1683 /* inserts before ID_SETUP_TCPIP */
1684 #ifndef NO_I18N
1685 strcpy(pvar->ts->UIMsg, "SSH F&orwarding...");
1686 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar);
1687 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1688 #else
1689 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1690 "SSH F&orwarding...");
1691 #endif
1692
1693 #ifndef NO_I18N
1694 strcpy(pvar->ts->UIMsg, "SSH KeyGe&nerator...");
1695 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar);
1696 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1697 #else
1698 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU,
1699 "SSH KeyGenerator...");
1700 #endif
1701 }
1702
1703 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1704 {
1705 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1706 (LPARAM) prefix);
1707 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1708 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1709 (LPARAM) (char FAR *) "\r\n");
1710 }
1711
1712 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1713 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1714 {
1715 typedef struct {
1716 WORD wLanguage;
1717 WORD wCodePage;
1718 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1719 LPLANGANDCODEPAGE lplgcode;
1720 UINT unLen;
1721 DWORD size;
1722 char *buf = NULL;
1723 BOOL ret;
1724 int i;
1725 char fmt[80];
1726 char *pbuf;
1727
1728 size = GetFileVersionInfoSize(exefile, NULL);
1729 if (size == 0) {
1730 goto error;
1731 }
1732 buf = malloc(size);
1733 ZeroMemory(buf, size);
1734
1735 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1736 goto error;
1737 }
1738
1739 ret = VerQueryValue(buf,
1740 "\\VarFileInfo\\Translation",
1741 (LPVOID *)&lplgcode, &unLen);
1742 if (ret == FALSE)
1743 goto error;
1744
1745 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1746 _snprintf(fmt, sizeof(fmt), "\\StringFileInfo\\%04x%04x\\FileVersion",
1747 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1748 VerQueryValue(buf, fmt, &pbuf, &unLen);
1749 if (unLen > 0) { // get success
1750 int n, a, b, c, d;
1751
1752 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1753 if (n == 4) { // convert success
1754 *major = a;
1755 *minor = b;
1756 *release = c;
1757 *build = d;
1758 break;
1759 }
1760 }
1761 }
1762
1763 free(buf);
1764 return;
1765
1766 error:
1767 free(buf);
1768 *major = *minor = *release = *build = 0;
1769 }
1770
1771 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1772 {
1773 char buf[1024];
1774 int a, b, c, d;
1775
1776 #ifndef NO_I18N
1777 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1778 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar);
1779 SetWindowText(dlg, pvar->ts->UIMsg);
1780
1781 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1782 UTIL_get_lang_msg("BTN_OK", pvar);
1783 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1784 #endif
1785
1786 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1787 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1788 _snprintf(buf, sizeof(buf), "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1789 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1790
1791 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1792 // ���������� (2005.5.11 yutaka)
1793 #ifdef OPENSSL_VERSION_TEXT
1794 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1795 #else
1796 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1797 #endif
1798
1799 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1800 #ifdef ZLIB_VERSION
1801 _snprintf(buf, sizeof(buf), "ZLib %s", ZLIB_VERSION);
1802 #else
1803 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1804 #endif
1805 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1806
1807
1808 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1809 if (pvar->socket != INVALID_SOCKET) {
1810 if (SSHv1(pvar)) {
1811 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1812 #ifndef NO_I18N
1813 strcpy(pvar->ts->UIMsg, "Server ID: ");
1814 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar);
1815 append_about_text(dlg, pvar->ts->UIMsg, buf);
1816 #else
1817 append_about_text(dlg, "Server ID: ", buf);
1818 #endif
1819 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1820 #ifndef NO_I18N
1821 strcpy(pvar->ts->UIMsg, "Using protocol: ");
1822 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar);
1823 append_about_text(dlg, pvar->ts->UIMsg, buf);
1824 #else
1825 append_about_text(dlg, "Using protocol: ", buf);
1826 #endif
1827 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1828 #ifndef NO_I18N
1829 strcpy(pvar->ts->UIMsg, "Encryption: ");
1830 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar);
1831 append_about_text(dlg, pvar->ts->UIMsg, buf);
1832 #else
1833 append_about_text(dlg, "Encryption: ", buf);
1834 #endif
1835 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1836 #ifndef NO_I18N
1837 strcpy(pvar->ts->UIMsg, "Server keys: ");
1838 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar);
1839 append_about_text(dlg, pvar->ts->UIMsg, buf);
1840 #else
1841 append_about_text(dlg, "Server keys: ", buf);
1842 #endif
1843 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1844 #ifndef NO_I18N
1845 strcpy(pvar->ts->UIMsg, "Authentication: ");
1846 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar);
1847 append_about_text(dlg, pvar->ts->UIMsg, buf);
1848 #else
1849 append_about_text(dlg, "Authentication: ", buf);
1850 #endif
1851 SSH_get_compression_info(pvar, buf, sizeof(buf));
1852 #ifndef NO_I18N
1853 strcpy(pvar->ts->UIMsg, "Compression: ");
1854 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar);
1855 append_about_text(dlg, pvar->ts->UIMsg, buf);
1856 #else
1857 append_about_text(dlg, "Compression: ", buf);
1858 #endif
1859
1860 } else { // SSH2
1861 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1862 #ifndef NO_I18N
1863 strcpy(pvar->ts->UIMsg, "Server ID: ");
1864 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar);
1865 append_about_text(dlg, pvar->ts->UIMsg, buf);
1866 #else
1867 append_about_text(dlg, "Server ID: ", buf);
1868 #endif
1869
1870 #ifndef NO_I18N
1871 strcpy(pvar->ts->UIMsg, "Client ID: ");
1872 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar);
1873 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1874 #else
1875 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1876 #endif
1877
1878 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1879 #ifndef NO_I18N
1880 strcpy(pvar->ts->UIMsg, "Using protocol: ");
1881 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar);
1882 append_about_text(dlg, pvar->ts->UIMsg, buf);
1883 #else
1884 append_about_text(dlg, "Using protocol: ", buf);
1885 #endif
1886
1887 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1888 strcpy(buf, KEX_DH1);
1889 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1890 strcpy(buf, KEX_DH14);
1891 } else {
1892 strcpy(buf, KEX_DHGEX);
1893 }
1894 append_about_text(dlg, "KEX: ", buf);
1895
1896 if (pvar->hostkey_type == KEY_DSA) {
1897 strcpy(buf, "ssh-dss");
1898 } else {
1899 strcpy(buf, "ssh-rsa");
1900 }
1901 #ifndef NO_I18N
1902 strcpy(pvar->ts->UIMsg, "Host Key: ");
1903 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar);
1904 append_about_text(dlg, pvar->ts->UIMsg, buf);
1905 #else
1906 append_about_text(dlg, "Host Key: ", buf);
1907 #endif
1908
1909 // add HMAC algorithm (2004.12.17 yutaka)
1910 buf[0] = '\0';
1911 if (pvar->ctos_hmac == HMAC_SHA1) {
1912 strcat(buf, "hmac-sha1");
1913 } else if (pvar->ctos_hmac == HMAC_MD5) {
1914 strcat(buf, "hmac-md5");
1915 }
1916 #ifndef NO_I18N
1917 strcpy(pvar->ts->UIMsg, " to server, ");
1918 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar);
1919 strcat(buf, pvar->ts->UIMsg);
1920 #else
1921 strcat(buf, " to server, ");
1922 #endif
1923 if (pvar->stoc_hmac == HMAC_SHA1) {
1924 strcat(buf, "hmac-sha1");
1925 } else if (pvar->stoc_hmac == HMAC_MD5) {
1926 strcat(buf, "hmac-md5");
1927 }
1928 #ifndef NO_I18N
1929 strcpy(pvar->ts->UIMsg, " from server");
1930 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar);
1931 strcat(buf, pvar->ts->UIMsg);
1932 #else
1933 strcat(buf, " from server");
1934 #endif
1935 append_about_text(dlg, "HMAC: ", buf);
1936
1937 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1938 #ifndef NO_I18N
1939 strcpy(pvar->ts->UIMsg, "Encryption: ");
1940 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar);
1941 append_about_text(dlg, pvar->ts->UIMsg, buf);
1942 #else
1943 append_about_text(dlg, "Encryption: ", buf);
1944 #endif
1945 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1946 #ifndef NO_I18N
1947 strcpy(pvar->ts->UIMsg, "Server keys: ");
1948 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar);
1949 append_about_text(dlg, pvar->ts->UIMsg, buf);
1950 #else
1951 append_about_text(dlg, "Server keys: ", buf);
1952 #endif
1953 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1954 #ifndef NO_I18N
1955 strcpy(pvar->ts->UIMsg, "Authentication: ");
1956 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar);
1957 append_about_text(dlg, pvar->ts->UIMsg, buf);
1958 #else
1959 append_about_text(dlg, "Authentication: ", buf);
1960 #endif
1961
1962 SSH_get_compression_info(pvar, buf, sizeof(buf));
1963 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1964 #ifndef NO_I18N
1965 strcpy(pvar->ts->UIMsg, "Delayed Compression: ");
1966 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar);
1967 append_about_text(dlg, pvar->ts->UIMsg, buf);
1968 #else
1969 append_about_text(dlg, "Delayed Compression: ", buf);
1970 #endif
1971 } else {
1972 #ifndef NO_I18N
1973 strcpy(pvar->ts->UIMsg, "Compression: ");
1974 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar);
1975 append_about_text(dlg, pvar->ts->UIMsg, buf);
1976 #else
1977 append_about_text(dlg, "Compression: ", buf);
1978 #endif
1979 }
1980
1981 }
1982 }
1983 }
1984
1985 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1986 LPARAM lParam)
1987 {
1988 #ifndef NO_I18N
1989 LOGFONT logfont;
1990 HFONT font;
1991 #endif
1992 switch (msg) {
1993 case WM_INITDIALOG:
1994 #ifndef NO_I18N
1995 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1996 GetObject(font, sizeof(LOGFONT), &logfont);
1997 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1998 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1999 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2000 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2001 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2002 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2003 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2004 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2005 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2006 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2007 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
2008 }
2009 else {
2010 DlgAboutFont = NULL;
2011 }
2012 #endif
2013 init_about_dlg((PTInstVar) lParam, dlg);
2014 return TRUE;
2015 case WM_COMMAND:
2016 switch (LOWORD(wParam)) {
2017 case IDOK:
2018 EndDialog(dlg, 1);
2019 #ifndef NO_I18N
2020 if (DlgAboutFont != NULL) {
2021 DeleteObject(DlgAboutFont);
2022 }
2023 #endif
2024 return TRUE;
2025 case IDCANCEL: /* there isn't a cancel button, but other Windows
2026 UI things can send this message */
2027 EndDialog(dlg, 0);
2028 #ifndef NO_I18N
2029 if (DlgAboutFont != NULL) {
2030 DeleteObject(DlgAboutFont);
2031 }
2032 #endif
2033 return TRUE;
2034 }
2035 break;
2036 }
2037
2038 return FALSE;
2039 }
2040
2041 static char FAR *get_cipher_name(int cipher)
2042 {
2043 switch (cipher) {
2044 case SSH_CIPHER_NONE:
2045 #ifndef NO_I18N
2046 strcpy(pvar->ts->UIMsg, "<ciphers below this line are disabled>");
2047 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar);
2048 return pvar->ts->UIMsg;
2049 #else
2050 return "<ciphers below this line are disabled>";
2051 #endif
2052 case SSH_CIPHER_RC4:
2053 return "RC4";
2054 case SSH_CIPHER_3DES:
2055 return "3DES";
2056 case SSH_CIPHER_DES:
2057 return "DES";
2058 case SSH_CIPHER_IDEA:
2059 return "IDEA";
2060 case SSH_CIPHER_TSS:
2061 return "TSS";
2062 case SSH_CIPHER_BLOWFISH:
2063 return "Blowfish";
2064
2065 // for SSH2(yutaka)
2066 case SSH_CIPHER_AES128:
2067 return "AES128(SSH2)";
2068 case SSH_CIPHER_3DES_CBC:
2069 return "3DES-CBC(SSH2)";
2070
2071 default:
2072 return NULL;
2073 }
2074 }
2075
2076 static void set_move_button_status(HWND dlg)
2077 {
2078 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2079 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2080 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2081
2082 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
2083 && curPos <= maxPos);
2084 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
2085 && curPos < maxPos);
2086 }
2087
2088 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2089 {
2090 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2091 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2092 int i;
2093 int ch;
2094
2095 #ifndef NO_I18N
2096 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2097 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar);
2098 SetWindowText(dlg, pvar->ts->UIMsg);
2099
2100 GetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2101 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar);
2102 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
2103
2104 GetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2105 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar);
2106 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
2107
2108 GetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2109 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar);
2110 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
2111
2112 GetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2113 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar);
2114 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
2115
2116 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2117 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar);
2118 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
2119
2120 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2121 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar);
2122 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2123
2124 GetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2125 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar);
2126 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2127
2128 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2129 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar);
2130 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2131
2132 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2133 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar);
2134 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2135
2136 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2137 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar);
2138 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2139
2140 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2141 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar);
2142 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2143
2144 GetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2145 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar);
2146 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2147
2148 strcpy(pvar->ts->UIMsg, "OK");
2149 UTIL_get_lang_msg("BTN_OK", pvar);
2150 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2151
2152 strcpy(pvar->ts->UIMsg, "Cancel");
2153 UTIL_get_lang_msg("BTN_CANCEL", pvar);
2154 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2155 #endif
2156
2157 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2158 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2159 pvar->settings.CompressionLevel);
2160
2161 normalize_cipher_order(pvar->settings.CipherOrder);
2162
2163 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2164 int cipher = pvar->settings.CipherOrder[i] - '0';
2165 char FAR *name = get_cipher_name(cipher);
2166
2167 if (name != NULL) {
2168 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2169 }
2170 }
2171
2172 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2173 set_move_button_status(dlg);
2174
2175 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2176 i++) {
2177 }
2178 if (ch != 0) {
2179 pvar->settings.KnownHostsFiles[i] = 0;
2180 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2181 pvar->settings.KnownHostsFiles);
2182 pvar->settings.KnownHostsFiles[i] = ch;
2183 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2184 pvar->settings.KnownHostsFiles + i + 1);
2185 } else {
2186 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2187 pvar->settings.KnownHostsFiles);
2188 }
2189
2190 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2191 {
2192 char buf[10];
2193 _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
2194 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2195 }
2196
2197 }
2198
2199 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2200 char FAR * basename)
2201 {
2202 int filename_start = 0;
2203 int i;
2204 int ch;
2205
2206 if (basename[0] == '\\' || basename[0] == '/'
2207 || (basename[0] != 0 && basename[1] == ':')) {
2208 strncpy(buf, basename, bufsize);
2209 buf[bufsize - 1] = 0;
2210 return;
2211 }
2212
2213 GetModuleFileName(NULL, buf, bufsize);
2214 for (i = 0; (ch = buf[i]) != 0; i++) {
2215 if (ch == '\\' || ch == '/' || ch == ':') {
2216 filename_start = i + 1;
2217 }
2218 }
2219
2220 if (bufsize > filename_start) {
2221 strncpy(buf + filename_start, basename, bufsize - filename_start);
2222 }
2223 buf[bufsize - 1] = 0;
2224 }
2225
2226 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2227 char FAR * basename)
2228 {
2229 char buf[1024];
2230 int filename_start = 0;
2231 int i;
2232 int ch, ch2;
2233
2234 if (basename[0] != '\\' && basename[0] != '/'
2235 && (basename[0] == 0 || basename[1] != ':')) {
2236 strncpy(dest, basename, destsize);
2237 dest[destsize - 1] = 0;
2238 return strlen(dest);
2239 }
2240
2241 GetModuleFileName(NULL, buf, sizeof(buf));
2242 for (i = 0; (ch = buf[i]) != 0; i++) {
2243 if (ch == '\\' || ch == '/' || ch == ':') {
2244 filename_start = i + 1;
2245 }
2246 }
2247
2248 for (i = 0; i < filename_start; i++) {
2249 ch = toupper(buf[i]);
2250 ch2 = toupper(basename[i]);
2251
2252 if (ch == ch2
2253 || ((ch == '\\' || ch == '/')
2254 && (ch2 == '\\' || ch2 == '/'))) {
2255 } else {
2256 break;
2257 }
2258 }
2259
2260 if (i == filename_start) {
2261 strncpy(dest, basename + i, destsize);
2262 } else {
2263 strncpy(dest, basename, destsize);
2264 }
2265 dest[destsize - 1] = 0;
2266 return strlen(dest);
2267 }
2268
2269 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2270 {
2271 char buf[4096];
2272 char buf2[1024];
2273 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2274 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2275 int i, j, buf2index, bufindex;
2276 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2277
2278 pvar->settings.CompressionLevel =
2279 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2280
2281 buf2index = 0;
2282 for (i = 0; i < count; i++) {
2283 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2284
2285 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2286 buf[0] = 0;
2287 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2288 for (j = 0;
2289 j <= SSH_CIPHER_MAX
2290 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2291 }
2292 if (j <= SSH_CIPHER_MAX) {
2293 buf2[buf2index] = '0' + j;
2294 buf2index++;
2295 }
2296 }
2297 }
2298 buf2[buf2index] = 0;
2299 normalize_cipher_order(buf2);
2300 strcpy(pvar->settings.CipherOrder, buf2);
2301
2302 buf[0] = 0;
2303 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2304 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2305 sizeof(pvar->settings.
2306 KnownHostsFiles), buf);
2307 buf[0] = 0;
2308 bufindex = 0;
2309 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2310 for (i = 0; buf[i] != 0; i++) {
2311 if (buf[i] == ';') {
2312 buf[i] = 0;
2313 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2314 pvar->settings.KnownHostsFiles[j] = ';';
2315 j++;
2316 j += copy_teraterm_dir_relative_path(pvar->settings.
2317 KnownHostsFiles + j,
2318 sizeof(pvar->settings.
2319 KnownHostsFiles)
2320 - j, buf + bufindex);
2321 }
2322 bufindex = i + 1;
2323 }
2324 }
2325 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2326 pvar->settings.KnownHostsFiles[j] = ';';
2327 j++;
2328 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2329 sizeof(pvar->settings.
2330 KnownHostsFiles) - j,
2331 buf + bufindex);
2332 }
2333
2334 // get SSH HeartBeat(keep-alive)
2335 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2336 i = atoi(buf);
2337 if (i < 0)
2338 i = 60;
2339 pvar->settings.ssh_heartbeat_overtime = i;
2340
2341 }
2342
2343 static void move_cur_sel_delta(HWND listbox, int delta)
2344 {
2345 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2346 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2347 int newPos = curPos + delta;
2348 char buf[1024];
2349
2350 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2351 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2352
2353 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2354 buf[0] = 0;
2355 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2356 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2357 SendMessage(listbox, LB_INSERTSTRING, newPos,
2358 (LPARAM) (char FAR *) buf);
2359 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2360 }
2361 }
2362 }
2363
2364 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2365 int readonly)
2366 {
2367 #ifdef TERATERM32
2368 OPENFILENAME params;
2369 char fullname_buf[2048] = "ssh_known_hosts";
2370
2371 params.lStructSize = sizeof(OPENFILENAME);
2372 params.hwndOwner = parent;
2373 params.lpstrFilter = NULL;
2374 params.lpstrCustomFilter = NULL;
2375 params.nFilterIndex = 0;
2376 buf[0] = 0;
2377 params.lpstrFile = fullname_buf;
2378 params.nMaxFile = sizeof(fullname_buf);
2379 params.lpstrFileTitle = NULL;
2380 params.lpstrInitialDir = NULL;
2381 #ifndef NO_I18N
2382 if (readonly) {
2383 strcpy(pvar->ts->UIMsg, "Choose a read-only known-hosts file to add");
2384 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar);
2385 }
2386 else {
2387 strcpy(pvar->ts->UIMsg, "Choose a read/write known-hosts file");
2388 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar);
2389 }
2390 params.lpstrTitle = pvar->ts->UIMsg;
2391 #else
2392 params.lpstrTitle =
2393 readonly ? "Choose a read-only known-hosts file to add" :
2394 "Choose a read/write known-hosts file";
2395 #endif
2396 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2397 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2398 params.lpstrDefExt = NULL;
2399
2400 if (GetOpenFileName(&params) != 0) {
2401 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2402 return 1;
2403 } else {
2404 int err = CommDlgExtendedError();
2405
2406 if (err != 0) {
2407 char buf[1024];
2408 #ifndef NO_I18N
2409 strcpy(pvar->ts->UIMsg, "Unable to display file dialog box: error %d");
2410 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar);
2411 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg, err);
2412 #else
2413 _snprintf(buf, sizeof(buf),
2414 "Cannot show file dialog box: error %d", err);
2415 #endif
2416 buf[sizeof(buf) - 1] = 0;
2417 MessageBox(parent, buf, "TTSSH Error",
2418 MB_OK | MB_ICONEXCLAMATION);
2419 }
2420
2421 return 0;
2422 }
2423 #else
2424 return 0;
2425 #endif
2426 }
2427
2428 static void choose_read_write_file(HWND dlg)
2429 {
2430 char buf[1024];
2431
2432 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2433 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2434 }
2435 }
2436
2437 static void choose_read_only_file(HWND dlg)
2438 {
2439 char buf[1024];
2440 char buf2[4096];
2441
2442 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2443 buf2[0] = 0;
2444 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2445 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2446 strncat(buf2, ";", sizeof(buf2));
2447 }
2448 strncat(buf2, buf, sizeof(buf2));
2449 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2450 }
2451 }
2452
2453 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2454 LPARAM lParam)
2455 {
2456 #ifndef NO_I18N
2457 LOGFONT logfont;
2458 HFONT font;
2459 #endif
2460 switch (msg) {
2461 case WM_INITDIALOG:
2462 SetWindowLong(dlg, DWL_USER, lParam);
2463 init_setup_dlg((PTInstVar) lParam, dlg);
2464 #ifndef NO_I18N
2465 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2466 GetObject(font, sizeof(LOGFONT), &logfont);
2467 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2468 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2469 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2470 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2471 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2472 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2473 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2474 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2475 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2476 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2477 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2478 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2479 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2480 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2481 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2482 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2483 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2484 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2485 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2486 }
2487 else {
2488 DlgSetupFont = NULL;
2489 }
2490 #endif
2491 return TRUE;
2492 case WM_COMMAND:
2493 switch (LOWORD(wParam)) {
2494 case IDOK:
2495 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
2496 dlg);
2497 EndDialog(dlg, 1);
2498 #ifndef NO_I18N
2499 if (DlgSetupFont != NULL) {
2500 DeleteObject(DlgSetupFont);
2501 }
2502 #endif
2503 return TRUE;
2504 case IDCANCEL: /* there isn't a cancel button, but other Windows
2505 UI things can send this message */
2506 EndDialog(dlg, 0);
2507 #ifndef NO_I18N
2508 if (DlgSetupFont != NULL) {
2509 DeleteObject(DlgSetupFont);
2510 }
2511 #endif
2512 return TRUE;
2513 case IDC_SSHMOVECIPHERUP:
2514 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2515 set_move_button_status(dlg);
2516 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2517 return TRUE;
2518 case IDC_SSHMOVECIPHERDOWN:
2519 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2520 set_move_button_status(dlg);
2521 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2522 return TRUE;
2523 case IDC_SSHCIPHERPREFS:
2524 set_move_button_status(dlg);
2525 return TRUE;
2526 case IDC_CHOOSEREADWRITEFILE:
2527 choose_read_write_file(dlg);
2528 return TRUE;
2529 case IDC_CHOOSEREADONLYFILE:
2530 choose_read_only_file(dlg);
2531 return TRUE;
2532 }
2533 break;
2534 }
2535
2536 return FALSE;
2537 }
2538
2539
2540 //
2541 // SSH key generator dialog (2005.4.10 yutaka)
2542 //
2543
2544 typedef struct {
2545 RSA *rsa;
2546 DSA *dsa;
2547 } ssh_private_key_t;
2548
2549 static ssh_private_key_t private_key = {NULL, NULL};
2550
2551 typedef struct {
2552 RSA *rsa;
2553 DSA *dsa;
2554 } ssh_public_key_t;
2555
2556 static ssh_public_key_t public_key = {NULL, NULL};;
2557
2558 static void free_ssh_key(void)
2559 {
2560 // DSA_free(), RSA_free()��NULL���n�����������������B
2561 DSA_free(private_key.dsa);
2562 private_key.dsa = NULL;
2563 DSA_free(public_key.dsa);
2564 public_key.dsa = NULL;
2565
2566 RSA_free(private_key.rsa);
2567 private_key.rsa = NULL;
2568 RSA_free(public_key.rsa);
2569 public_key.rsa = NULL;
2570 }
2571
2572
2573 static BOOL generate_ssh_key(enum hostkey_type type)
2574 {
2575 int bits = 1024;
2576
2577 // if SSH key already is generated, should free the resource.
2578 free_ssh_key();
2579
2580 if (type == KEY_RSA1 || type == KEY_RSA) {
2581 RSA *priv = NULL;
2582 RSA *pub = NULL;
2583
2584 // private key
2585 priv = RSA_generate_key(bits, 35, NULL, NULL);
2586 if (priv == NULL)
2587 goto error;
2588 private_key.rsa = priv;
2589
2590 // public key
2591 pub = RSA_new();
2592 pub->n = BN_new();
2593 pub->e = BN_new();
2594 if (pub->n == NULL || pub->e == NULL) {
2595 RSA_free(pub);
2596 goto error;
2597 }
2598
2599 BN_copy(pub->n, priv->n);
2600 BN_copy(pub->e, priv->e);
2601 public_key.rsa = pub;
2602
2603 } else if (type == KEY_DSA) {
2604 DSA *priv = NULL;
2605 DSA *pub = NULL;
2606
2607 // private key
2608 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2609 if (priv == NULL)
2610 goto error;
2611 if (!DSA_generate_key(priv)) {
2612 // TODO: free 'priv'?
2613 goto error;
2614 }
2615 private_key.dsa = priv;
2616
2617 // public key
2618 pub = DSA_new();
2619 if (pub == NULL)
2620 goto error;
2621 pub->p = BN_new();
2622 pub->q = BN_new();
2623 pub->g = BN_new();
2624 pub->pub_key = BN_new();
2625 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2626 DSA_free(pub);
2627 goto error;
2628 }
2629
2630 BN_copy(pub->p, priv->p);
2631 BN_copy(pub->q, priv->q);
2632 BN_copy(pub->g, priv->g);
2633 BN_copy(pub->pub_key, priv->pub_key);
2634 public_key.dsa = pub;
2635
2636 } else {
2637 goto error;
2638 }
2639
2640 return TRUE;
2641
2642 error:
2643 free_ssh_key();
2644 return FALSE;
2645 }
2646
2647
2648 //
2649 // RC4
2650 //
2651
2652 /* Size of key to use */
2653 #define SEED_SIZE 20
2654
2655 /* Number of bytes to reseed after */
2656 #define REKEY_BYTES (1 << 24)
2657
2658 static int rc4_ready = 0;
2659 static RC4_KEY rc4;
2660
2661 static void seed_rng(void)
2662 {
2663 if (RAND_status() != 1)
2664 return;
2665 }
2666
2667 static void arc4random_stir(void)
2668 {
2669 unsigned char rand_buf[SEED_SIZE];
2670 int i;
2671
2672 memset(&rc4, 0, sizeof(rc4));
2673 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2674 //fatal("Couldn't obtain random bytes (error %ld)",
2675 // ERR_get_error());
2676 }
2677 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2678
2679 /*
2680 * Discard early keystream, as per recommendations in:
2681 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2682 */
2683 for(i = 0; i <= 256; i += sizeof(rand_buf))
2684 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2685
2686 memset(rand_buf, 0, sizeof(rand_buf));
2687
2688 rc4_ready = REKEY_BYTES;
2689 }
2690
2691 static unsigned int arc4random(void)
2692 {
2693 unsigned int r = 0;
2694 static int first_time = 1;
2695
2696 if (rc4_ready <= 0) {
2697 if (first_time) {
2698 seed_rng();
2699 }
2700 first_time = 0;
2701 arc4random_stir();
2702 }
2703
2704 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2705
2706 rc4_ready -= sizeof(r);
2707
2708 return(r);
2709 }
2710
2711 //
2712 // SSH1 3DES
2713 //
2714 /*
2715 * This is used by SSH1:
2716 *
2717 * What kind of triple DES are these 2 routines?
2718 *
2719 * Why is there a redundant initialization vector?
2720 *
2721 * If only iv3 was used, then, this would till effect have been
2722 * outer-cbc. However, there is also a private iv1 == iv2 which
2723 * perhaps makes differential analysis easier. On the other hand, the
2724 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2725 * result of that there is no longer any known iv1 to use when
2726 * choosing the X block.
2727 */
2728 struct ssh1_3des_ctx
2729 {
2730 EVP_CIPHER_CTX k1, k2, k3;
2731 };
2732
2733 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2734 {
2735 struct ssh1_3des_ctx *c;
2736 u_char *k1, *k2, *k3;
2737
2738 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2739 c = malloc(sizeof(*c));
2740 EVP_CIPHER_CTX_set_app_data(ctx, c);
2741 }
2742 if (key == NULL)
2743 return (1);
2744 if (enc == -1)
2745 enc = ctx->encrypt;
2746 k1 = k2 = k3 = (u_char *) key;
2747 k2 += 8;
2748 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2749 if (enc)
2750 k3 += 16;
2751 else
2752 k1 += 16;
2753 }
2754 EVP_CIPHER_CTX_init(&c->k1);
2755 EVP_CIPHER_CTX_init(&c->k2);
2756 EVP_CIPHER_CTX_init(&c->k3);
2757 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2758 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2759 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2760 memset(c, 0, sizeof(*c));
2761 free(c);
2762 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2763 return (0);
2764 }
2765 return (1);
2766 }
2767
2768 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2769 {
2770 struct ssh1_3des_ctx *c;
2771
2772 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2773 //error("ssh1_3des_cbc: no context");
2774 return (0);
2775 }
2776 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2777 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2778 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2779 return (0);
2780 return (1);
2781 }
2782
2783 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2784 {
2785 struct ssh1_3des_ctx *c;
2786
2787 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2788 EVP_CIPHER_CTX_cleanup(&c->k1);
2789 EVP_CIPHER_CTX_cleanup(&c->k2);
2790 EVP_CIPHER_CTX_cleanup(&c->k3);
2791 memset(c, 0, sizeof(*c));
2792 free(c);
2793 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2794 }
2795 return (1);
2796 }
2797
2798 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2799 {
2800 struct ssh1_3des_ctx *c;
2801
2802 if (len != 24)
2803 //fatal("%s: bad 3des iv length: %d", __func__, len);
2804 ;
2805
2806 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2807 //fatal("%s: no 3des context", __func__);
2808 ;
2809
2810 if (doset) {
2811 //debug3("%s: Installed 3DES IV", __func__);
2812 memcpy(c->k1.iv, iv, 8);
2813 memcpy(c->k2.iv, iv + 8, 8);
2814 memcpy(c->k3.iv, iv + 16, 8);
2815 } else {
2816 //debug3("%s: Copying 3DES IV", __func__);
2817 memcpy(iv, c->k1.iv, 8);
2818 memcpy(iv + 8, c->k2.iv, 8);
2819 memcpy(iv + 16, c->k3.iv, 8);
2820 }
2821 }
2822
2823 const EVP_CIPHER *evp_ssh1_3des(void)
2824 {
2825 static EVP_CIPHER ssh1_3des;
2826
2827 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2828 ssh1_3des.nid = NID_undef;
2829 ssh1_3des.block_size = 8;
2830 ssh1_3des.iv_len = 0;
2831 ssh1_3des.key_len = 16;
2832 ssh1_3des.init = ssh1_3des_init;
2833 ssh1_3des.cleanup = ssh1_3des_cleanup;
2834 ssh1_3des.do_cipher = ssh1_3des_cbc;
2835 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2836 return (&ssh1_3des);
2837 }
2838
2839 static void ssh_make_comment(char *comment, int maxlen)
2840 {
2841 char user[UNLEN + 1], host[128];
2842 DWORD dwSize;
2843 WSADATA wsaData;
2844 int ret;
2845
2846 // get Windows logon user name
2847 dwSize = sizeof(user);
2848 if (GetUserName(user, &dwSize) == 0) {
2849 strcpy(user, "yutaka");
2850 }
2851
2852 // get local hostname (by WinSock)
2853 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2854 if (ret == 0) {
2855 if (gethostname(host, sizeof(host)) != 0) {
2856 ret = WSAGetLastError();
2857 }
2858 WSACleanup();
2859 }
2860 if (ret != 0) {
2861 strcpy(host, "sai");
2862 }
2863
2864 _snprintf(comment, maxlen, "%s@%s", user, host);
2865 }
2866
2867 // uuencode (rfc1521)
2868 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2869 {
2870 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2871 char pad = '=';
2872 int datalength = 0;
2873 unsigned char input[3];
2874 unsigned char output[4];
2875 int i;
2876
2877 while (srclen > 2) {
2878 input[0] = *src++;
2879 input[1] = *src++;
2880 input[2] = *src++;
2881 srclen -= 3;
2882
2883 output[0] = input[0] >> 2;
2884 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2885 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2886 output[3] = input[2] & 0x3f;
2887 if (output[0] >= 64 ||
2888 output[1] >= 64 ||
2889 output[2] >= 64 ||
2890 output[3] >= 64)
2891 return -1;
2892
2893 if (datalength + 4 > targsize)
2894 return (-1);
2895 target[datalength++] = base64[output[0]];
2896 target[datalength++] = base64[output[1]];
2897 target[datalength++] = base64[output[2]];
2898 target[datalength++] = base64[output[3]];
2899 }
2900
2901 if (srclen != 0) {
2902 /* Get what's left. */
2903 input[0] = input[1] = input[2] = '\0';
2904 for (i = 0; i < srclen; i++)
2905 input[i] = *src++;
2906
2907 output[0] = input[0] >> 2;
2908 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2909 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2910 if (output[0] >= 64 ||
2911 output[1] >= 64 ||
2912 output[2] >= 64)
2913 return -1;
2914
2915 if (datalength + 4 > targsize)
2916 return (-1);
2917 target[datalength++] = base64[output[0]];
2918 target[datalength++] = base64[output[1]];
2919 if (srclen == 1)
2920 target[datalength++] = pad;
2921 else
2922 target[datalength++] = base64[output[2]];
2923 target[datalength++] = pad;
2924 }
2925 if (datalength >= targsize)
2926 return (-1);
2927 target[datalength] = '\0'; /* Returned value doesn't count \0. */
2928
2929 return (datalength); // success
2930 }
2931
2932 static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2933 LPARAM lParam)
2934 {
2935 static enum hostkey_type key_type;
2936 #ifndef NO_I18N
2937 char uimsg[MAX_UIMSG];
2938 LOGFONT logfont;
2939 HFONT font;
2940 #endif
2941
2942 switch (msg) {
2943