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 3166 - (show annotations) (download) (as text)
Wed Nov 19 22:39:47 2008 UTC (15 years, 4 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118522 byte(s)
_strdup しなくてもよかったので修正

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