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 3067 - (show annotations) (download) (as text)
Thu Nov 8 14:53:21 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 112280 byte(s)
/ssh-acceptall コマンドラインオプションを追加した。

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