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 3015 - (show annotations) (download) (as text)
Sun Sep 30 14:03:02 2007 UTC (16 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109895 byte(s)
サポートされていない認証メソッドをはじめから無効にする機能を追加した。

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