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 3028 - (show annotations) (download) (as text)
Thu Oct 4 15:41:56 2007 UTC (16 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 110838 byte(s)
Fix typo.

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 // C-d/C-k ���T�|�[�g (2007.10.3 yutaka)
809 // �h���b�v�_�E���������G�f�B�b�g�R���g���[����
810 // �T�u�N���X�������������E�C���h�E�v���V�[�W��
811 WNDPROC OrigHostnameEditProc; // Original window procedure
812 LRESULT CALLBACK HostnameEditProc(HWND dlg, UINT msg,
813 WPARAM wParam, LPARAM lParam)
814 {
815 HWND parent;
816 int max, select, len;
817 char *str;
818
819 switch (msg) {
820 // �L�[�����������������m����
821 case WM_KEYDOWN:
822 if (GetKeyState(VK_CONTROL) < 0) {
823 switch (wParam) {
824 case 0x50: // Ctrl+p ... up
825 parent = GetParent(dlg);
826 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
827 if (select > 0) {
828 PostMessage(parent, CB_SETCURSEL, select - 1, 0);
829 }
830 return 0;
831 case 0x4e: // Ctrl+n ... down
832 parent = GetParent(dlg);
833 max = SendMessage(parent, CB_GETCOUNT, 0, 0);
834 select = SendMessage(parent, CB_GETCURSEL, 0, 0);
835 if (select < max - 1) {
836 PostMessage(parent, CB_SETCURSEL, select + 1, 0);
837 }
838 return 0;
839 case 0x42: // Ctrl+b ... left
840 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
841 PostMessage(dlg, EM_SETSEL, select-1, select-1);
842 return 0;
843 case 0x46: // Ctrl+f ... right
844 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
845 max = GetWindowTextLength(dlg) ;
846 PostMessage(dlg, EM_SETSEL, select+1, select+1);
847 return 0;
848 case 0x41: // Ctrl+a ... home
849 PostMessage(dlg, EM_SETSEL, 0, 0);
850 return 0;
851 case 0x45: // Ctrl+e ... end
852 max = GetWindowTextLength(dlg) ;
853 PostMessage(dlg, EM_SETSEL, max, max);
854 return 0;
855
856 case 0x44: // Ctrl+d
857 case 0x4b: // Ctrl+k
858 SendMessage(dlg, EM_GETSEL, 0, (LPARAM)&select);
859 max = GetWindowTextLength(dlg);
860 max++; // '\0'
861 str = malloc(max);
862 if (str != NULL) {
863 len = GetWindowText(dlg, str, max);
864 if (select >= 0 && select < len) {
865 if (wParam == 0x44) { // �J�[�\���z����������������������
866 memmove(&str[select], &str[select + 1], len - select - 1);
867 str[len - 1] = '\0';
868
869 } else if (wParam == 0x4b) { // �J�[�\�������s��������������
870 str[select] = '\0';
871 }
872
873 SetWindowText(dlg, str);
874 SendMessage(dlg, EM_SETSEL, select, select);
875 }
876 free(str);
877 return 0;
878 }
879 break;
880 }
881 }
882 break;
883
884 // �����L�[��������������������������������������������
885 case WM_CHAR:
886 switch (wParam) {
887 case 0x01:
888 case 0x02:
889 case 0x04:
890 case 0x05:
891 case 0x06:
892 case 0x0b:
893 case 0x0e:
894 case 0x10:
895 return 0;
896 }
897 }
898
899 return CallWindowProc(OrigHostnameEditProc, dlg, msg, wParam, lParam);
900 }
901
902 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
903 LPARAM lParam)
904 {
905 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
906 PGetHNRec GetHNRec;
907 char EntName[128];
908 char TempHost[HostNameMaxLength + 1];
909 WORD i, j, w;
910 WORD ComPortTable[MAXCOMPORT];
911 static char *ComPortDesc[MAXCOMPORT];
912 int comports;
913 BOOL Ok;
914 LOGFONT logfont;
915 HFONT font;
916 char uimsg[MAX_UIMSG];
917 HWND hwndHostname = NULL; // HOSTNAME dropdown
918 HWND hwndHostnameEdit = NULL; // Edit control on HOSTNAME dropdown
919
920 GET_VAR();
921
922 switch (msg) {
923 case WM_INITDIALOG:
924 GetHNRec = (PGetHNRec) lParam;
925 SetWindowLong(dlg, DWL_USER, lParam);
926
927 GetWindowText(dlg, uimsg, sizeof(uimsg));
928 UTIL_get_lang_msg("DLG_HOST_TITLE", pvar, uimsg);
929 SetWindowText(dlg, pvar->ts->UIMsg);
930 GetDlgItemText(dlg, IDC_HOSTNAMELABEL, uimsg, sizeof(uimsg));
931 UTIL_get_lang_msg("DLG_HOST_TCPIP_HOST", pvar, uimsg);
932 SetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg);
933 GetDlgItemText(dlg, IDC_HISTORY, uimsg, sizeof(uimsg));
934 UTIL_get_lang_msg("DLG_HOST_TCPIP_HISTORY", pvar, uimsg);
935 SetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg);
936 GetDlgItemText(dlg, IDC_SERVICELABEL, uimsg, sizeof(uimsg));
937 UTIL_get_lang_msg("DLG_HOST_TCPIP_SERVICE", pvar, uimsg);
938 SetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg);
939 GetDlgItemText(dlg, IDC_HOSTOTHER, uimsg, sizeof(uimsg));
940 UTIL_get_lang_msg("DLG_HOST_TCPIP_OTHER", pvar, uimsg);
941 SetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg);
942 GetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, uimsg, sizeof(uimsg));
943 UTIL_get_lang_msg("DLG_HOST_TCPIP_PORT", pvar, uimsg);
944 SetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg);
945 GetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, uimsg, sizeof(uimsg));
946 UTIL_get_lang_msg("DLG_HOST_TCPIP_SSHVERSION", pvar, uimsg);
947 SetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg);
948 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, uimsg, sizeof(uimsg));
949 UTIL_get_lang_msg("DLG_HOST_TCPIP_PROTOCOL", pvar, uimsg);
950 SetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg);
951 GetDlgItemText(dlg, IDC_HOSTSERIAL, uimsg, sizeof(uimsg));
952 UTIL_get_lang_msg("DLG_HOST_SERIAL", pvar, uimsg);
953 SetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg);
954 GetDlgItemText(dlg, IDC_HOSTCOMLABEL, uimsg, sizeof(uimsg));
955 UTIL_get_lang_msg("DLG_HOST_SERIAL_PORT", pvar, uimsg);
956 SetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg);
957 GetDlgItemText(dlg, IDC_HOSTHELP, uimsg, sizeof(uimsg));
958 UTIL_get_lang_msg("DLG_HOST_HELP", pvar, uimsg);
959 SetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg);
960 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
961 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
962 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
963 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
964 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
965 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
966
967 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
968 if (pvar->ts->HistoryList > 0) {
969 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
970 } else {
971 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
972 }
973
974 if (GetHNRec->PortType == IdFile)
975 GetHNRec->PortType = IdTCPIP;
976
977 strncpy_s(EntName, sizeof(EntName), "Host", _TRUNCATE);
978
979 i = 1;
980 do {
981 _snprintf_s(&EntName[4], sizeof(EntName)-4, _TRUNCATE, "%d", i);
982 GetPrivateProfileString("Hosts", EntName, "",
983 TempHost, sizeof(TempHost),
984 GetHNRec->SetupFN);
985 if (strlen(TempHost) > 0)
986 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
987 0, (LPARAM) TempHost);
988 i++;
989 } while ((i <= MAXHOSTLIST) && (strlen(TempHost) > 0));
990
991 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
992 HostNameMaxLength - 1, 0);
993
994 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
995
996 // C-n/C-p ���������T�u�N���X�� (2007.9.4 maya)
997 hwndHostname = GetDlgItem(dlg, IDC_HOSTNAME);
998 hwndHostnameEdit = GetWindow(hwndHostname, GW_CHILD);
999 OrigHostnameEditProc = (WNDPROC)GetWindowLong(hwndHostnameEdit, GWL_WNDPROC);
1000 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)HostnameEditProc);
1001
1002 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1003 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1004 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1005 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1006 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1007 #ifndef NO_INET6
1008 for (i = 0; ProtocolFamilyList[i]; ++i) {
1009 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1010 0, (LPARAM) ProtocolFamilyList[i]);
1011 }
1012 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1013 ProtocolFamilyMaxLength - 1, 0);
1014 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1015 #endif /* NO_INET6 */
1016
1017 /////// SSH version
1018 for (i = 0; ssh_version[i]; ++i) {
1019 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1020 0, (LPARAM) ssh_version[i]);
1021 }
1022 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1023 NUM_ELEM(ssh_version) - 1, 0);
1024
1025 if (pvar->settings.ssh_protocol_version == 1) {
1026 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1027 } else {
1028 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1029 }
1030
1031 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1032 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1033 } else {
1034 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1035 }
1036 /////// SSH version
1037
1038
1039 j = 0;
1040 w = 1;
1041 if ((comports=DetectComPorts(ComPortTable, GetHNRec->MaxComPort, ComPortDesc)) >= 0) {
1042 for (i=0; i<comports; i++) {
1043 // MaxComPort ���z�����|�[�g���\��������
1044 if (ComPortTable[i] > GetHNRec->MaxComPort) {
1045 continue;
1046 }
1047
1048 // �g�p�����|�[�g���\��������
1049 if (CheckCOMFlag(ComPortTable[i]) == 1) {
1050 continue;
1051 }
1052
1053 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", ComPortTable[i]);
1054 if (ComPortDesc[i] != NULL) {
1055 strncat_s(EntName, sizeof(EntName), ": ", _TRUNCATE);
1056 strncat_s(EntName, sizeof(EntName), ComPortDesc[i], _TRUNCATE);
1057 }
1058 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1059 0, (LPARAM)EntName);
1060 j++;
1061 if (GetHNRec->ComPort == ComPortTable[i])
1062 w = j;
1063 }
1064
1065 } else {
1066 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1067 // �g�p�����|�[�g���\��������
1068 if (CheckCOMFlag(i) == 1) {
1069 continue;
1070 }
1071
1072 _snprintf_s(EntName, sizeof(EntName), _TRUNCATE, "COM%d", i);
1073 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1074 0, (LPARAM) EntName);
1075 j++;
1076 if (GetHNRec->ComPort == i)
1077 w = j;
1078 }
1079 }
1080
1081 if (j > 0)
1082 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1083 else { /* All com ports are already used */
1084 GetHNRec->PortType = IdTCPIP;
1085 enable_dlg_items(dlg, IDC_HOSTSERIAL, IDC_HOSTSERIAL, FALSE);
1086 }
1087
1088 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
1089 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
1090
1091 if (GetHNRec->PortType == IdTCPIP) {
1092 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1093
1094 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1095 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1096 }
1097 #ifndef NO_INET6
1098 else {
1099 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1100 FALSE);
1101 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1102 IDC_HOSTTCPPROTOCOL, FALSE);
1103
1104 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1105 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1106 }
1107 #else
1108 else
1109 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1110 FALSE);
1111 #endif /* NO_INET6 */
1112
1113 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1114 if (GetHNRec->PortType == IdTCPIP) {
1115 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1116 SetFocus(hwnd);
1117 } else {
1118 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1119 SetFocus(hwnd);
1120 }
1121
1122 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1123 GetObject(font, sizeof(LOGFONT), &logfont);
1124 if (UTIL_get_lang_font("DLG_SYSTEM_FONT", dlg, &logfont, &DlgHostFont, pvar)) {
1125 SendDlgItemMessage(dlg, IDC_HOSTTCPIP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1126 SendDlgItemMessage(dlg, IDC_HOSTNAMELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1127 SendDlgItemMessage(dlg, IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1128 SendDlgItemMessage(dlg, IDC_HISTORY, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1129 SendDlgItemMessage(dlg, IDC_SERVICELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1130 SendDlgItemMessage(dlg, IDC_HOSTTELNET, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1131 SendDlgItemMessage(dlg, IDC_HOSTSSH, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1132 SendDlgItemMessage(dlg, IDC_HOSTOTHER, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1133 SendDlgItemMessage(dlg, IDC_HOSTTCPPORTLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1134 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1135 SendDlgItemMessage(dlg, IDC_SSH_VERSION_LABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1136 SendDlgItemMessage(dlg, IDC_SSH_VERSION, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1137 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOLLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1138 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1139 SendDlgItemMessage(dlg, IDC_HOSTSERIAL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1140 SendDlgItemMessage(dlg, IDC_HOSTCOMLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1141 SendDlgItemMessage(dlg, IDC_HOSTCOM, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1142 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1143 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1144 SendDlgItemMessage(dlg, IDC_HOSTHELP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1145 }
1146 else {
1147 DlgHostFont = NULL;
1148 }
1149
1150 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1151 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1152 // (2004.11.23 yutaka)
1153 return FALSE;
1154 //return TRUE;
1155
1156 case WM_COMMAND:
1157 switch (LOWORD(wParam)) {
1158 case IDOK:
1159 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1160 if (GetHNRec != NULL) {
1161 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1162 #ifndef NO_INET6
1163 char afstr[BUFSIZ];
1164 #endif /* NO_INET6 */
1165 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1166 if (Ok) {
1167 GetHNRec->TCPPort = i;
1168 } else {
1169 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar,
1170 "The TCP port must be a number.");
1171 MessageBox(dlg, pvar->ts->UIMsg,
1172 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1173 return TRUE;
1174 }
1175 #ifndef NO_INET6
1176 #define getaf(str) \
1177 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1178 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1179 memset(afstr, 0, sizeof(afstr));
1180 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1181 sizeof(afstr));
1182 GetHNRec->ProtocolFamily = getaf(afstr);
1183 #endif /* NO_INET6 */
1184 GetHNRec->PortType = IdTCPIP;
1185 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1186 HostNameMaxLength);
1187 GetHNRec->Telnet = FALSE;
1188 pvar->hostdlg_activated = TRUE;
1189 pvar->hostdlg_Enabled = FALSE;
1190 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1191 GetHNRec->Telnet = TRUE;
1192 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1193 pvar->hostdlg_Enabled = TRUE;
1194
1195 // check SSH protocol version
1196 memset(afstr, 0, sizeof(afstr));
1197 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1198 if (_stricmp(afstr, "SSH1") == 0) {
1199 pvar->settings.ssh_protocol_version = 1;
1200 } else {
1201 pvar->settings.ssh_protocol_version = 2;
1202 }
1203 }
1204
1205 // host history check button
1206 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1207 pvar->ts->HistoryList = 1;
1208 } else {
1209 pvar->ts->HistoryList = 0;
1210 }
1211
1212 } else {
1213 GetHNRec->PortType = IdSerial;
1214 GetHNRec->HostName[0] = 0;
1215 memset(EntName, 0, sizeof(EntName));
1216 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1217 sizeof(EntName) - 1);
1218 if (strncmp(EntName, "COM", 3) == 0 && EntName[3] != '\0') {
1219 #if 0
1220 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1221 if (strlen(EntName) > 4)
1222 GetHNRec->ComPort =
1223 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1224 0x30;
1225 #else
1226 GetHNRec->ComPort = atoi(&EntName[3]);
1227 #endif
1228 if (GetHNRec->ComPort > GetHNRec->MaxComPort)
1229 GetHNRec->ComPort = 1;
1230 } else {
1231 GetHNRec->ComPort = 1;
1232 }
1233 }
1234 }
1235 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)OrigHostnameEditProc);
1236 EndDialog(dlg, 1);
1237
1238 if (DlgHostFont != NULL) {
1239 DeleteObject(DlgHostFont);
1240 }
1241
1242 return TRUE;
1243
1244 case IDCANCEL:
1245 SetWindowLong(hwndHostnameEdit, GWL_WNDPROC, (LONG)OrigHostnameEditProc);
1246 EndDialog(dlg, 0);
1247
1248 if (DlgHostFont != NULL) {
1249 DeleteObject(DlgHostFont);
1250 }
1251
1252 return TRUE;
1253
1254 case IDC_HOSTTCPIP:
1255 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1256 TRUE);
1257 #ifndef NO_INET6
1258 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1259 IDC_HOSTTCPPROTOCOL, TRUE);
1260 #endif /* NO_INET6 */
1261 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1262
1263 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1264 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1265 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1266 } else {
1267 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1268 }
1269
1270 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1271
1272 return TRUE;
1273
1274 case IDC_HOSTSERIAL:
1275 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1276 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1277 FALSE);
1278 #ifndef NO_INET6
1279 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1280 IDC_HOSTTCPPROTOCOL, FALSE);
1281 #endif /* NO_INET6 */
1282 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1283 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1284
1285 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1286
1287 return TRUE;
1288
1289 case IDC_HOSTSSH:
1290 enable_dlg_items(dlg, IDC_SSH_VERSION,
1291 IDC_SSH_VERSION, TRUE);
1292 goto hostssh_enabled;
1293
1294 case IDC_HOSTTELNET:
1295 case IDC_HOSTOTHER:
1296 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1297 hostssh_enabled:
1298
1299 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1300
1301 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1302 if (GetHNRec != NULL)
1303 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1304 FALSE);
1305 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1306 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1307 }
1308 return TRUE;
1309
1310 case IDC_HOSTCOM:
1311 if(HIWORD(wParam) == CBN_DROPDOWN) {
1312 HWND hostcom = GetDlgItem(dlg, IDC_HOSTCOM);
1313 int count = SendMessage(hostcom, CB_GETCOUNT, 0, 0);
1314 int i, len, max_len = 0;
1315 char *lbl;
1316 HDC TmpDC = GetDC(hostcom);
1317 SIZE s;
1318 for (i=0; i<count; i++) {
1319 len = SendMessage(hostcom, CB_GETLBTEXTLEN, i, 0);
1320 lbl = (char *)calloc(len+1, sizeof(char));
1321 SendMessage(hostcom, CB_GETLBTEXT, i, (LPARAM)lbl);
1322 GetTextExtentPoint32(TmpDC, lbl, len, &s);
1323 if (s.cx > max_len)
1324 max_len = s.cx;
1325 free(lbl);
1326 }
1327 SendMessage(hostcom, CB_SETDROPPEDWIDTH,
1328 max_len + GetSystemMetrics(SM_CXVSCROLL), 0);
1329 }
1330 break;
1331
1332 case IDC_HOSTHELP:
1333 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1334 }
1335 }
1336 return FALSE;
1337 }
1338
1339 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1340 {
1341 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1342 parent, TTXHostDlg, (LONG) rec);
1343 }
1344
1345 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1346 {
1347 GET_VAR();
1348
1349 *hooks->GetHostName = TTXGetHostName;
1350 }
1351
1352 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1353 {
1354 GET_VAR();
1355
1356 (pvar->ReadIniFile) (fileName, ts);
1357 read_ssh_options(pvar, fileName);
1358 pvar->settings = *pvar->ts_SSH;
1359 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1360 FWDUI_load_settings(pvar);
1361 }
1362
1363 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1364 {
1365 GET_VAR();
1366
1367 (pvar->WriteIniFile) (fileName, ts);
1368 *pvar->ts_SSH = pvar->settings;
1369 clear_local_settings(pvar);
1370 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1371 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1372 }
1373
1374 static void read_ssh_options_from_user_file(PTInstVar pvar,
1375 char FAR * user_file_name)
1376 {
1377 if (user_file_name[0] == '.') {
1378 read_ssh_options(pvar, user_file_name);
1379 } else {
1380 char buf[1024];
1381
1382 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1383 read_ssh_options(pvar, buf);
1384 }
1385
1386 pvar->settings = *pvar->ts_SSH;
1387 FWDUI_load_settings(pvar);
1388 }
1389
1390
1391 // @���u�����N���u�������B (2005.1.26 yutaka)
1392 static void replace_to_blank(char *src, char *dst, int dst_len)
1393 {
1394 int len, i;
1395
1396 len = strlen(src);
1397 if (dst_len < len) // buffer overflow check
1398 return;
1399
1400 for (i = 0 ; i < len ; i++) {
1401 if (src[i] == '@') { // @ ���o��������
1402 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1403 *dst++ = '@';
1404 i++;
1405 } else {
1406 *dst++ = ' '; // �������u��������
1407 }
1408 } else {
1409 *dst++ = src[i];
1410 }
1411 }
1412 *dst = '\0';
1413 }
1414
1415 /* returns 1 if the option text must be deleted */
1416 static int parse_option(PTInstVar pvar, char FAR * option)
1417 {
1418 if ((option[0] == '-' || option[0] == '/')) {
1419 if (MATCH_STR(option + 1, "ssh") == 0) {
1420 if (option[4] == 0) {
1421 pvar->settings.Enabled = 1;
1422 } else if (MATCH_STR(option + 4, "-L") == 0 ||
1423 MATCH_STR(option + 4, "-R") == 0 ||
1424 _stricmp(option + 4, "-X") == 0) {
1425 if (pvar->settings.DefaultForwarding[0] == 0) {
1426 strncpy_s(pvar->settings.DefaultForwarding,
1427 sizeof(pvar->settings.DefaultForwarding),
1428 option + 5, _TRUNCATE);
1429 } else {
1430 strncat_s(pvar->settings.DefaultForwarding,
1431 sizeof(pvar->settings.DefaultForwarding),
1432 ";", _TRUNCATE);
1433 strncat_s(pvar->settings.DefaultForwarding,
1434 sizeof(pvar->settings.DefaultForwarding),
1435 option + 5, _TRUNCATE);
1436 }
1437 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1438 read_ssh_options_from_user_file(pvar, option + 7);
1439 } else if (MATCH_STR(option + 4, "-v") == 0) {
1440 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1441 } else if (_stricmp(option + 4, "-autologin") == 0 ||
1442 _stricmp(option + 4, "-autologon") == 0) {
1443 pvar->settings.TryDefaultAuth = TRUE;
1444
1445 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1446 read_ssh_options_from_user_file(pvar, option + 13);
1447 DeleteFile(option + 13);
1448
1449 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1450 } else if (MATCH_STR(option + 4, "1") == 0) {
1451 pvar->settings.ssh_protocol_version = 1;
1452 } else if (MATCH_STR(option + 4, "2") == 0) {
1453 pvar->settings.ssh_protocol_version = 2;
1454
1455 } else {
1456 char buf[1024];
1457
1458 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar,
1459 "Unrecognized command-line option: %s");
1460 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, option);
1461
1462 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1463 }
1464
1465 return 1;
1466
1467 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1468 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1469 if (strcmp(option + 3, "2") == 0) {
1470 pvar->settings.Enabled = 1;
1471 return 1;
1472 } else {
1473 pvar->settings.Enabled = 0;
1474 }
1475
1476 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1477 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1478 read_ssh_options_from_user_file(pvar, option + 3);
1479
1480 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1481 } else if (MATCH_STR(option + 1, "1") == 0) {
1482 // command line: /ssh /1 is SSH1 only
1483 pvar->settings.ssh_protocol_version = 1;
1484
1485 } else if (MATCH_STR(option + 1, "2") == 0) {
1486 // command line: /ssh /2 is SSH2 & SSH1
1487 pvar->settings.ssh_protocol_version = 2;
1488
1489 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1490 // '/nossh' �I�v�V�����������B
1491 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1492 // �����������������B(2004.10.11 yutaka)
1493 pvar->settings.Enabled = 0;
1494
1495 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1496 // '/telnet' ���w�������������������� '/nossh' ��������
1497 // SSH������������ (2006.9.16 maya)
1498 pvar->settings.Enabled = 0;
1499
1500 } else if (MATCH_STR(option + 1, "auth") == 0) {
1501 // SSH2�������O�C���I�v�V����������
1502 //
1503 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1504 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1505 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1506 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1507 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1508 //
1509 // (2004.11.30 yutaka)
1510 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1511 //
1512 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1513
1514 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h
1515 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1516 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1517
1518 // /auth=challenge ������ (2007.10.5 maya)
1519 } else if (MATCH_STR(option + 5, "=challenge") == 0) { // keyboard-interactive�F��
1520 //pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
1521 pvar->ssh2_authmethod = SSH_AUTH_TIS;
1522
1523 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1524 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1525 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1526
1527 } else {
1528 // TODO:
1529
1530 }
1531
1532 } else if (MATCH_STR(option + 1, "user=") == 0) {
1533 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1534 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1535
1536 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1537 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1538 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1539
1540 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1541 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1542
1543 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1544 // �p�X���[�h������ (2006.9.18 maya)
1545 pvar->ask4passwd = 1;
1546
1547 }
1548
1549 // �p�X���[�h�������������������O�C��������������
1550 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1551 if (pvar->ask4passwd == 1) {
1552 pvar->ssh2_autologin = 0;
1553 }
1554
1555 }
1556
1557 return 0;
1558 }
1559
1560 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1561 PCHAR DDETopic)
1562 {
1563 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1564 int i;
1565 BOOL inParam = FALSE;
1566 BOOL inQuotes = FALSE;
1567 BOOL inFileParam = FALSE;
1568 PCHAR option = NULL;
1569 GET_VAR();
1570
1571 if (pvar->hostdlg_activated) {
1572 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1573 }
1574
1575 for (i = 0; param[i] != 0; i++) {
1576 if (inQuotes ? param[i] == '"'
1577 : (param[i] == ' ' || param[i] == '\t')) {
1578 if (option != NULL) {
1579 char ch = param[i];
1580 PCHAR Equal;
1581
1582 param[i] = 0;
1583 Equal = strchr(option, '=');
1584 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1585 int buf_len = strlen(option) * sizeof(char);
1586 char *buf = (char *)calloc(strlen(option), sizeof(char));
1587 char c = option[Equal - option + 1];
1588 option[Equal - option + 1] = 0;
1589 strncat_s(buf, buf_len, option, _TRUNCATE);
1590 option[Equal - option + 1] = c;
1591 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1592 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1593 memset(option, ' ', i + 1 - (option - param));
1594 } else {
1595 param[i] = ch;
1596 }
1597 free(buf);
1598 }
1599 else {
1600 if (parse_option(pvar, *option == '"' ? option + 1 : option)) {
1601 memset(option, ' ', i + 1 - (option - param));
1602 } else {
1603 param[i] = ch;
1604 }
1605 }
1606 option = NULL;
1607 }
1608 inParam = FALSE;
1609 inQuotes = FALSE;
1610 inFileParam = FALSE;
1611 } else if (!inParam) {
1612 if (param[i] == '"') {
1613 inQuotes = TRUE;
1614 inParam = TRUE;
1615 option = param + i;
1616 } else if (param[i] != ' ' && param[i] != '\t') {
1617 inParam = TRUE;
1618 option = param + i;
1619 }
1620 } else {
1621 if (option == NULL) {
1622 continue;
1623 }
1624 if ((option[0] == '-' || option[0] == '/') &&
1625 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1626 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1627 MATCH_STR_I(option + 1, "f=") == 0 ||
1628 MATCH_STR(option + 1, "keyfile=") == 0)) {
1629 if (param[i] == '"') {
1630 inQuotes = TRUE;
1631 }
1632 inFileParam = TRUE;
1633 }
1634 }
1635 }
1636
1637 if (option != NULL) {
1638 PCHAR Equal = strchr(option, '=');
1639 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1640 int buf_len = strlen(option) * sizeof(char);
1641 char *buf = (char *)calloc(strlen(option), sizeof(char));
1642 char c = option[Equal - option + 1];
1643 option[Equal - option + 1] = 0;
1644 strncat_s(buf, buf_len, option, _TRUNCATE);
1645 option[Equal - option + 1] = c;
1646 strncat_s(buf, buf_len, Equal + 2, _TRUNCATE);
1647 if (parse_option(pvar, *buf == '"' ? buf + 1 : buf)) {
1648 memset(option, ' ', i + 1 - (option - param));
1649 }
1650 free(buf);
1651 }
1652 else {
1653 if (parse_option(pvar, option)) {
1654 memset(option, ' ', i - (option - param));
1655 }
1656 }
1657 }
1658
1659 FWDUI_load_settings(pvar);
1660
1661 (pvar->ParseParam) (param, ts, DDETopic);
1662
1663 }
1664
1665 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1666 {
1667 GET_VAR();
1668
1669 pvar->ReadIniFile = *hooks->ReadIniFile;
1670 pvar->WriteIniFile = *hooks->WriteIniFile;
1671 pvar->ParseParam = *hooks->ParseParam;
1672
1673 *hooks->ReadIniFile = TTXReadINIFile;
1674 *hooks->WriteIniFile = TTXWriteINIFile;
1675 *hooks->ParseParam = TTXParseParam;
1676 }
1677
1678 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1679 {
1680 GET_VAR();
1681
1682 SSH_notify_win_size(pvar, cols, rows);
1683 }
1684
1685 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1686 WORD newItemID, char FAR * text)
1687 {
1688 int i, j;
1689
1690 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1691 HMENU submenu = GetSubMenu(menu, i);
1692
1693 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1694 if (GetMenuItemID(submenu, j) == beforeItemID) {
1695 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID, text);
1696 return;
1697 }
1698 }
1699 }
1700 }
1701
1702 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1703 {
1704 GET_VAR();
1705
1706 /* inserts before ID_HELP_ABOUT */
1707 UTIL_get_lang_msg("MENU_ABOUT", pvar, "About &TTSSH...");
1708 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1709
1710 /* inserts before ID_SETUP_TCPIP */
1711 UTIL_get_lang_msg("MENU_SSH", pvar, "SS&H...");
1712 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1713 /* inserts before ID_SETUP_TCPIP */
1714 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar, "SSH &Authentication...");
1715 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1716 /* inserts before ID_SETUP_TCPIP */
1717 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar, "SSH F&orwarding...");
1718 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1719 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar, "SSH KeyGe&nerator...");
1720 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1721 }
1722
1723 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1724 {
1725 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1726 (LPARAM) prefix);
1727 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1728 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1729 (LPARAM) (char FAR *) "\r\n");
1730 }
1731
1732 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1733 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1734 {
1735 typedef struct {
1736 WORD wLanguage;
1737 WORD wCodePage;
1738 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1739 LPLANGANDCODEPAGE lplgcode;
1740 UINT unLen;
1741 DWORD size;
1742 char *buf = NULL;
1743 BOOL ret;
1744 int i;
1745 char fmt[80];
1746 char *pbuf;
1747
1748 size = GetFileVersionInfoSize(exefile, NULL);
1749 if (size == 0) {
1750 goto error;
1751 }
1752 buf = malloc(size);
1753 ZeroMemory(buf, size);
1754
1755 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1756 goto error;
1757 }
1758
1759 ret = VerQueryValue(buf,
1760 "\\VarFileInfo\\Translation",
1761 (LPVOID *)&lplgcode, &unLen);
1762 if (ret == FALSE)
1763 goto error;
1764
1765 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1766 _snprintf_s(fmt, sizeof(fmt), _TRUNCATE,
1767 "\\StringFileInfo\\%04x%04x\\FileVersion",
1768 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1769 VerQueryValue(buf, fmt, &pbuf, &unLen);
1770 if (unLen > 0) { // get success
1771 int n, a, b, c, d;
1772
1773 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1774 if (n == 4) { // convert success
1775 *major = a;
1776 *minor = b;
1777 *release = c;
1778 *build = d;
1779 break;
1780 }
1781 }
1782 }
1783
1784 free(buf);
1785 return;
1786
1787 error:
1788 free(buf);
1789 *major = *minor = *release = *build = 0;
1790 }
1791
1792 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1793 {
1794 char buf[1024];
1795 int a, b, c, d;
1796 char uimsg[MAX_UIMSG];
1797
1798 GetWindowText(dlg, uimsg, sizeof(uimsg));
1799 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar, uimsg);
1800 SetWindowText(dlg, pvar->ts->UIMsg);
1801 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
1802 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
1803 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1804
1805 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1806 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1807 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
1808 "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1809 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1810
1811 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1812 // ���������� (2005.5.11 yutaka)
1813 #ifdef OPENSSL_VERSION_TEXT
1814 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1815 #else
1816 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1817 #endif
1818
1819 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1820 #ifdef ZLIB_VERSION
1821 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "ZLib %s", ZLIB_VERSION);
1822 #else
1823 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1824 #endif
1825 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1826
1827
1828 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1829 if (pvar->socket != INVALID_SOCKET) {
1830 if (SSHv1(pvar)) {
1831 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1832 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1833 append_about_text(dlg, pvar->ts->UIMsg, buf);
1834 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1835 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1836 append_about_text(dlg, pvar->ts->UIMsg, buf);
1837 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1838 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1839 append_about_text(dlg, pvar->ts->UIMsg, buf);
1840 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1841 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1842 append_about_text(dlg, pvar->ts->UIMsg, buf);
1843 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1844 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1845 append_about_text(dlg, pvar->ts->UIMsg, buf);
1846 SSH_get_compression_info(pvar, buf, sizeof(buf));
1847 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1848 append_about_text(dlg, pvar->ts->UIMsg, buf);
1849
1850 } else { // SSH2
1851 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1852 UTIL_get_lang_msg("DLG_ABOUT_SERVERID", pvar, "Server ID: ");
1853 append_about_text(dlg, pvar->ts->UIMsg, buf);
1854 UTIL_get_lang_msg("DLG_ABOUT_CLIENTID", pvar, "Client ID: ");
1855 append_about_text(dlg, pvar->ts->UIMsg, pvar->client_version_string);
1856
1857 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1858 UTIL_get_lang_msg("DLG_ABOUT_PROTOCOL", pvar, "Using protocol: ");
1859 append_about_text(dlg, pvar->ts->UIMsg, buf);
1860
1861 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1862 strncpy_s(buf, sizeof(buf), KEX_DH1, _TRUNCATE);
1863 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1864 strncpy_s(buf, sizeof(buf), KEX_DH14, _TRUNCATE);
1865 } else {
1866 strncpy_s(buf, sizeof(buf), KEX_DHGEX, _TRUNCATE);
1867 }
1868 append_about_text(dlg, "KEX: ", buf);
1869
1870 if (pvar->hostkey_type == KEY_DSA) {
1871 strncpy_s(buf, sizeof(buf), "ssh-dss", _TRUNCATE);
1872 } else {
1873 strncpy_s(buf, sizeof(buf), "ssh-rsa", _TRUNCATE);
1874 }
1875 UTIL_get_lang_msg("DLG_ABOUT_HOSTKEY", pvar, "Host Key: ");
1876 append_about_text(dlg, pvar->ts->UIMsg, buf);
1877
1878 // add HMAC algorithm (2004.12.17 yutaka)
1879 buf[0] = '\0';
1880 if (pvar->ctos_hmac == HMAC_SHA1) {
1881 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1882 } else if (pvar->ctos_hmac == HMAC_MD5) {
1883 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1884 }
1885 UTIL_get_lang_msg("DLG_ABOUT_TOSERVER", pvar, " to server, ");
1886 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1887 if (pvar->stoc_hmac == HMAC_SHA1) {
1888 strncat_s(buf, sizeof(buf), "hmac-sha1", _TRUNCATE);
1889 } else if (pvar->stoc_hmac == HMAC_MD5) {
1890 strncat_s(buf, sizeof(buf), "hmac-md5", _TRUNCATE);
1891 }
1892 UTIL_get_lang_msg("DLG_ABOUT_FROMSERVER", pvar, " from server");
1893 strncat_s(buf, sizeof(buf), pvar->ts->UIMsg, _TRUNCATE);
1894 append_about_text(dlg, "HMAC: ", buf);
1895
1896 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1897 UTIL_get_lang_msg("DLG_ABOUT_ENCRYPTION", pvar, "Encryption: ");
1898 append_about_text(dlg, pvar->ts->UIMsg, buf);
1899 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1900 UTIL_get_lang_msg("DLG_ABOUT_SERVERKEY", pvar, "Server keys: ");
1901 append_about_text(dlg, pvar->ts->UIMsg, buf);
1902
1903 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1904 UTIL_get_lang_msg("DLG_ABOUT_AUTH", pvar, "Authentication: ");
1905 append_about_text(dlg, pvar->ts->UIMsg, buf);
1906
1907 SSH_get_compression_info(pvar, buf, sizeof(buf));
1908 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1909 UTIL_get_lang_msg("DLG_ABOUT_COMPDELAY", pvar, "Delayed Compression: ");
1910 append_about_text(dlg, pvar->ts->UIMsg, buf);
1911 } else {
1912 UTIL_get_lang_msg("DLG_ABOUT_COMP", pvar, "Compression: ");
1913 append_about_text(dlg, pvar->ts->UIMsg, buf);
1914 }
1915 }
1916 }
1917 }
1918
1919 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1920 LPARAM lParam)
1921 {
1922 LOGFONT logfont;
1923 HFONT font;
1924
1925 switch (msg) {
1926 case WM_INITDIALOG:
1927 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1928 GetObject(font, sizeof(LOGFONT), &logfont);
1929 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1930 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1931 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1932 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1933 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1934 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1935 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1936 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1937 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1938 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1939 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1940 }
1941 else {
1942 DlgAboutFont = NULL;
1943 }
1944 init_about_dlg((PTInstVar) lParam, dlg);
1945 return TRUE;
1946 case WM_COMMAND:
1947 switch (LOWORD(wParam)) {
1948 case IDOK:
1949 EndDialog(dlg, 1);
1950 if (DlgAboutFont != NULL) {
1951 DeleteObject(DlgAboutFont);
1952 }
1953 return TRUE;
1954 case IDCANCEL: /* there isn't a cancel button, but other Windows
1955 UI things can send this message */
1956 EndDialog(dlg, 0);
1957 if (DlgAboutFont != NULL) {
1958 DeleteObject(DlgAboutFont);
1959 }
1960 return TRUE;
1961 }
1962 break;
1963 }
1964
1965 return FALSE;
1966 }
1967
1968 static char FAR *get_cipher_name(int cipher)
1969 {
1970 switch (cipher) {
1971 case SSH_CIPHER_NONE:
1972 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar,
1973 "<ciphers below this line are disabled>");
1974 return pvar->ts->UIMsg;
1975 case SSH_CIPHER_RC4:
1976 return "RC4";
1977 case SSH_CIPHER_3DES:
1978 return "3DES";
1979 case SSH_CIPHER_DES:
1980 return "DES";
1981 case SSH_CIPHER_IDEA:
1982 return "IDEA";
1983 case SSH_CIPHER_TSS:
1984 return "TSS";
1985 case SSH_CIPHER_BLOWFISH:
1986 return "Blowfish";
1987
1988 // for SSH2(yutaka)
1989 case SSH_CIPHER_AES128:
1990 return "AES128(SSH2)";
1991 case SSH_CIPHER_3DES_CBC:
1992 return "3DES-CBC(SSH2)";
1993
1994 default:
1995 return NULL;
1996 }
1997 }
1998
1999 static void set_move_button_status(HWND dlg)
2000 {
2001 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2002 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
2003 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
2004
2005 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP),
2006 curPos > 0 && curPos <= maxPos);
2007 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN),
2008 curPos >= 0 && curPos < maxPos);
2009 }
2010
2011 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
2012 {
2013 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2014 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2015 int i;
2016 int ch;
2017 char uimsg[MAX_UIMSG];
2018
2019 GetWindowText(dlg, uimsg, sizeof(uimsg));
2020 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar, uimsg);
2021 SetWindowText(dlg, pvar->ts->UIMsg);
2022 GetDlgItemText(dlg, IDC_COMPRESSLABEL, uimsg, sizeof(uimsg));
2023 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar, uimsg);
2024 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
2025 GetDlgItemText(dlg, IDC_COMPRESSNONE, uimsg, sizeof(uimsg));
2026 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar, uimsg);
2027 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
2028 GetDlgItemText(dlg, IDC_COMPRESSHIGH, uimsg, sizeof(uimsg));
2029 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar, uimsg);
2030 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
2031 GetDlgItemText(dlg, IDC_CIPHERORDER, uimsg, sizeof(uimsg));
2032 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar, uimsg);
2033 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
2034 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, uimsg, sizeof(uimsg));
2035 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar, uimsg);
2036 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
2037 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, uimsg, sizeof(uimsg));
2038 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar, uimsg);
2039 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2040 GetDlgItemText(dlg, IDC_KNOWNHOSTS, uimsg, sizeof(uimsg));
2041 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar, uimsg);
2042 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2043 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, uimsg, sizeof(uimsg));
2044 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar, uimsg);
2045 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2046 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, uimsg, sizeof(uimsg));
2047 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar, uimsg);
2048 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2049 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, uimsg, sizeof(uimsg));
2050 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar, uimsg);
2051 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2052 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, uimsg, sizeof(uimsg));
2053 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar, uimsg);
2054 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2055 GetDlgItemText(dlg, IDC_NOTICEBANNER, uimsg, sizeof(uimsg));
2056 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar, uimsg);
2057 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2058 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2059 UTIL_get_lang_msg("BTN_OK", pvar, uimsg);
2060 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2061 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2062 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);
2063 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2064
2065 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2066 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2067 pvar->settings.CompressionLevel);
2068
2069 normalize_cipher_order(pvar->settings.CipherOrder);
2070
2071 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2072 int cipher = pvar->settings.CipherOrder[i] - '0';
2073 char FAR *name = get_cipher_name(cipher);
2074
2075 if (name != NULL) {
2076 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2077 }
2078 }
2079
2080 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2081 set_move_button_status(dlg);
2082
2083 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2084 i++) {
2085 }
2086 if (ch != 0) {
2087 pvar->settings.KnownHostsFiles[i] = 0;
2088 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2089 pvar->settings.KnownHostsFiles);
2090 pvar->settings.KnownHostsFiles[i] = ch;
2091 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2092 pvar->settings.KnownHostsFiles + i + 1);
2093 } else {
2094 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2095 pvar->settings.KnownHostsFiles);
2096 }
2097
2098 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2099 {
2100 char buf[10];
2101 _snprintf_s(buf, sizeof(buf), _TRUNCATE,
2102 "%d", pvar->settings.ssh_heartbeat_overtime);
2103 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2104 }
2105
2106 }
2107
2108 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2109 char FAR * basename)
2110 {
2111 int filename_start = 0;
2112 int i;
2113 int ch;
2114
2115 if (basename[0] == '\\' || basename[0] == '/'
2116 || (basename[0] != 0 && basename[1] == ':')) {
2117 strncpy_s(buf, bufsize, basename, _TRUNCATE);
2118 return;
2119 }
2120
2121 GetModuleFileName(NULL, buf, bufsize);
2122 for (i = 0; (ch = buf[i]) != 0; i++) {
2123 if (ch == '\\' || ch == '/' || ch == ':') {
2124 filename_start = i + 1;
2125 }
2126 }
2127
2128 if (bufsize > filename_start) {
2129 strncpy_s(buf + filename_start, bufsize - filename_start, basename, _TRUNCATE);
2130 }
2131 }
2132
2133 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2134 char FAR * basename)
2135 {
2136 char buf[1024];
2137 int filename_start = 0;
2138 int i;
2139 int ch, ch2;
2140
2141 if (basename[0] != '\\' && basename[0] != '/'
2142 && (basename[0] == 0 || basename[1] != ':')) {
2143 strncpy_s(dest, destsize, basename, _TRUNCATE);
2144 return strlen(dest);
2145 }
2146
2147 GetModuleFileName(NULL, buf, sizeof(buf));
2148 for (i = 0; (ch = buf[i]) != 0; i++) {
2149 if (ch == '\\' || ch == '/' || ch == ':') {
2150 filename_start = i + 1;
2151 }
2152 }
2153
2154 for (i = 0; i < filename_start; i++) {
2155 ch = toupper(buf[i]);
2156 ch2 = toupper(basename[i]);
2157
2158 if (ch == ch2 ||
2159 ((ch == '\\' || ch == '/') && (ch2 == '\\' || ch2 == '/'))) {
2160 } else {
2161 break;
2162 }
2163 }
2164
2165 if (i == filename_start) {
2166 strncpy_s(dest, destsize, basename + i, _TRUNCATE);
2167 } else {
2168 strncpy_s(dest, destsize, basename, _TRUNCATE);
2169 }
2170 return strlen(dest);
2171 }
2172
2173 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2174 {
2175 char buf[4096];
2176 char buf2[1024];
2177 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2178 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2179 int i, j, buf2index, bufindex;
2180 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2181
2182 pvar->settings.CompressionLevel =
2183 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2184
2185 buf2index = 0;
2186 for (i = 0; i < count; i++) {
2187 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2188
2189 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2190 buf[0] = 0;
2191 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2192 for (j = 0;
2193 j <= SSH_CIPHER_MAX
2194 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2195 }
2196 if (j <= SSH_CIPHER_MAX) {
2197 buf2[buf2index] = '0' + j;
2198 buf2index++;
2199 }
2200 }
2201 }
2202 buf2[buf2index] = 0;
2203 normalize_cipher_order(buf2);
2204 strncpy_s(pvar->settings.CipherOrder, sizeof(pvar->settings.CipherOrder), buf2, _TRUNCATE);
2205
2206 buf[0] = 0;
2207 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2208 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2209 sizeof(pvar->settings.KnownHostsFiles),
2210 buf);
2211 buf[0] = 0;
2212 bufindex = 0;
2213 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2214 for (i = 0; buf[i] != 0; i++) {
2215 if (buf[i] == ';') {
2216 buf[i] = 0;
2217 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2218 pvar->settings.KnownHostsFiles[j] = ';';
2219 j++;
2220 j += copy_teraterm_dir_relative_path(pvar->settings.
2221 KnownHostsFiles + j,
2222 sizeof(pvar->settings.
2223 KnownHostsFiles)
2224 - j, buf + bufindex);
2225 }
2226 bufindex = i + 1;
2227 }
2228 }
2229 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2230 pvar->settings.KnownHostsFiles[j] = ';';
2231 j++;
2232 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2233 sizeof(pvar->settings. KnownHostsFiles) - j,
2234 buf + bufindex);
2235 }
2236
2237 // get SSH HeartBeat(keep-alive)
2238 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2239 i = atoi(buf);
2240 if (i < 0)
2241 i = 60;
2242 pvar->settings.ssh_heartbeat_overtime = i;
2243
2244 }
2245
2246 static void move_cur_sel_delta(HWND listbox, int delta)
2247 {
2248 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2249 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2250 int newPos = curPos + delta;
2251 char buf[1024];
2252
2253 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2254 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2255
2256 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2257 buf[0] = 0;
2258 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2259 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2260 SendMessage(listbox, LB_INSERTSTRING, newPos,
2261 (LPARAM) (char FAR *) buf);
2262 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2263 }
2264 }
2265 }
2266
2267 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2268 int readonly)
2269 {
2270 OPENFILENAME params;
2271 char fullname_buf[2048] = "ssh_known_hosts";
2272
2273 params.lStructSize = sizeof(OPENFILENAME);
2274 params.hwndOwner = parent;
2275 params.lpstrFilter = NULL;
2276 params.lpstrCustomFilter = NULL;
2277 params.nFilterIndex = 0;
2278 buf[0] = 0;
2279 params.lpstrFile = fullname_buf;
2280 params.nMaxFile = sizeof(fullname_buf);
2281 params.lpstrFileTitle = NULL;
2282 params.lpstrInitialDir = NULL;
2283 if (readonly) {
2284 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar,
2285 "Choose a read-only known-hosts file to add");
2286 }
2287 else {
2288 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar,
2289 "Choose a read/write known-hosts file");
2290 }
2291 params.lpstrTitle = pvar->ts->UIMsg;
2292 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2293 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2294 params.lpstrDefExt = NULL;
2295
2296 if (GetOpenFileName(&params) != 0) {
2297 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2298 return 1;
2299 } else {
2300 int err = CommDlgExtendedError();
2301
2302 if (err != 0) {
2303 char buf[1024];
2304 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar,
2305 "Unable to display file dialog box: error %d");
2306 _snprintf_s(buf, sizeof(buf), _TRUNCATE, pvar->ts->UIMsg, err);
2307 MessageBox(parent, buf, "TTSSH Error",
2308 MB_OK | MB_ICONEXCLAMATION);
2309 }
2310
2311 return 0;
2312 }
2313 }
2314
2315 static void choose_read_write_file(HWND dlg)
2316 {
2317 char buf[1024];
2318
2319 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2320 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2321 }
2322 }
2323
2324 static void choose_read_only_file(HWND dlg)
2325 {
2326 char buf[1024];
2327 char buf2[4096];
2328
2329 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2330 buf2[0] = 0;
2331 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2332 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2333 strncat_s(buf2, sizeof(buf2), ";", _TRUNCATE);
2334 }
2335 strncat_s(buf2, sizeof(buf2), buf, _TRUNCATE);
2336 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2337 }
2338 }
2339
2340 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2341 LPARAM lParam)
2342 {
2343 LOGFONT logfont;
2344 HFONT font;
2345
2346 switch (msg) {
2347 case WM_INITDIALOG:
2348 SetWindowLong(dlg, DWL_USER, lParam);
2349 init_setup_dlg((PTInstVar) lParam, dlg);
2350
2351 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2352 GetObject(font, sizeof(LOGFONT), &logfont);
2353 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2354 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2355 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2356 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2357 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2358 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2359 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2360 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2361 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2362 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2363 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2364 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2365 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2366 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2367 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2368 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2369 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2370 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2371 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2372 }
2373 else {
2374 DlgSetupFont = NULL;
2375 }
2376
2377 return TRUE;
2378 case WM_COMMAND:
2379 switch (LOWORD(wParam)) {
2380 case IDOK:
2381 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER), dlg);
2382 EndDialog(dlg, 1);
2383 if (DlgSetupFont != NULL) {
2384 DeleteObject(DlgSetupFont);
2385 }
2386 return TRUE;
2387 case IDCANCEL: /* there isn't a cancel button, but other Windows
2388 UI things can send this message */
2389 EndDialog(dlg, 0);
2390 if (DlgSetupFont != NULL) {
2391 DeleteObject(DlgSetupFont);
2392 }
2393 return TRUE;
2394 case IDC_SSHMOVECIPHERUP:
2395 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2396 set_move_button_status(dlg);
2397 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2398 return TRUE;
2399 case IDC_SSHMOVECIPHERDOWN:
2400 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2401 set_move_button_status(dlg);
2402 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2403 return TRUE;
2404 case IDC_SSHCIPHERPREFS:
2405 set_move_button_status(dlg);
2406 return TRUE;
2407 case IDC_CHOOSEREADWRITEFILE:
2408 choose_read_write_file(dlg);
2409 return TRUE;
2410 case IDC_CHOOSEREADONLYFILE:
2411 choose_read_only_file(dlg);
2412 return TRUE;
2413 }
2414 break;
2415 }
2416
2417 return FALSE;
2418 }
2419
2420
2421 //
2422 // SSH key generator dialog (2005.4.10 yutaka)
2423 //
2424
2425 typedef struct {
2426 RSA *rsa;
2427 DSA *dsa;
2428 } ssh_private_key_t;
2429
2430 static ssh_private_key_t private_key = {NULL, NULL};
2431
2432 typedef struct {
2433 RSA *rsa;
2434 DSA *dsa;
2435 } ssh_public_key_t;
2436
2437 static ssh_public_key_t public_key = {NULL, NULL};;
2438
2439 static void free_ssh_key(void)
2440 {
2441 // DSA_free(), RSA_free()��NULL���n�����������������B
2442 DSA_free(private_key.dsa);
2443 private_key.dsa = NULL;
2444 DSA_free(public_key.dsa);
2445 public_key.dsa = NULL;
2446
2447 RSA_free(private_key.rsa);
2448 private_key.rsa = NULL;
2449 RSA_free(public_key.rsa);
2450 public_key.rsa = NULL;
2451 }
2452
2453
2454 static BOOL generate_ssh_key(enum hostkey_type type)
2455 {
2456 int bits = 1024;
2457
2458 // if SSH key already is generated, should free the resource.
2459 free_ssh_key();
2460
2461 if (type == KEY_RSA1 || type == KEY_RSA) {
2462 RSA *priv = NULL;
2463 RSA *pub = NULL;
2464
2465 // private key
2466 priv = RSA_generate_key(bits, 35, NULL, NULL);
2467 if (priv == NULL)
2468 goto error;
2469 private_key.rsa = priv;
2470
2471 // public key
2472 pub = RSA_new();
2473 pub->n = BN_new();
2474 pub->e = BN_new();
2475 if (pub->n == NULL || pub->e == NULL) {
2476 RSA_free(pub);
2477 goto error;
2478 }
2479
2480 BN_copy(pub->n, priv->n);
2481 BN_copy(pub->e, priv->e);
2482 public_key.rsa = pub;
2483
2484 } else if (type == KEY_DSA) {
2485 DSA *priv = NULL;
2486 DSA *pub = NULL;
2487
2488 // private key
2489 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2490 if (priv == NULL)
2491 goto error;
2492 if (!DSA_generate_key(priv)) {
2493 // TODO: free 'priv'?
2494 goto error;
2495 }
2496 private_key.dsa = priv;
2497
2498 // public key
2499 pub = DSA_new();
2500 if (pub == NULL)
2501 goto error;
2502 pub->p = BN_new();
2503 pub->q = BN_new();
2504 pub->g = BN_new();
2505 pub->pub_key = BN_new();
2506 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2507 DSA_free(pub);
2508 goto error;
2509 }
2510
2511 BN_copy(pub->p, priv->p);
2512 BN_copy(pub->q, priv->q);
2513 BN_copy(pub->g, priv->g);
2514 BN_copy(pub->pub_key, priv->pub_key);
2515 public_key.dsa = pub;
2516
2517 } else {
2518 goto error;
2519 }
2520
2521 return TRUE;
2522
2523 error:
2524 free_ssh_key();
2525 return FALSE;
2526 }
2527
2528
2529 //
2530 // RC4
2531 //
2532
2533 /* Size of key to use */
2534 #define SEED_SIZE 20
2535
2536 /* Number of bytes to reseed after */
2537 #define REKEY_BYTES (1 << 24)
2538
2539 static int rc4_ready = 0;
2540 static RC4_KEY rc4;
2541
2542 static void seed_rng(void)
2543 {
2544 if (RAND_status() != 1)
2545 return;
2546 }
2547
2548 static void arc4random_stir(void)
2549 {
2550 unsigned char rand_buf[SEED_SIZE];
2551 int i;
2552
2553 memset(&rc4, 0, sizeof(rc4));
2554 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2555 //fatal("Couldn't obtain random bytes (error %ld)",
2556 // ERR_get_error());
2557 }
2558 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2559
2560 /*
2561 * Discard early keystream, as per recommendations in:
2562 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2563 */
2564 for(i = 0; i <= 256; i += sizeof(rand_buf))
2565 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2566
2567 memset(rand_buf, 0, sizeof(rand_buf));
2568
2569 rc4_ready = REKEY_BYTES;
2570 }
2571
2572 static unsigned int arc4random(void)
2573 {
2574 unsigned int r = 0;
2575 static int first_time = 1;
2576
2577 if (rc4_ready <= 0) {
2578 if (first_time) {
2579 seed_rng();
2580 }
2581 first_time = 0;
2582 arc4random_stir();
2583 }
2584
2585 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2586
2587 rc4_ready -= sizeof(r);
2588
2589 return(r);
2590 }
2591
2592 //
2593 // SSH1 3DES
2594 //
2595 /*
2596 * This is used by SSH1:
2597 *
2598 * What kind of triple DES are these 2 routines?
2599 *
2600 * Why is there a redundant initialization vector?
2601 *
2602 * If only iv3 was used, then, this would till effect have been
2603 * outer-cbc. However, there is also a private iv1 == iv2 which
2604 * perhaps makes differential analysis easier. On the other hand, the
2605 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2606 * result of that there is no longer any known iv1 to use when
2607 * choosing the X block.
2608 */
2609 struct ssh1_3des_ctx
2610 {
2611 EVP_CIPHER_CTX k1, k2, k3;
2612 };
2613
2614 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2615 {
2616 struct ssh1_3des_ctx *c;
2617 u_char *k1, *k2, *k3;
2618
2619 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2620 c = malloc(sizeof(*c));
2621 EVP_CIPHER_CTX_set_app_data(ctx, c);
2622 }
2623 if (key == NULL)
2624 return (1);
2625 if (enc == -1)
2626 enc = ctx->encrypt;
2627 k1 = k2 = k3 = (u_char *) key;
2628 k2 += 8;
2629 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2630 if (enc)
2631 k3 += 16;
2632 else
2633 k1 += 16;
2634 }
2635 EVP_CIPHER_CTX_init(&c->k1);
2636 EVP_CIPHER_CTX_init(&c->k2);
2637 EVP_CIPHER_CTX_init(&c->k3);
2638 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2639 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2640 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2641 memset(c, 0, sizeof(*c));
2642 free(c);
2643 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2644 return (0);
2645 }
2646 return (1);
2647 }
2648
2649 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2650 {
2651 struct ssh1_3des_ctx *c;
2652
2653 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2654 //error("ssh1_3des_cbc: no context");
2655 return (0);
2656 }
2657 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2658 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2659 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2660 return (0);
2661 return (1);
2662 }
2663
2664 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2665 {
2666 struct ssh1_3des_ctx *c;
2667
2668 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2669 EVP_CIPHER_CTX_cleanup(&c->k1);
2670 EVP_CIPHER_CTX_cleanup(&c->k2);
2671 EVP_CIPHER_CTX_cleanup(&c->k3);
2672 memset(c, 0, sizeof(*c));
2673 free(c);
2674 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2675 }
2676 return (1);
2677 }
2678
2679 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2680 {
2681 struct ssh1_3des_ctx *c;
2682
2683 if (len != 24)
2684 //fatal("%s: bad 3des iv length: %d", __func__, len);
2685 ;
2686
2687 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2688 //fatal("%s: no 3des context", __func__);
2689 ;
2690
2691 if (doset) {
2692 //debug3("%s: Installed 3DES IV", __func__);
2693 memcpy(c->k1.iv, iv, 8);
2694 memcpy(c->k2.iv, iv + 8, 8);
2695 memcpy(c->k3.iv, iv + 16, 8);
2696 } else {
2697 //debug3("%s: Copying 3DES IV", __func__);
2698 memcpy(iv, c->k1.iv, 8);
2699 memcpy(iv + 8, c->k2.iv, 8);
2700 memcpy(iv + 16, c->k3.iv, 8);
2701 }
2702 }
2703
2704 const EVP_CIPHER *evp_ssh1_3des(void)
2705 {
2706 static EVP_CIPHER ssh1_3des;
2707
2708 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2709 ssh1_3des.nid = NID_undef;
2710 ssh1_3des.block_size = 8;
2711 ssh1_3des.iv_len = 0;
2712 ssh1_3des.key_len = 16;
2713 ssh1_3des.init = ssh1_3des_init;
2714 ssh1_3des.cleanup = ssh1_3des_cleanup;
2715 ssh1_3des.do_cipher = ssh1_3des_cbc;
2716 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2717 return (&ssh1_3des);
2718 }
2719
2720 static void ssh_make_comment(char *comment, int maxlen)
2721 {
2722 char user[UNLEN + 1], host[128];
2723 DWORD dwSize;
2724 WSADATA wsaData;
2725 int ret;
2726
2727 // get Windows logon user name
2728 dwSize = sizeof(user);
2729 if (GetUserName(user, &dwSize) == 0) {
2730 strncpy_s(user, sizeof(user), "yutaka", _TRUNCATE);
2731 }
2732
2733 // get local hostname (by WinSock)
2734 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2735 if (ret == 0) {
2736 if (gethostname(host, sizeof(host)) != 0) {
2737 ret = WSAGetLastError();
2738 }
2739 WSACleanup();
2740 }
2741 if (ret != 0) {
2742 strncpy_s(host, sizeof(host), "sai", _TRUNCATE);
2743 }
2744
2745 _snprintf_s(comment, maxlen, _TRUNCATE, "%s@%s", user, host);
2746 }
2747
2748 // uuencode (rfc1521)
2749 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2750 {
2751 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2752 char pad = '=';
2753 int datalength = 0;
2754 unsigned char input[3];
2755 unsigned char output[4];
2756 int i;
2757
2758 while (srclen > 2) {
2759 input[0] = *src++;
2760 input[1] = *src++;
2761 input[2] = *src++;
2762 srclen -= 3;
2763
2764 output[0] = input[0] >> 2;
2765 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2766 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2767 output[3] = input[2] & 0x3f;
2768 if (output[0] >= 64 ||
2769 output[1] >= 64 ||
2770 output[2] >= 64 ||
2771 output[3] >= 64)
2772 return -1;
2773
2774 if (datalength + 4 > targsize)
2775 return (-1);
2776 target[datalength++] = base64[output[0]];
2777 target[datalength++] = base64[output[1]];
2778 target[datalength++] = base64[output[2]];
2779 target[datalength++] = base64[output[3]];
2780 }
2781
2782 if (srclen != 0) {
2783 /* Get what's left. */
2784 input[0] = input[1] = input[2] = '\0';
2785 for (i = 0; i < srclen; i++)
2786 input[i] = *src++;
2787
2788 output[0] = input[0] >> 2;
2789 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2790 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2791 if (output[0] >= 64 ||
2792 output[1] >= 64 ||
2793 output[2] >= 64)
2794 return -1;
2795
2796 if (datalength + 4 > targsize)
2797 return (-1);
2798 target[datalength++] = base64[output[0]];
2799 target[datalength++] = base64[output[1]];
2800 if (srclen == 1)
2801 target[datalength++] = pad;
2802 else
2803 target[datalength++] = base64[output[2]];
2804 target[datalength++] = pad;
2805 }
2806 if (datalength >= targsize)
2807 return (-1);
2808 target[datalength] = '\0'; /* Returned value doesn't count \0. */
2809
2810 return (datalength); // success
2811 }
2812
2813 static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2814 LPARAM lParam)
2815 {
2816 static enum hostkey_type key_type;
2817 char uimsg[MAX_UIMSG];
2818 LOGFONT logfont;
2819 HFONT font;
2820
2821 switch (msg) {
2822 case WM_INITDIALOG:
2823 {
2824 GetWindowText(dlg, uimsg, sizeof(uimsg));
2825 UTIL_get_lang_msg("DLG_KEYGEN_TITLE", pvar, uimsg);
2826 SetWindowText(dlg, pvar->ts->UIMsg);
2827 GetDlgItemText(dlg, IDC_KEYTYPE, uimsg, sizeof(uimsg));
2828 UTIL_get_lang_msg("DLG_KEYGEN_KEYTYPE", pvar, uimsg);
2829 SetDlgItemText(dlg, IDC_KEYTYPE, pvar->ts->UIMsg);
2830 GetDlgItemText(dlg, IDC_KEY_LABEL, uimsg, sizeof(uimsg));
2831 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE", pvar, uimsg);
2832 SetDlgItemText(dlg, IDC_KEY_LABEL, pvar->ts->UIMsg);
2833 GetDlgItemText(dlg, IDC_CONFIRM_LABEL, uimsg, sizeof(uimsg));
2834 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE2", pvar, uimsg);
2835 SetDlgItemText(dlg, IDC_CONFIRM_LABEL, pvar->ts->UIMsg);
2836 GetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, uimsg, sizeof(uimsg));
2837 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPUBLIC", pvar, uimsg);
2838 SetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, pvar->ts->UIMsg);
2839 GetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, uimsg, sizeof(uimsg));
2840 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPRIVATE", pvar, uimsg);
2841 SetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, pvar->ts->UIMsg);
2842 GetDlgItemText(dlg, IDOK, uimsg, sizeof(uimsg));
2843 UTIL_get_lang_msg("DLG_KEYGEN_GENERATE", pvar, uimsg);
2844 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2845 GetDlgItemText(dlg, IDCANCEL, uimsg, sizeof(uimsg));
2846 UTIL_get_lang_msg("BTN_CANCEL", pvar, uimsg);