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 3169 - (show annotations) (download) (as text)
Sat Nov 22 06:46:43 2008 UTC (15 years, 4 months ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118774 byte(s)
SSH2 の共通鍵暗号方式として Arcfour128, Arcfour256 をサポート

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