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 3011 - (show annotations) (download) (as text)
Sat Sep 22 16:10:45 2007 UTC (16 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 109425 byte(s)
password 認証で keyboard-interactive を使用するのをやめた。
明示的に challange/response を選択する必要がある。

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