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