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 3006 - (show annotations) (download) (as text)
Thu Aug 30 13:18:20 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107237 byte(s)
MaxComPort を越えるシリアルポートを表示しないようにした。

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