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