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 3040 - (show annotations) (download) (as text)
Wed Oct 17 04:06:57 2007 UTC (16 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 111347 byte(s)
SSH2 の暗号方式として AES192 をサポートした。

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