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 3005 - (show annotations) (download) (as text)
Thu Aug 30 12:42:06 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107120 byte(s)
New connection ダイアログの Host の最大値を定数で持つようにした。

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