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 2964 - (show annotations) (download) (as text)
Sun Mar 4 18:02:36 2007 UTC (17 years, 1 month ago) by doda
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 119447 byte(s)
New connection$B$*$h$S(BSerial port setup$B%@%$%"%m%0$G!"MxMQ2DG=$J%7%j%"%k%]!<%H$N$_(B>
$B$rI=<($9$k$h$&$K$7$?!#(B

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