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 3021 - (show annotations) (download) (as text)
Wed Oct 3 11:44:52 2007 UTC (16 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109832 byte(s)
シリアルポートの最大値を 256 に変更した。
管理テーブルの型を unsigned char から WORD に変更した。

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