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 3000 - (show annotations) (download) (as text)
Sun Aug 19 13:07:48 2007 UTC (16 years, 7 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 107116 byte(s)
不正な修正を元に戻した。

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