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 3007 - (show annotations) (download) (as text)
Sun Sep 2 05:20:58 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107427 byte(s)
接続ダイアログに使用中のシリアルポートを表示しないようにした。

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