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 3010 - (show annotations) (download) (as text)
Wed Sep 5 14:51:28 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109935 byte(s)
接続ダイアログのホスト名ドロップダウンにおいて、Ctrl+b/Ctrl+f をサポートした。

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