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 3146 - (show annotations) (download) (as text)
Thu Sep 11 06:57:52 2008 UTC (15 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 118108 byte(s)
SSH2 RSA 接続で、サーバの鍵長が 768 bit 以下のときにも接続する設定項目を追加した。
teraterm.ini への直接指定のみ有効となる。
推奨されない設定なので、ドキュメントには書かない。

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