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 2996 - (show annotations) (download) (as text)
Fri Aug 17 05:49:55 2007 UTC (16 years, 7 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107015 byte(s)
Serial portのDescriptionを取得するようにした。

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