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 2937 - (show annotations) (download) (as text)
Thu Nov 23 02:19:30 2006 UTC (17 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107719 byte(s)
表示メッセージを言語ファイルから読み込みむコードの作成を開始した。

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