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 3112 - (show annotations) (download) (as text)
Sat Feb 16 10:18:11 2008 UTC (16 years, 1 month ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 116830 byte(s)
SSH1 でもメッセージを MessageBox を表示するように戻した。

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