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 3096 - (show annotations) (download) (as text)
Sat Jan 19 15:02:03 2008 UTC (16 years, 2 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 116155 byte(s)
SFTPサポートのためのフレームワークを追加。動作上は影響ありません。

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