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 3001 - (show annotations) (download) (as text)
Mon Aug 20 08:32:12 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 104876 byte(s)
TERATERM32 マクロを削除した。

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