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 3107 - (show annotations) (download) (as text)
Mon Feb 11 12:26:39 2008 UTC (16 years, 2 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 116275 byte(s)
SFTP debug用ボタンを追加。
debug buildで出現します。

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