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 3036 - (show annotations) (download) (as text)
Tue Oct 16 15:28:14 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 111276 byte(s)
SSH2 の暗号方式として AES256 をサポートした。

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