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 3168 - (show annotations) (download) (as text)
Fri Nov 21 18:54:22 2008 UTC (15 years, 4 months ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118598 byte(s)
SSH2 の共通鍵暗号として Arcfour をサポート (yasuhide) [Ttssh2-devel 1250]

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