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 2982 - (show annotations) (download) (as text)
Thu Jul 5 12:16:11 2007 UTC (16 years, 9 months ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 120034 byte(s)
利用可能なCOMポートが無い時、新しい接続ダイアログでシリアルポートの選択を無効化した。

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