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 3008 - (show annotations) (download) (as text)
Tue Sep 4 13:40:18 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109119 byte(s)
接続ダイアログのホスト名ドロップダウンにおいて、Ctrl+n/Ctrl+p を使って上下できるようにした。

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