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