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 2999 - (show annotations) (download) (as text)
Sat Aug 18 08:54:14 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107271 byte(s)
不定なメモリを free して落ちることがある問題を修正した。

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