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 2949 - (show annotations) (download) (as text)
Mon Jan 22 13:45:19 2007 UTC (17 years, 2 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 117331 byte(s)
表示メッセージの読み込み対応

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