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 3155 - (show annotations) (download) (as text)
Sun Oct 19 05:58:09 2008 UTC (15 years, 5 months ago) by yutakapon
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118250 byte(s)
Historyボックスのenable/disableを追加した。

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