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 3170 - (show annotations) (download) (as text)
Sat Nov 22 10:05:33 2008 UTC (15 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118862 byte(s)
SSH2 の共通鍵暗号方式として CAST128-CBC をサポート

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