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