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 2995 - (show annotations) (download) (as text)
Wed Aug 15 04:03:26 2007 UTC (16 years, 8 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 106830 byte(s)
$Log$ を削除した。

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