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 3163 - (show annotations) (download) (as text)
Wed Nov 19 14:00:14 2008 UTC (15 years, 4 months ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118318 byte(s)
GET_VER()を削除。

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