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 3003 - (show annotations) (download) (as text)
Mon Aug 20 14:21:57 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 106447 byte(s)
インデントを変更した。

1 /*
2 Copyright (c) 1998-2001, Robert O'Callahan
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Teraterm extension mechanism
30 Robert O'Callahan (roc+tt@cs.cmu.edu)
31
32 Teraterm by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33 */
34
35 #include "ttxssh.h"
36 #include "fwdui.h"
37 #include "util.h"
38 #include "ssh.h"
39 #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 ||
245 _stricmp(buf, "y") == 0;
246 }
247 }
248
249 static void read_string_option(PCHAR fileName, char FAR * keyName,
250 char FAR * def, char FAR * buf, int bufSize)
251 {
252
253 buf[0] = 0;
254 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
255 }
256
257 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
258 {
259 char buf[1024];
260 TS_SSH FAR *settings = pvar->ts_SSH;
261
262 #define READ_STD_STRING_OPTION(name) \
263 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
264
265 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
266
267 buf[0] = 0;
268 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
269 fileName);
270 settings->CompressionLevel = atoi(buf);
271 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
272 settings->CompressionLevel = 0;
273 }
274
275 READ_STD_STRING_OPTION(DefaultUserName);
276 READ_STD_STRING_OPTION(DefaultForwarding);
277 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
278 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
279 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
280
281 READ_STD_STRING_OPTION(CipherOrder);
282 normalize_cipher_order(settings->CipherOrder);
283
284 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
285 settings->KnownHostsFiles,
286 sizeof(settings->KnownHostsFiles));
287
288 buf[0] = 0;
289 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
290 sizeof(buf), fileName);
291 settings->DefaultAuthMethod = atoi(buf);
292 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
293 && settings->DefaultAuthMethod != SSH_AUTH_RSA
294 && settings->DefaultAuthMethod != SSH_AUTH_TIS // add (2005.3.12 yutaka)
295 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS) {
296 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
297 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
298 when the dialog box has rhosts selected and an host private key file
299 is supplied. */
300 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
301 }
302
303 buf[0] = 0;
304 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
305 fileName);
306 settings->LogLevel = atoi(buf);
307
308 buf[0] = 0;
309 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
310 sizeof(buf), fileName);
311 settings->WriteBufferSize = atoi(buf);
312 if (settings->WriteBufferSize <= 0) {
313 settings->WriteBufferSize = 2 * 1024 * 1024;
314 }
315
316 settings->LocalForwardingIdentityCheck =
317 read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
318
319 // SSH protocol version (2004.10.11 yutaka)
320 // default is SSH2 (2004.11.30 yutaka)
321 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
322
323 // SSH heartbeat time(second) (2004.12.11 yutaka)
324 settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
325
326 // SSH2 keyboard-interactive (2005.1.23 yutaka)
327 // �f�t�H���g���������������BOpenSSH 4.0����keyboard-interactive���\�b�h�����`�������������������A
328 // ���Y���\�b�h���g�����R�l�N�V���������������������B(2005.3.12 yutaka)
329 settings->ssh2_keyboard_interactive = GetPrivateProfileInt("TTSSH", "KeyboardInteractive", 0, fileName);
330
331 // �p�X���[�h�F�����������J���F�����g���p�X���[�h����������������������������������
332 // �\���B(2006.8.5 yutaka)
333 settings->remember_password = GetPrivateProfileInt("TTSSH", "RememberPassword", 1, fileName);
334
335 clear_local_settings(pvar);
336 }
337
338 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
339 TS_SSH FAR * settings, BOOL copy_forward)
340 {
341 char buf[1024];
342
343 WritePrivateProfileString("TTSSH", "Enabled",
344 settings->Enabled ? "1" : "0", fileName);
345
346 _itoa(settings->CompressionLevel, buf, 10);
347 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
348
349 WritePrivateProfileString("TTSSH", "DefaultUserName",
350 settings->DefaultUserName, fileName);
351
352 if (copy_forward) {
353 WritePrivateProfileString("TTSSH", "DefaultForwarding",
354 settings->DefaultForwarding, fileName);
355 }
356
357 WritePrivateProfileString("TTSSH", "CipherOrder",
358 settings->CipherOrder, fileName);
359
360 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
361 settings->KnownHostsFiles, fileName);
362
363 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
364 settings->DefaultRhostsLocalUserName,
365 fileName);
366
367 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
368 settings->DefaultRhostsHostPrivateKeyFile,
369 fileName);
370
371 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
372 settings->DefaultRSAPrivateKeyFile,
373 fileName);
374
375 _itoa(settings->DefaultAuthMethod, buf, 10);
376 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
377
378 _itoa(settings->LogLevel, buf, 10);
379 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
380
381 _itoa(settings->WriteBufferSize, buf, 10);
382 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
383
384 WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
385 settings->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 #else
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(pvar, *buf == '"' ? buf + 1 : buf)) {
1448 memset(option, ' ', i + 1 - (option - param));
1449 } else {
1450 param[i] = ch;
1451 }
1452 free(buf);
1453 }
1454 else {
1455 if (parse_option(pvar, *option == '"' ? option + 1 : option)) {
1456 memset(option, ' ', i + 1 - (option - param));
1457 } else {
1458 param[i] = ch;
1459 }
1460 }
1461 option = NULL;
1462 }
1463 inParam = FALSE;
1464 inQuotes = FALSE;
1465 inFileParam = FALSE;
1466 } else if (!inParam) {
1467 if (param[i] == '"') {
1468 inQuotes = TRUE;
1469 inParam = TRUE;
1470 option = param + i;
1471 } else if (param[i] != ' ' && param[i] != '\t') {
1472 inParam = TRUE;
1473 option = param + i;
1474 }
1475 } else {
1476 if (option == NULL) {
1477 continue;
1478 }
1479 if ((option[0] == '-' || option[0] == '/') &&
1480 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1481 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1482 MATCH_STR_I(option + 1, "f=") == 0 ||
1483 MATCH_STR(option + 1, "keyfile=") == 0)) {
1484 if (param[i] == '"') {
1485 inQuotes = TRUE;
1486 }
1487 inFileParam = TRUE;
1488 }
1489 }
1490 }
1491
1492 if (option != NULL) {
1493 PCHAR Equal = strchr(option, '=');
1494 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1495 int buf_len = strlen(option) * sizeof(char);
1496 char *buf = (char *)calloc(strlen(option), sizeof(char));
1497 char c = option[Equal - option + 1];
1498 option[Equal - option + 1] = 0;
1499 strncat_s(buf, buf_len, option, _TRUNCATE);
1500 option[Equal - option + 1] = c;
1501 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1502 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1503 memset(option, ' ', i + 1 - (option - param));
1504 }
1505 free(buf);
1506 }
1507 else {
1508 if (parse_option(pvar, option)) {
1509 memset(option, ' ', i - (option - param));
1510 }
1511 }
1512 }
1513
1514 FWDUI_load_settings(pvar);
1515
1516 (pvar->ParseParam) (param, ts, DDETopic);
1517
1518 }
1519
1520 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1521 {
1522 GET_VAR();
1523
1524 pvar->ReadIniFile = *hooks->ReadIniFile;
1525 pvar->WriteIniFile = *hooks->WriteIniFile;
1526 pvar->ParseParam = *hooks->ParseParam;
1527
1528 *hooks->ReadIniFile = TTXReadINIFile;
1529 *hooks->WriteIniFile = TTXWriteINIFile;
1530 *hooks->ParseParam = TTXParseParam;
1531 }
1532
1533 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1534 {
1535 GET_VAR();
1536
1537 SSH_notify_win_size(pvar, cols, rows);
1538 }
1539
1540 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1541 WORD newItemID, char FAR * text)
1542 {
1543 int i, j;
1544
1545 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1546 HMENU submenu = GetSubMenu(menu, i);
1547
1548 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1549 if (GetMenuItemID(submenu, j) == beforeItemID) {
1550 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID, text);
1551 return;
1552 }
1553 }
1554 }
1555 }
1556
1557 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1558 {
1559 GET_VAR();
1560
1561 /* inserts before ID_HELP_ABOUT */
1562 UTIL_get_lang_msg("MENU_ABOUT", pvar, "About &TTSSH...");
1563 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1564
1565 /* inserts before ID_SETUP_TCPIP */
1566 UTIL_get_lang_msg("MENU_SSH", pvar, "SS&H...");
1567 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1568 /* inserts before ID_SETUP_TCPIP */
1569 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar, "SSH &Authentication...");
1570 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1571 /* inserts before ID_SETUP_TCPIP */
1572 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar, "SSH F&orwarding...");
1573 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1574 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar, "SSH KeyGe&nerator...");
1575 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1576 }
1577
1578 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1579 {
1580 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1581 (LPARAM) prefix);
1582 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1583 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1584 (LPARAM) (char FAR *) "\r\n");
1585 }
1586
1587 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1588 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1589 {
1590 typedef struct {
1591 WORD wLanguage;
1592 WORD wCodePage;
1593 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1594 LPLANGANDCODEPAGE lplgcode;
1595 UINT unLen;
1596 DWORD size;
1597 char *buf = NULL;
1598 BOOL ret;
1599 int i;
1600 char fmt[80];
1601 char *pbuf;
1602
1603 size = GetFileVersionInfoSize(exefile, NULL);
1604 if (size == 0) {
1605 goto error;
1606 }
1607 buf = malloc(size);
1608 ZeroMemory(buf, size);
1609
1610 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1611 goto error;
1612 }
1613
1614 ret = VerQueryValue(buf,
1615 "\\VarFileInfo\\Translation",
1616 (LPVOID *)&lplgcode, &unLen);
1617 if (ret == FALSE)
1618 goto error;
1619
1620 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1621 _snprintf_s(fmt, sizeof(fmt), _TRUNCATE,
1622 "\\StringFileInfo\\%04x%04x\\FileVersion",
1623 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1624 VerQueryValue(buf, fmt, &pbuf, &unLen);
1625 if (unLen > 0) { // get success
1626 int n, a, b, c, d;
1627
1628 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1629 if (n == 4) { // convert success
1630 *major = a;
1631 *minor = b;
1632 *release = c;
1633 *build = d;
1634 break;
1635 }
1636 }
1637 }
1638
1639 free(buf);
1640 return;
1641
1642 error:
1643 free(buf);
1644 *major = *minor = *release = *build = 0;
1645 }
1646
1647 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1648 {
1649 char buf[1024];
1650 int a, b, c, d;
1651 char uimsg[MAX_UIMSG];
1652
1653 GetWindowText(dlg, uimsg, sizeof(uimsg));
1654 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar, uimsg);
1655 SetWindowText(dlg, pvar->ts->UIMsg);
1656 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1657 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
1658 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1659
1660 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1661 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1662 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1663 "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1664 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1665
1666 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1667 // ���������� (2005.5.11 yutaka)
1668 #ifdef OPENSSL_VERSION_TEXT
1669 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1670 #else
1671 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1672 #endif
1673
1674 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1675 #ifdef ZLIB_VERSION
1676 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
1677 #else
1678 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1679 #endif
1680 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1681
1682
1683 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1684 if (pvar->socket != INVALID_SOCKET) {
1685 if (SSHv1(pvar)) {
1686 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1687 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1688 append_about_text(dlg, pvar->ts->UIMsg, buf);
1689 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1690 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1691 append_about_text(dlg, pvar->ts->UIMsg, buf);
1692 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1693 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1694 append_about_text(dlg, pvar->ts->UIMsg, buf);
1695 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1696 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1697 append_about_text(dlg, pvar->ts->UIMsg, buf);
1698 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1699 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1700 append_about_text(dlg, pvar->ts->UIMsg, buf);
1701 SSH_get_compression_info(pvar, buf, sizeof(buf));
1702 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1703 append_about_text(dlg, pvar->ts->UIMsg, buf);
1704
1705 } else { // SSH2
1706 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1707 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1708 append_about_text(dlg, pvar->ts->UIMsg, buf);
1709 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar, "Client ID: ");
1710 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1711
1712 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1713 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1714 append_about_text(dlg, pvar->ts->UIMsg, buf);
1715
1716 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1717 strncpy_s(buf, sizeof(buf), KEX_DH1, _TRUNCATE);
1718 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1719 strncpy_s(buf, sizeof(buf), KEX_DH14, _TRUNCATE);
1720 } else {
1721 strncpy_s(buf, sizeof(buf), KEX_DHGEX, _TRUNCATE);
1722 }
1723 append_about_text(dlg, "KEX: ", buf);
1724
1725 if (pvar->hostkey_type == KEY_DSA) {
1726 strncpy_s(buf, sizeof(buf), "ssh-dss", _TRUNCATE);
1727 } else {
1728 strncpy_s(buf, sizeof(buf), "ssh-rsa", _TRUNCATE);
1729 }
1730 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key: ");
1731 append_about_text(dlg, pvar->ts->UIMsg, buf);
1732
1733 // add HMAC algorithm (2004.12.17 yutaka)
1734 buf[0] = '\0';
1735 if (pvar->ctos_hmac == HMAC_SHA1) {
1736 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1737 } else if (pvar->ctos_hmac == HMAC_MD5) {
1738 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1739 }
1740 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar, " to server, ");
1741 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1742 if (pvar->stoc_hmac == HMAC_SHA1) {
1743 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1744 } else if (pvar->stoc_hmac == HMAC_MD5) {
1745 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1746 }
1747 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar, " from server");
1748 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1749 append_about_text(dlg, "HMAC: ", buf);
1750
1751 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1752 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1753 append_about_text(dlg, pvar->ts->UIMsg, buf);
1754 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1755 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1756 append_about_text(dlg, pvar->ts->UIMsg, buf);
1757
1758 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1759 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1760 append_about_text(dlg, pvar->ts->UIMsg, buf);
1761
1762 SSH_get_compression_info(pvar, buf, sizeof(buf));
1763 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1764 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar, "Delayed Compression: ");
1765 append_about_text(dlg, pvar->ts->UIMsg, buf);
1766 } else {
1767 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1768 append_about_text(dlg, pvar->ts->UIMsg, buf);
1769 }
1770 }
1771 }
1772 }
1773
1774 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1775 LPARAM lParam)
1776 {
1777 LOGFONT logfont;
1778 HFONT font;
1779
1780 switch (msg) {
1781 case WM_INITDIALOG:
1782 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1783 GetObject(font, sizeof(LOGFONT), &logfont);
1784 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1785 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1786 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1787 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1788 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1789 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1790 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1791 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1792 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1793 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1794 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1795 }
1796 else {
1797 DlgAboutFont = NULL;
1798 }
1799 init_about_dlg((PTInstVar) lParam, dlg);
1800 return TRUE;
1801 case WM_COMMAND:
1802 switch (LOWORD(wParam)) {
1803 case IDOK:
1804 EndDialog(dlg, 1);
1805 if (DlgAboutFont != NULL) {
1806 DeleteObject(DlgAboutFont);
1807 }
1808 return TRUE;
1809 case IDCANCEL: /* there isn't a cancel button, but other Windows
1810 UI things can send this message */
1811 EndDialog(dlg, 0);
1812 if (DlgAboutFont != NULL) {
1813 DeleteObject(DlgAboutFont);
1814 }
1815 return TRUE;
1816 }
1817 break;
1818 }
1819
1820 return FALSE;
1821 }
1822
1823 static char FAR *get_cipher_name(int cipher)
1824 {
1825 switch (cipher) {
1826 case SSH_CIPHER_NONE:
1827 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
1828 "<ciphers below this line are disabled>");
1829 return pvar->ts->UIMsg;
1830 case SSH_CIPHER_RC4:
1831 return "RC4";
1832 case SSH_CIPHER_3DES:
1833 return "3DES";
1834 case SSH_CIPHER_DES:
1835 return "DES";
1836 case SSH_CIPHER_IDEA:
1837 return "IDEA";
1838 case SSH_CIPHER_TSS:
1839 return "TSS";
1840 case SSH_CIPHER_BLOWFISH:
1841 return "Blowfish";
1842
1843 // for SSH2(yutaka)
1844 case SSH_CIPHER_AES128:
1845 return "AES128(SSH2)";
1846 case SSH_CIPHER_3DES_CBC:
1847 return "3DES-CBC(SSH2)";
1848
1849 default:
1850 return NULL;
1851 }
1852 }
1853
1854 static void set_move_button_status(HWND dlg)
1855 {
1856 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1857 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1858 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1859
1860 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP),
1861 curPos > 0 && curPos <= maxPos);
1862 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN),
1863 curPos >= 0 && curPos < maxPos);
1864 }
1865
1866 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1867 {
1868 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1869 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1870 int i;
1871 int ch;
1872 char uimsg[MAX_UIMSG];
1873
1874 GetWindowText(dlg, uimsg, sizeof(uimsg));
1875 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar, uimsg);
1876 SetWindowText(dlg, pvar->ts->UIMsg);
1877 GetDlgItemText(dlg, IDC_COMPRESSLABEL, uimsg, sizeof(uimsg));
1878 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar, uimsg);
1879 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
1880 GetDlgItemText(dlg, IDC_COMPRESSNONE, uimsg, sizeof(uimsg));
1881 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar, uimsg);
1882 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
1883 GetDlgItemText(dlg, IDC_COMPRESSHIGH, uimsg, sizeof(uimsg));
1884 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar, uimsg);
1885 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
1886 GetDlgItemText(dlg, IDC_CIPHERORDER, uimsg, sizeof(uimsg));
1887 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar, uimsg);
1888 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
1889 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, uimsg, sizeof(uimsg));
1890 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar, uimsg);
1891 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
1892 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, uimsg, sizeof(uimsg));
1893 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar, uimsg);
1894 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
1895 GetDlgItemText(dlg, IDC_KNOWNHOSTS, uimsg, sizeof(uimsg));
1896 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar, uimsg);
1897 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
1898 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, uimsg, sizeof(uimsg));
1899 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar, uimsg);
1900 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
1901 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, uimsg, sizeof(uimsg));
1902 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar, uimsg);
1903 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
1904 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, uimsg, sizeof(uimsg));
1905 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar, uimsg);
1906 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
1907 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, uimsg, sizeof(uimsg));
1908 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar, uimsg);
1909 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
1910 GetDlgItemText(dlg, IDC_NOTICEBANNER, uimsg, sizeof(uimsg));
1911 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar, uimsg);
1912 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
1913 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1914 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
1915 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1916 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
1917 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
1918 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
1919
1920 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1921 SendMessage(compressionControl, TBM_SETPOS, TRUE,
1922 pvar->settings.CompressionLevel);
1923
1924 normalize_cipher_order(pvar->settings.CipherOrder);
1925
1926 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1927 int cipher = pvar->settings.CipherOrder[i] - '0';
1928 char FAR *name = get_cipher_name(cipher);
1929
1930 if (name != NULL) {
1931 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1932 }
1933 }
1934
1935 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1936 set_move_button_status(dlg);
1937
1938 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1939 i++) {
1940 }
1941 if (ch != 0) {
1942 pvar->settings.KnownHostsFiles[i] = 0;
1943 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1944 pvar->settings.KnownHostsFiles);
1945 pvar->settings.KnownHostsFiles[i] = ch;
1946 SetDlgItemText(dlg, IDC_READONLYFILENAME,
1947 pvar->settings.KnownHostsFiles + i + 1);
1948 } else {
1949 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1950 pvar->settings.KnownHostsFiles);
1951 }
1952
1953 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
1954 {
1955 char buf[10];
1956 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1957 "%d", pvar->settings.ssh_heartbeat_overtime);
1958 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
1959 }
1960
1961 }
1962
1963 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1964 char FAR * basename)
1965 {
1966 int filename_start = 0;
1967 int i;
1968 int ch;
1969
1970 if (basename[0] == '\\' || basename[0] == '/'
1971 || (basename[0] != 0 && basename[1] == ':')) {
1972 strncpy_s(buf, bufsize, basename, _TRUNCATE);
1973 return;
1974 }
1975
1976 GetModuleFileName(NULL, buf, bufsize);
1977 for (i = 0; (ch = buf[i]) != 0; i++) {
1978 if (ch == '\\' || ch == '/' || ch == ':') {
1979 filename_start = i + 1;
1980 }
1981 }
1982
1983 if (bufsize > filename_start) {
1984 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
1985 }
1986 }
1987
1988 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1989 char FAR * basename)
1990 {
1991 char buf[1024];
1992 int filename_start = 0;
1993 int i;
1994 int ch, ch2;
1995
1996 if (basename[0] != '\\' && basename[0] != '/'
1997 && (basename[0] == 0 || basename[1] != ':')) {
1998 strncpy_s(dest, destsize, basename, _TRUNCATE);
1999 return strlen(dest);
2000 }
2001
2002 GetModuleFileName(NULL, buf, sizeof(buf));
2003 for (i = 0; (ch = buf[i]) != 0; i++) {
2004 if (ch == '\\' || ch == '/' || ch == ':') {
2005 filename_start = i + 1;
2006 }
2007 }
2008
2009 for (i = 0; i < filename_start; i++) {
2010 ch = toupper(buf[i]);
2011 ch2 = toupper(basename[i]);
2012
2013 if (ch == ch2 ||
2014 ((ch == '\\' || ch == '/') && (ch2 == '\\' || ch2 == '/'))) {
2015 } else {
2016 break;
2017 }
2018 }
2019
2020 if (i == filename_start) {
2021 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2022 } else {
2023 strncpy_s(dest, destsize, basename, _TRUNCATE);
2024 }
2025 return strlen(dest);
2026 }
2027
2028 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2029 {
2030 char buf[4096];
2031 char buf2[1024];
2032 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2033 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2034 int i, j, buf2index, bufindex;
2035 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2036
2037 pvar->settings.CompressionLevel =
2038 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2039
2040 buf2index = 0;
2041 for (i = 0; i < count; i++) {
2042 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2043
2044 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2045 buf[0] = 0;
2046 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2047 for (j = 0;
2048 j <= SSH_CIPHER_MAX
2049 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2050 }
2051 if (j <= SSH_CIPHER_MAX) {
2052 buf2[buf2index] = '0' + j;
2053 buf2index++;
2054 }
2055 }
2056 }
2057 buf2[buf2index] = 0;
2058 normalize_cipher_order(buf2);
2059 strncpy_s(pvar->settings.CipherOrder, sizeof(pvar->settings.CipherOrder), buf2, _TRUNCATE);
2060
2061 buf[0] = 0;
2062 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2063 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2064 sizeof(pvar->settings.KnownHostsFiles),
2065 buf);
2066 buf[0] = 0;
2067 bufindex = 0;
2068 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2069 for (i = 0; buf[i] != 0; i++) {
2070 if (buf[i] == ';') {
2071 buf[i] = 0;
2072 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2073 pvar->settings.KnownHostsFiles[j] = ';';
2074 j++;
2075 j += copy_teraterm_dir_relative_path(pvar->settings.
2076 KnownHostsFiles + j,
2077 sizeof(pvar->settings.
2078 KnownHostsFiles)
2079 - j, buf + bufindex);
2080 }
2081 bufindex = i + 1;
2082 }
2083 }
2084 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2085 pvar->settings.KnownHostsFiles[j] = ';';
2086 j++;
2087 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2088 sizeof(pvar->settings. KnownHostsFiles) - j,
2089 buf + bufindex);
2090 }
2091
2092 // get SSH HeartBeat(keep-alive)
2093 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2094 i = atoi(buf);
2095 if (i < 0)
2096 i = 60;
2097 pvar->settings.ssh_heartbeat_overtime = i;
2098
2099 }
2100
2101 static void move_cur_sel_delta(HWND listbox, int delta)
2102 {
2103 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2104 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2105 int newPos = curPos + delta;
2106 char buf[1024];
2107
2108 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2109 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2110
2111 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2112 buf[0] = 0;
2113 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2114 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2115 SendMessage(listbox, LB_INSERTSTRING, newPos,
2116 (LPARAM) (char FAR *) buf);
2117 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2118 }
2119 }
2120 }
2121
2122 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2123 int readonly)
2124 {
2125 OPENFILENAME params;
2126 char fullname_buf[2048] = "ssh_known_hosts";
2127
2128 params.lStructSize = sizeof(OPENFILENAME);
2129 params.hwndOwner = parent;
2130 params.lpstrFilter = NULL;
2131 params.lpstrCustomFilter = NULL;
2132 params.nFilterIndex = 0;
2133 buf[0] = 0;
2134 params.lpstrFile = fullname_buf;
2135 params.nMaxFile = sizeof(fullname_buf);
2136 params.lpstrFileTitle = NULL;
2137 params.lpstrInitialDir = NULL;
2138 if (readonly) {
2139 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar,
2140 "Choose a read-only known-hosts file to add");
2141 }
2142 else {
2143 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar,
2144 "Choose a read/write known-hosts file");
2145 }
2146 params.lpstrTitle = pvar->ts->UIMsg;
2147 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2148 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2149 params.lpstrDefExt = NULL;
2150
2151 if (GetOpenFileName(&params) != 0) {
2152 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2153 return 1;
2154 } else {
2155 int err = CommDlgExtendedError();
2156
2157 if (err != 0) {
2158 char buf[1024];
2159 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar,
2160 "Unable to display file dialog box: error %d");
2161 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, err);
2162 MessageBox(parent, buf, "TTSSH Error",
2163 MB_OK | MB_ICONEXCLAMATION);
2164 }
2165
2166 return 0;
2167 }
2168 }
2169
2170 static void choose_read_write_file(HWND dlg)
2171 {
2172 char buf[1024];
2173
2174 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2175 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2176 }
2177 }
2178
2179 static void choose_read_only_file(HWND dlg)
2180 {
2181 char buf[1024];
2182 char buf2[4096];
2183
2184 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2185 buf2[0] = 0;
2186 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2187 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2188 strncat_s(buf2, sizeof(buf2), ";", _TRUNCATE);
2189 }
2190 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2191 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2192 }
2193 }
2194
2195 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2196 LPARAM lParam)
2197 {
2198 LOGFONT logfont;
2199 HFONT font;
2200
2201 switch (msg) {
2202 case WM_INITDIALOG:
2203 SetWindowLong(dlg, DWL_USER, lParam);
2204 init_setup_dlg((PTInstVar) lParam, dlg);
2205
2206 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2207 GetObject(font, sizeof(LOGFONT), &logfont);
2208 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2209 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2210 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2211 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2212 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2213 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2214 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2215 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2216 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2217 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2218 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2219 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2220 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2221 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2222 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2223 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2224 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2225 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2226 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2227 }
2228 else {
2229 DlgSetupFont = NULL;
2230 }
2231
2232 return TRUE;
2233 case WM_COMMAND:
2234 switch (LOWORD(wParam)) {
2235 case IDOK:
2236 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER), dlg);
2237 EndDialog(dlg, 1);
2238 if (DlgSetupFont != NULL) {
2239 DeleteObject(DlgSetupFont);
2240 }
2241 return TRUE;
2242 case IDCANCEL: /* there isn't a cancel button, but other Windows
2243 UI things can send this message */
2244 EndDialog(dlg, 0);
2245 if (DlgSetupFont != NULL) {
2246 DeleteObject(DlgSetupFont);
2247 }
2248 return TRUE;
2249 case IDC_SSHMOVECIPHERUP:
2250 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2251 set_move_button_status(dlg);
2252 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2253 return TRUE;
2254 case IDC_SSHMOVECIPHERDOWN:
2255 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2256 set_move_button_status(dlg);
2257 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2258 return TRUE;
2259 case IDC_SSHCIPHERPREFS:
2260 set_move_button_status(dlg);
2261 return TRUE;
2262 case IDC_CHOOSEREADWRITEFILE:
2263 choose_read_write_file(dlg);
2264 return TRUE;
2265 case IDC_CHOOSEREADONLYFILE:
2266 choose_read_only_file(dlg);
2267 return TRUE;
2268 }
2269 break;
2270 }
2271
2272 return FALSE;
2273 }
2274
2275
2276 //
2277 // SSH key generator dialog (2005.4.10 yutaka)
2278 //
2279
2280 typedef struct {
2281 RSA *rsa;
2282 DSA *dsa;
2283 } ssh_private_key_t;
2284
2285 static ssh_private_key_t private_key = {NULL, NULL};
2286
2287 typedef struct {
2288 RSA *rsa;
2289 DSA *dsa;
2290 } ssh_public_key_t;
2291
2292 static ssh_public_key_t public_key = {NULL, NULL};;
2293
2294 static void free_ssh_key(void)
2295 {
2296 // DSA_free(), RSA_free()��NULL���n�����������������B
2297 DSA_free(private_key.dsa);
2298 private_key.dsa = NULL;
2299 DSA_free(public_key.dsa);
2300 public_key.dsa = NULL;
2301
2302 RSA_free(private_key.rsa);
2303 private_key.rsa = NULL;
2304 RSA_free(public_key.rsa);
2305 public_key.rsa = NULL;
2306 }
2307
2308
2309 static BOOL generate_ssh_key(enum hostkey_type type)
2310 {
2311 int bits = 1024;
2312
2313 // if SSH key already is generated, should free the resource.
2314 free_ssh_key();
2315
2316 if (type == KEY_RSA1 || type == KEY_RSA) {
2317 RSA *priv = NULL;
2318 RSA *pub = NULL;
2319
2320 // private key
2321 priv = RSA_generate_key(bits, 35, NULL, NULL);
2322 if (priv == NULL)
2323 goto error;
2324 private_key.rsa = priv;
2325
2326 // public key
2327 pub = RSA_new();
2328 pub->n = BN_new();
2329 pub->e = BN_new();
2330 if (pub->n == NULL || pub->e == NULL) {
2331 RSA_free(pub);
2332 goto error;
2333 }
2334
2335 BN_copy(pub->n, priv->n);
2336 BN_copy(pub->e, priv->e);
2337 public_key.rsa = pub;
2338
2339 } else if (type == KEY_DSA) {
2340 DSA *priv = NULL;
2341 DSA *pub = NULL;
2342
2343 // private key
2344 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2345 if (priv == NULL)
2346 goto error;
2347 if (!DSA_generate_key(priv)) {
2348 // TODO: free 'priv'?
2349 goto error;
2350 }
2351 private_key.dsa = priv;
2352
2353 // public key
2354 pub = DSA_new();
2355 if (pub == NULL)
2356 goto error;
2357 pub->p = BN_new();
2358 pub->q = BN_new();
2359 pub->g = BN_new();
2360 pub->pub_key = BN_new();
2361 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2362 DSA_free(pub);
2363 goto error;
2364 }
2365
2366 BN_copy(pub->p, priv->p);
2367 BN_copy(pub->q, priv->q);
2368 BN_copy(pub->g, priv->g);
2369 BN_copy(pub->pub_key, priv->pub_key);
2370 public_key.dsa = pub;
2371
2372 } else {
2373 goto error;
2374 }
2375
2376 return TRUE;
2377
2378 error:
2379 free_ssh_key();
2380 return FALSE;
2381 }
2382
2383
2384 //
2385 // RC4
2386 //
2387
2388 /* Size of key to use */
2389 #define SEED_SIZE 20
2390
2391 /* Number of bytes to reseed after */
2392 #define REKEY_BYTES (1 << 24)
2393
2394 static int rc4_ready = 0;
2395 static RC4_KEY rc4;
2396
2397 static void seed_rng(void)
2398 {
2399 if (RAND_status() != 1)
2400 return;
2401 }
2402
2403 static void arc4random_stir(void)
2404 {
2405 unsigned char rand_buf[SEED_SIZE];
2406 int i;
2407
2408 memset(&rc4, 0, sizeof(rc4));
2409 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2410 //fatal("Couldn't obtain random bytes (error %ld)",
2411 // ERR_get_error());
2412 }
2413 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2414
2415 /*
2416 * Discard early keystream, as per recommendations in:
2417 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2418 */
2419 for(i = 0; i <= 256; i += sizeof(rand_buf))
2420 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2421
2422 memset(rand_buf, 0, sizeof(rand_buf));
2423
2424 rc4_ready = REKEY_BYTES;
2425 }
2426
2427 static unsigned int arc4random(void)
2428 {
2429 unsigned int r = 0;
2430 static int first_time = 1;
2431
2432 if (rc4_ready <= 0) {
2433 if (first_time) {
2434 seed_rng();
2435 }
2436 first_time = 0;
2437 arc4random_stir();
2438 }
2439
2440 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2441
2442 rc4_ready -= sizeof(r);
2443
2444 return(r);
2445 }
2446
2447 //
2448 // SSH1 3DES
2449 //
2450 /*
2451 * This is used by SSH1:
2452 *
2453 * What kind of triple DES are these 2 routines?
2454 *
2455 * Why is there a redundant initialization vector?
2456 *
2457 * If only iv3 was used, then, this would till effect have been
2458 * outer-cbc. However, there is also a private iv1 == iv2 which
2459 * perhaps makes differential analysis easier. On the other hand, the
2460 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2461 * result of that there is no longer any known iv1 to use when
2462 * choosing the X block.
2463 */
2464 struct ssh1_3des_ctx
2465 {
2466 EVP_CIPHER_CTX k1, k2, k3;
2467 };
2468
2469 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2470 {
2471 struct ssh1_3des_ctx *c;
2472 u_char *k1, *k2, *k3;
2473
2474 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2475 c = malloc(sizeof(*c));
2476 EVP_CIPHER_CTX_set_app_data(ctx, c);
2477 }
2478 if (key == NULL)
2479 return (1);
2480 if (enc == -1)
2481 enc = ctx->encrypt;
2482 k1 = k2 = k3 = (u_char *) key;
2483 k2 += 8;
2484 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2485 if (enc)
2486 k3 += 16;
2487 else
2488 k1 += 16;
2489 }
2490 EVP_CIPHER_CTX_init(&c->k1);
2491 EVP_CIPHER_CTX_init(&c->k2);
2492 EVP_CIPHER_CTX_init(&c->k3);
2493 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2494 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2495 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2496 memset(c, 0, sizeof(*c));
2497 free(c);
2498 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2499 return (0);
2500 }
2501 return (1);
2502 }
2503
2504 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2505 {
2506 struct ssh1_3des_ctx *c;
2507
2508 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2509 //error("ssh1_3des_cbc: no context");
2510 return (0);
2511 }
2512 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2513 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2514 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2515 return (0);
2516 return (1);
2517 }
2518
2519 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2520 {
2521 struct ssh1_3des_ctx *c;
2522
2523 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2524 EVP_CIPHER_CTX_cleanup(&c->k1);
2525 EVP_CIPHER_CTX_cleanup(&c->k2);
2526 EVP_CIPHER_CTX_cleanup(&c->k3);
2527 memset(c, 0, sizeof(*c));
2528 free(c);
2529 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2530 }
2531 return (1);
2532 }
2533
2534 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2535 {
2536 struct ssh1_3des_ctx *c;
2537
2538 if (len != 24)
2539 //fatal("%s: bad 3des iv length: %d", __func__, len);
2540 ;
2541
2542 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2543 //fatal("%s: no 3des context", __func__);
2544 ;
2545
2546 if (doset) {
2547 //debug3("%s: Installed 3DES IV", __func__);
2548 memcpy(c->k1.iv, iv, 8);
2549 memcpy(c->k2.iv, iv + 8, 8);
2550 memcpy(c->k3.iv, iv + 16, 8);
2551 } else {
2552 //debug3("%s: Copying 3DES IV", __func__);
2553 memcpy(iv, c->k1.iv, 8);
2554 memcpy(iv + 8, c->k2.iv, 8);
2555 memcpy(iv + 16, c->k3.iv, 8);
2556 }
2557 }
2558
2559 const EVP_CIPHER *evp_ssh1_3des(void)
2560 {
2561 static EVP_CIPHER ssh1_3des;
2562
2563 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2564 ssh1_3des.nid = NID_undef;
2565 ssh1_3des.block_size = 8;
2566 ssh1_3des.iv_len = 0;
2567 ssh1_3des.key_len = 16;
2568 ssh1_3des.init = ssh1_3des_init;
2569 ssh1_3des.cleanup = ssh1_3des_cleanup;
2570 ssh1_3des.do_cipher = ssh1_3des_cbc;
2571 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2572 return (&ssh1_3des);
2573 }
2574
2575 static void ssh_make_comment(char *comment, int maxlen)
2576 {
2577 char user[UNLEN + 1], host[128];
2578 DWORD dwSize;
2579 WSADATA wsaData;
2580 int ret;
2581
2582 // get Windows logon user name
2583 dwSize = sizeof(user);
2584 if (GetUserName(user, &dwSize) == 0) {
2585 strncpy_s(user, sizeof(user), "yutaka", _TRUNCATE);
2586 }
2587
2588 // get local hostname (by WinSock)
2589 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2590 if (ret == 0) {
2591 if (gethostname(host, sizeof(host)) != 0) {
2592 ret = WSAGetLastError();
2593 }
2594 WSACleanup();
2595 }
2596 if (ret != 0) {
2597 strncpy_s(host, sizeof(host), "sai", _TRUNCATE);
2598 }
2599
2600 _snprintf_s(comment, maxlen, _TRUNCATE, "%s@%s", user, host);
2601 }
2602
2603 // uuencode (rfc1521)
2604 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2605 {
2606 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2607 char pad = '=';
2608 int datalength = 0;
2609 unsigned char input[3];
2610 unsigned char output[4];
2611 int i;
2612
2613 while (srclen > 2) {
2614 input[0] = *src++;
2615 input[1] = *src++;
2616 input[2] = *src++;
2617 srclen -= 3;
2618
2619 output[0] = input[0] >> 2;
2620 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2621 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2622 output[3] = input[2] & 0x3f;
2623 if (output[0] >= 64 ||
2624 output[1] >= 64 ||
2625 output[2] >= 64 ||
2626 output[3] >= 64)
2627 return -1;
2628
2629 if (datalength + 4 > targsize)
2630 return (-1);
2631 target[datalength++] = base64[output[0]];
2632 target[datalength++] = base64[output[1]];
2633 target[datalength++] = base64[output[2]];
2634 target[datalength++] = base64[output[3]];
2635 }
2636
2637 if (srclen != 0) {
2638 /* Get what's left. */
2639 input[0] = input[1] = input[2] = '\0';
2640 for (i = 0; i < srclen; i++)
2641 input[i] = *src++;
2642
2643 output[0] = input[0] >> 2;
2644 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2645 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2646 if (output[0] >= 64 ||
2647 output[1] >= 64 ||
2648 output[2] >= 64)
2649 return -1;
2650
2651 if (datalength + 4 > targsize)
2652 return (-1);
2653 target[datalength++] = base64[output[0]];
2654 target[datalength++] = base64[output[1]];
2655 if (srclen == 1)
2656 target[datalength++] = pad;
2657 else
2658 target[datalength++] = base64[output[2]];
2659 target[datalength++] = pad;
2660 }
2661 if (datalength >= targsize)
2662 return (-1);
2663 target[datalength] = '\0'; /* Returned value doesn't count \0. */
2664
2665 return (datalength); // success
2666 }
2667
2668 static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2669 LPARAM lParam)
2670 {
2671 static enum hostkey_type key_type;
2672 char uimsg[MAX_UIMSG];
2673 LOGFONT logfont;
2674 HFONT font;
2675
2676 switch (msg) {
2677 case WM_INITDIALOG:
2678 {
2679 GetWindowText(dlg, uimsg, sizeof(uimsg));
2680 UTIL_get_lang_msg("DLG_KEYGEN_TITLE", pvar, uimsg);
2681 SetWindowText(dlg, pvar->ts->UIMsg);
2682 GetDlgItemText(dlg, IDC_KEYTYPE, uimsg, sizeof(uimsg));
2683 UTIL_get_lang_msg("DLG_KEYGEN_KEYTYPE", pvar, uimsg);
2684 SetDlgItemText(dlg, IDC_KEYTYPE, pvar->ts->UIMsg);
2685 GetDlgItemText(dlg, IDC_KEY_LABEL, uimsg, sizeof(uimsg));
2686 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE", pvar, uimsg);
2687 SetDlgItemText(dlg, IDC_KEY_LABEL, pvar->ts->UIMsg);
2688 GetDlgItemText(dlg, IDC_CONFIRM_LABEL, uimsg, sizeof(uimsg));
2689 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE2", pvar, uimsg);
2690 SetDlgItemText(dlg, IDC_CONFIRM_LABEL, pvar->ts->UIMsg);
2691 GetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, uimsg, sizeof(uimsg));
2692 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPUBLIC", pvar, uimsg);
2693 SetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, pvar->ts->UIMsg);
2694 GetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, uimsg, sizeof(uimsg));
2695 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPRIVATE", pvar, uimsg);
2696 SetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, pvar->ts->UIMsg);
2697 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2698 UTIL_get_lang_msg("DLG_KEYGEN_GENERATE", pvar, uimsg);
2699 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2700 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2701 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
2702 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2703
2704 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2705 GetObject(font, sizeof(LOGFONT), &logfont);
2706 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgKeygenFont, pvar)) {
2707 SendDlgItemMessage(dlg, IDC_KEYTYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2708 SendDlgItemMessage(dlg, IDC_RSA1_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2709 SendDlgItemMessage(dlg, IDC_RSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2710 SendDlgItemMessage(dlg, IDC_DSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2711 SendDlgItemMessage(dlg, IDC_KEY_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2712 SendDlgItemMessage(dlg, IDC_CONFIRM_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2713 SendDlgItemMessage(dlg, IDC_KEY_EDIT, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2714 SendDlgItemMessage(dlg, IDC_CONFIRM_EDIT, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2715 SendDlgItemMessage(dlg, IDC_SAVE_PUBLIC_KEY, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2716 SendDlgItemMessage(dlg, IDC_SAVE_PRIVATE_KEY, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2717 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2718 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2719 }
2720 else {
2721 DlgHostFont = NULL;
2722 }
2723
2724 // default key type
2725 SendMessage(GetDlgItem(dlg, IDC_RSA_TYPE), BM_SETCHECK, BST_CHECKED, 0);
2726 key_type = KEY_RSA;
2727
2728 // passphrase edit box disabled(default)
2729 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2730 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2731
2732 // file saving dialog disabled(default)
2733 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2734 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2735
2736 }
2737 return TRUE;
2738
2739 case WM_COMMAND:
2740 switch (LOWORD(wParam)) {
2741 case IDOK: // key generate button pressed
2742 // passphrase edit box disabled(default)
2743 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2744 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2745
2746 // file saving dialog disabled(default)
2747 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2748 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2749
2750 if (generate_ssh_key(key_type)) {
2751 // passphrase edit box disabled(default)
2752 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), TRUE);
2753 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), TRUE);
2754
2755 // file saving dialog disabled(default)
2756 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), TRUE);
2757 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), TRUE);
2758
2759 // set focus to passphrase edit control (2007.1.27 maya)
2760 SetFocus(GetDlgItem(dlg, IDC_KEY_EDIT));
2761 }
2762 return TRUE;
2763
2764 case IDCANCEL:
2765 // don't forget to free SSH resource!
2766 free_ssh_key();
2767 EndDialog(dlg, 0); // dialog close
2768 if (DlgKeygenFont != NULL) {
2769 DeleteObject(DlgKeygenFont);
2770 }
2771 return TRUE;
2772
2773 // if radio button pressed...
2774 case IDC_RSA1_TYPE | (BN_CLICKED << 16):
2775 key_type = KEY_RSA1;
2776 break;
2777
2778 case IDC_RSA_TYPE | (BN_CLICKED << 16):
2779 key_type = KEY_RSA;
2780 break;
2781
2782 case IDC_DSA_TYPE | (BN_CLICKED << 16):
2783 key_type = KEY_DSA;
2784 break;
2785
2786 // saving public key file
2787 case IDC_SAVE_PUBLIC_KEY:
2788 {
2789 int ret;
2790 OPENFILENAME ofn;
2791 char filename[MAX_PATH];
2792 FILE *fp;
2793 char comment[1024]; // comment string in private key
2794
2795 arc4random_stir();
2796
2797 // saving file dialog
2798 ZeroMemory(&ofn, sizeof(ofn));
2799 ofn.lStructSize = sizeof(ofn);
2800 ofn.hwndOwner = dlg;
2801 if (key_type == KEY_RSA1) {
2802 UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_RSA1_FILTER", pvar,
2803 "SSH1 RSA key(identity.pub)\\0identity.pub\\0All Files(*.*)\\0*.*\\0\\0");
2804 memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg));
2805 ofn.lpstrFilter = uimsg;
2806 strncpy_s(filename, sizeof(filename), "identity.pub", _TRUNCATE);
2807 } else if (key_type == KEY_RSA) {
2808 UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_RSA_FILTER", pvar,
2809 "SSH2 RSA key(id_rsa.pub)\\0id_rsa.pub\\0All Files(*.*)\\0*.*\\0\\0");
2810 memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg));
2811 ofn.lpstrFilter = uimsg;
2812 strncpy_s(filename, sizeof(filename), "id_rsa.pub", _TRUNCATE);
2813 } else {
2814 UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_DSA_FILTER", pvar,
2815 "SSH2 DSA key(id_dsa.pub)\\0id_dsa.pub\\0All Files(*.*)\\0*.*\\0\\0");
2816 memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg));
2817 ofn.lpstrFilter = uimsg;
2818 strncpy_s(filename, sizeof(filename), "id_dsa.pub", _TRUNCATE);
2819 }
2820 ofn.lpstrFile = filename;
2821 ofn.nMaxFile = sizeof(filename);
2822 UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_TITLE", pvar,
2823 "Save public key as:");
2824 ofn.lpstrTitle = pvar->ts->UIMsg;
2825 if (GetSaveFileName(&ofn) == 0) { // failure
2826 ret = CommDlgExtendedError();
2827 break;
2828 }
2829
2830 ssh_make_comment(comment, sizeof(comment));
2831
2832 // saving public key file
2833 fp = fopen(filename, "wb");
2834 if (fp == NULL) {
2835 UTIL_get_lang_msg("MSG_SAVE_KEY_OPENFILE_ERROR", pvar,
2836 "Can't open key file");
2837 strncpy_s(uimsg, sizeof(uimsg), pvar->ts->UIMsg