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 3009 - (show annotations) (download) (as text)
Wed Sep 5 12:07:04 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109590 byte(s)
接続ダイアログのホスト名ドロップダウンにおいて、Ctrl+a/Ctrl+e を使って先頭/終端に移動できるようにした。

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