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 2947 - (show annotations) (download) (as text)
Thu Jan 4 11:59:03 2007 UTC (17 years, 3 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 114376 byte(s)
フォントを変更する部分を追加した。

1 /*
2 Copyright (c) 1998-2001, Robert O'Callahan
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list of
9 conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this list
12 of conditions and the following disclaimer in the documentation and/or other materials
13 provided with the distribution.
14
15 The name of Robert O'Callahan may not be used to endorse or promote products derived from
16 this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Teraterm extension mechanism
30 Robert O'Callahan (roc+tt@cs.cmu.edu)
31
32 Teraterm by Takashi Teranishi (teranishi@rikaxp.riken.go.jp)
33 */
34
35 #include "ttxssh.h"
36 #include "fwdui.h"
37 #include "util.h"
38 #include "ssh.h"
39
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 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
895 LPARAM lParam)
896 {
897 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
898 PGetHNRec GetHNRec;
899 char EntName[7];
900 char TempHost[HostNameMaxLength + 1];
901 WORD i, j, w;
902 BOOL Ok;
903 #ifdef I18N
904 LOGFONT logfont;
905 HFONT font;
906 #endif
907
908 GET_VAR();
909
910 switch (msg) {
911 case WM_INITDIALOG:
912 GetHNRec = (PGetHNRec) lParam;
913 SetWindowLong(dlg, DWL_USER, lParam);
914
915 #ifdef I18N
916 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
917 UTIL_get_lang_msg("DLG_HOST_TITLE", pvar);
918 SetWindowText(dlg, pvar->ts->UIMsg);
919
920 GetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
921 UTIL_get_lang_msg("DLG_HOST_TCPIP_HOST", pvar);
922 SetDlgItemText(dlg, IDC_HOSTNAMELABEL, pvar->ts->UIMsg);
923
924 GetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
925 UTIL_get_lang_msg("DLG_HOST_TCPIP_HISTORY", pvar);
926 SetDlgItemText(dlg, IDC_HISTORY, pvar->ts->UIMsg);
927
928 GetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
929 UTIL_get_lang_msg("DLG_HOST_TCPIP_SERVICE", pvar);
930 SetDlgItemText(dlg, IDC_SERVICELABEL, pvar->ts->UIMsg);
931
932 GetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
933 UTIL_get_lang_msg("IDC_HOSTOTHER", pvar);
934 SetDlgItemText(dlg, IDC_HOSTOTHER, pvar->ts->UIMsg);
935
936 GetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
937 UTIL_get_lang_msg("DLG_HOST_TCPIP_PORT", pvar);
938 SetDlgItemText(dlg, IDC_HOSTTCPPORTLABEL, pvar->ts->UIMsg);
939
940 GetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
941 UTIL_get_lang_msg("DLG_HOST_TCPIP_SSHVERSION", pvar);
942 SetDlgItemText(dlg, IDC_SSH_VERSION_LABEL, pvar->ts->UIMsg);
943
944 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
945 UTIL_get_lang_msg("DLG_HOST_TCPIP_PROTOCOL", pvar);
946 SetDlgItemText(dlg, IDC_HOSTTCPPROTOCOLLABEL, pvar->ts->UIMsg);
947
948 GetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
949 UTIL_get_lang_msg("DLG_HOST_SERIAL", pvar);
950 SetDlgItemText(dlg, IDC_HOSTSERIAL, pvar->ts->UIMsg);
951
952 GetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
953 UTIL_get_lang_msg("DLG_HOST_SERIAL_PORT", pvar);
954 SetDlgItemText(dlg, IDC_HOSTCOMLABEL, pvar->ts->UIMsg);
955
956 GetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
957 UTIL_get_lang_msg("DLG_HOST_HELP", pvar);
958 SetDlgItemText(dlg, IDC_HOSTHELP, pvar->ts->UIMsg);
959
960 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
961 UTIL_get_lang_msg("BTN_OK", pvar);
962 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
963
964 GetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
965 UTIL_get_lang_msg("BTN_CANCEL", pvar);
966 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
967 #endif
968
969 // �z�X�g�q�X�g�����`�F�b�N�{�b�N�X������ (2005.10.21 yutaka)
970 if (pvar->ts->HistoryList > 0) {
971 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_CHECKED, 0);
972 } else {
973 SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_SETCHECK, BST_UNCHECKED, 0);
974 }
975
976 if (GetHNRec->PortType == IdFile)
977 GetHNRec->PortType = IdTCPIP;
978 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
979 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
980
981 strcpy(EntName, "Host");
982
983 i = 1;
984 do {
985 sprintf(&EntName[4], "%d", i);
986 GetPrivateProfileString("Hosts", EntName, "",
987 TempHost, sizeof(TempHost),
988 GetHNRec->SetupFN);
989 if (strlen(TempHost) > 0)
990 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
991 0, (LPARAM) TempHost);
992 i++;
993 } while ((i <= 99) && (strlen(TempHost) > 0));
994
995 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
996 HostNameMaxLength - 1, 0);
997
998 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
999
1000 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
1001 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
1002 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
1003 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
1004 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
1005 #ifdef INET6
1006 for (i = 0; ProtocolFamilyList[i]; ++i) {
1007 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
1008 0, (LPARAM) ProtocolFamilyList[i]);
1009 }
1010 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
1011 ProtocolFamilyMaxLength - 1, 0);
1012 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
1013 #endif /* INET6 */
1014
1015 /////// SSH version
1016 for (i = 0; ssh_version[i]; ++i) {
1017 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
1018 0, (LPARAM) ssh_version[i]);
1019 }
1020 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
1021 NUM_ELEM(ssh_version) - 1, 0);
1022
1023 if (pvar->settings.ssh_protocol_version == 1) {
1024 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
1025 } else {
1026 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
1027 }
1028
1029 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1030 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
1031 } else {
1032 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1033 }
1034 /////// SSH version
1035
1036
1037 j = 0;
1038 w = 1;
1039 strcpy(EntName, "COM");
1040 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
1041 sprintf(&EntName[3], "%d", i);
1042 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
1043 0, (LPARAM) EntName);
1044 j++;
1045 if (GetHNRec->ComPort == i)
1046 w = j;
1047 }
1048 if (j > 0)
1049 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
1050 else /* All com ports are already used */
1051 GetHNRec->PortType = IdTCPIP;
1052
1053 if (GetHNRec->PortType == IdTCPIP) {
1054 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1055
1056 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1057 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE);
1058 }
1059 #ifdef INET6
1060 else {
1061 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1062 FALSE);
1063 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1064 IDC_HOSTTCPPROTOCOL, FALSE);
1065
1066 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1067 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1068 }
1069 #else
1070 else
1071 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1072 FALSE);
1073 #endif /* INET6 */
1074
1075 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
1076 if (GetHNRec->PortType == IdTCPIP) {
1077 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
1078 SetFocus(hwnd);
1079 } else {
1080 HWND hwnd = GetDlgItem(dlg, IDC_HOSTCOM);
1081 SetFocus(hwnd);
1082 }
1083
1084 #ifdef I18N
1085 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1086 GetObject(font, sizeof(LOGFONT), &logfont);
1087 if (UTIL_get_lang_font("DLG_SYSTEM_FONT", dlg, &logfont, &DlgHostFont, pvar)) {
1088 SendDlgItemMessage(dlg, IDC_HOSTTCPIP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1089 SendDlgItemMessage(dlg, IDC_HOSTNAMELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1090 SendDlgItemMessage(dlg, IDC_HOSTNAME, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1091 SendDlgItemMessage(dlg, IDC_HISTORY, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1092 SendDlgItemMessage(dlg, IDC_SERVICELABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1093 SendDlgItemMessage(dlg, IDC_HOSTTELNET, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1094 SendDlgItemMessage(dlg, IDC_HOSTSSH, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1095 SendDlgItemMessage(dlg, IDC_HOSTOTHER, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1096 SendDlgItemMessage(dlg, IDC_HOSTTCPPORTLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1097 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1098 SendDlgItemMessage(dlg, IDC_SSH_VERSION_LABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1099 SendDlgItemMessage(dlg, IDC_SSH_VERSION, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1100 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOLLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1101 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1102 SendDlgItemMessage(dlg, IDC_HOSTSERIAL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1103 SendDlgItemMessage(dlg, IDC_HOSTCOMLABEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1104 SendDlgItemMessage(dlg, IDC_HOSTCOM, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1105 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1106 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1107 SendDlgItemMessage(dlg, IDC_HOSTHELP, WM_SETFONT, (WPARAM)DlgHostFont, MAKELPARAM(TRUE,0));
1108 }
1109 else {
1110 DlgHostFont = NULL;
1111 }
1112 #endif
1113
1114 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
1115 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
1116 // (2004.11.23 yutaka)
1117 return FALSE;
1118 //return TRUE;
1119
1120 case WM_COMMAND:
1121 switch (LOWORD(wParam)) {
1122 case IDOK:
1123 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1124 if (GetHNRec != NULL) {
1125 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
1126 #ifdef INET6
1127 char afstr[BUFSIZ];
1128 #endif /* INET6 */
1129 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
1130 if (Ok) {
1131 GetHNRec->TCPPort = i;
1132 } else {
1133 #ifdef I18N
1134 strcpy(pvar->ts->UIMsg, "The TCP port must be a number.");
1135 UTIL_get_lang_msg("MSG_TCPPORT_NAN_ERROR", pvar);
1136 MessageBox(dlg, pvar->ts->UIMsg,
1137 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1138 #else
1139 MessageBox(dlg, "The TCP port must be a number.",
1140 "Teraterm", MB_OK | MB_ICONEXCLAMATION);
1141 #endif
1142 return TRUE;
1143 }
1144 #ifdef INET6
1145 #define getaf(str) \
1146 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
1147 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
1148 memset(afstr, 0, sizeof(afstr));
1149 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
1150 sizeof(afstr));
1151 GetHNRec->ProtocolFamily = getaf(afstr);
1152 #endif /* INET6 */
1153 GetHNRec->PortType = IdTCPIP;
1154 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
1155 HostNameMaxLength);
1156 GetHNRec->Telnet = FALSE;
1157 pvar->hostdlg_activated = TRUE;
1158 pvar->hostdlg_Enabled = FALSE;
1159 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1160 GetHNRec->Telnet = TRUE;
1161 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1162 pvar->hostdlg_Enabled = TRUE;
1163
1164 // check SSH protocol version
1165 memset(afstr, 0, sizeof(afstr));
1166 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
1167 if (_stricmp(afstr, "SSH1") == 0) {
1168 pvar->settings.ssh_protocol_version = 1;
1169 } else {
1170 pvar->settings.ssh_protocol_version = 2;
1171 }
1172 }
1173
1174 // host history check button
1175 if (SendMessage(GetDlgItem(dlg, IDC_HISTORY), BM_GETCHECK, 0, 0) == BST_CHECKED) {
1176 pvar->ts->HistoryList = 1;
1177 } else {
1178 pvar->ts->HistoryList = 0;
1179 }
1180
1181 } else {
1182 GetHNRec->PortType = IdSerial;
1183 GetHNRec->HostName[0] = 0;
1184 memset(EntName, 0, sizeof(EntName));
1185 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1186 sizeof(EntName) - 1);
1187 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1188 if (strlen(EntName) > 4)
1189 GetHNRec->ComPort =
1190 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1191 0x30;
1192 }
1193 }
1194 EndDialog(dlg, 1);
1195
1196 #ifdef I18N
1197 if (DlgHostFont != NULL) {
1198 DeleteObject(DlgHostFont);
1199 }
1200 #endif
1201
1202 return TRUE;
1203
1204 case IDCANCEL:
1205 EndDialog(dlg, 0);
1206
1207 #ifdef I18N
1208 if (DlgHostFont != NULL) {
1209 DeleteObject(DlgHostFont);
1210 }
1211 #endif
1212
1213 return TRUE;
1214
1215 case IDC_HOSTTCPIP:
1216 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1217 TRUE);
1218 #ifdef INET6
1219 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1220 IDC_HOSTTCPPROTOCOL, TRUE);
1221 #endif /* INET6 */
1222 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1223
1224 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1225 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1226 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1227 } else {
1228 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1229 }
1230
1231 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, TRUE); // disabled
1232
1233 return TRUE;
1234
1235 case IDC_HOSTSERIAL:
1236 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1237 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1238 FALSE);
1239 #ifdef INET6
1240 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1241 IDC_HOSTTCPPROTOCOL, FALSE);
1242 #endif /* INET6 */
1243 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1244 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1245
1246 enable_dlg_items(dlg, IDC_HISTORY, IDC_HISTORY, FALSE); // disabled
1247
1248 return TRUE;
1249
1250 case IDC_HOSTSSH:
1251 enable_dlg_items(dlg, IDC_SSH_VERSION,
1252 IDC_SSH_VERSION, TRUE);
1253 goto hostssh_enabled;
1254
1255 case IDC_HOSTTELNET:
1256 case IDC_HOSTOTHER:
1257 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1258 hostssh_enabled:
1259
1260 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1261
1262 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1263 if (GetHNRec != NULL)
1264 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1265 FALSE);
1266 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1267 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1268 }
1269 return TRUE;
1270
1271 case IDC_HOSTHELP:
1272 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1273 }
1274 }
1275 return FALSE;
1276 }
1277
1278 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1279 {
1280 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1281 parent, TTXHostDlg, (LONG) rec);
1282 }
1283
1284 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1285 {
1286 GET_VAR();
1287
1288 *hooks->GetHostName = TTXGetHostName;
1289 }
1290
1291 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1292 {
1293 GET_VAR();
1294
1295 (pvar->ReadIniFile) (fileName, ts);
1296 read_ssh_options(pvar, fileName);
1297 pvar->settings = *pvar->ts_SSH;
1298 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1299 FWDUI_load_settings(pvar);
1300 }
1301
1302 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1303 {
1304 GET_VAR();
1305
1306 (pvar->WriteIniFile) (fileName, ts);
1307 *pvar->ts_SSH = pvar->settings;
1308 clear_local_settings(pvar);
1309 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1310 write_ssh_options(pvar, fileName, pvar->ts_SSH, TRUE);
1311 }
1312
1313 static void read_ssh_options_from_user_file(PTInstVar pvar,
1314 char FAR * user_file_name)
1315 {
1316 if (user_file_name[0] == '.') {
1317 read_ssh_options(pvar, user_file_name);
1318 } else {
1319 char buf[1024];
1320
1321 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1322 read_ssh_options(pvar, buf);
1323 }
1324
1325 pvar->settings = *pvar->ts_SSH;
1326 FWDUI_load_settings(pvar);
1327 }
1328
1329
1330 // @���u�����N���u�������B (2005.1.26 yutaka)
1331 static void replace_to_blank(char *src, char *dst, int dst_len)
1332 {
1333 int len, i;
1334
1335 len = strlen(src);
1336 if (dst_len < len) // buffer overflow check
1337 return;
1338
1339 for (i = 0 ; i < len ; i++) {
1340 if (src[i] == '@') { // @ ���o��������
1341 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1342 *dst++ = '@';
1343 i++;
1344 } else {
1345 *dst++ = ' '; // �������u��������
1346 }
1347 } else {
1348 *dst++ = src[i];
1349 }
1350 }
1351 *dst = '\0';
1352 }
1353
1354 /* returns 1 if the option text must be deleted */
1355 static int parse_option(PTInstVar pvar, char FAR * option)
1356 {
1357 if ((option[0] == '-' || option[0] == '/')) {
1358 if (MATCH_STR(option + 1, "ssh") == 0) {
1359 if (option[4] == 0) {
1360 pvar->settings.Enabled = 1;
1361 } else if (MATCH_STR(option + 4, "-L") == 0
1362 || MATCH_STR(option + 4, "-R") == 0
1363 || _stricmp(option + 4, "-X") == 0) {
1364 if (pvar->settings.DefaultForwarding[0] == 0) {
1365 strcpy(pvar->settings.DefaultForwarding, option + 5);
1366 } else {
1367 strcat(pvar->settings.DefaultForwarding, ";");
1368 strcat(pvar->settings.DefaultForwarding, option + 5);
1369 }
1370 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1371 read_ssh_options_from_user_file(pvar, option + 7);
1372 } else if (MATCH_STR(option + 4, "-v") == 0) {
1373 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1374 } else if (_stricmp(option + 4, "-autologin") == 0
1375 || _stricmp(option + 4, "-autologon") == 0) {
1376 pvar->settings.TryDefaultAuth = TRUE;
1377
1378 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1379 read_ssh_options_from_user_file(pvar, option + 13);
1380 DeleteFile(option + 13);
1381
1382 // /ssh1 �� /ssh2 �I�v�V�������V�K���� (2006.9.16 maya)
1383 } else if (MATCH_STR(option + 4, "1") == 0) {
1384 pvar->settings.ssh_protocol_version = 1;
1385 } else if (MATCH_STR(option + 4, "2") == 0) {
1386 pvar->settings.ssh_protocol_version = 2;
1387
1388 } else {
1389 char buf[1024];
1390
1391 #ifdef I18N
1392 strcpy(pvar->ts->UIMsg, "Unrecognized command-line option: %s");
1393 UTIL_get_lang_msg("MSG_UNKNOWN_OPTION_ERROR", pvar);
1394 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg, option);
1395 #else
1396 _snprintf(buf, sizeof(buf),
1397 "Unrecognized command-line option: %s", option);
1398 #endif
1399 buf[sizeof(buf) - 1] = 0;
1400
1401 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1402 }
1403
1404 return 1;
1405
1406 // ttermpro.exe �� /T= �w�������p�������A������������ (2006.10.19 maya)
1407 } else if (MATCH_STR_I(option + 1, "t=") == 0) {
1408 if (strcmp(option + 3, "2") == 0) {
1409 pvar->settings.Enabled = 1;
1410 return 1;
1411 } else {
1412 pvar->settings.Enabled = 0;
1413 }
1414
1415 // ttermpro.exe �� /F= �w������ TTSSH ������������ (2006.10.11 maya)
1416 } else if (MATCH_STR_I(option + 1, "f=") == 0) {
1417 read_ssh_options_from_user_file(pvar, option + 3);
1418
1419 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1420 } else if (MATCH_STR(option + 1, "1") == 0) {
1421 // command line: /ssh /1 is SSH1 only
1422 pvar->settings.ssh_protocol_version = 1;
1423
1424 } else if (MATCH_STR(option + 1, "2") == 0) {
1425 // command line: /ssh /2 is SSH2 & SSH1
1426 pvar->settings.ssh_protocol_version = 2;
1427
1428 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1429 // '/nossh' �I�v�V�����������B
1430 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1431 // �����������������B(2004.10.11 yutaka)
1432 pvar->settings.Enabled = 0;
1433
1434 } else if (MATCH_STR(option + 1, "telnet") == 0) {
1435 // '/telnet' ���w�������������������� '/nossh' ��������
1436 // SSH������������ (2006.9.16 maya)
1437 pvar->settings.Enabled = 0;
1438
1439 } else if (MATCH_STR(option + 1, "auth") == 0) {
1440 // SSH2�������O�C���I�v�V����������
1441 //
1442 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1443 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1444 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1445 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1446 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1447 //
1448 // (2004.11.30 yutaka)
1449 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1450 //
1451 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1452
1453 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h/keyboard-interactive�F��
1454 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1455 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1456
1457 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1458 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1459 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1460
1461 } else {
1462 // TODO:
1463
1464 }
1465
1466 } else if (MATCH_STR(option + 1, "user=") == 0) {
1467 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1468 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1469
1470 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1471 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1472 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1473
1474 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1475 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1476
1477 } else if (MATCH_STR(option + 1, "ask4passwd") == 0) {
1478 // �p�X���[�h������ (2006.9.18 maya)
1479 pvar->ask4passwd = 1;
1480
1481 }
1482
1483 // �p�X���[�h�������������������O�C��������������
1484 // /auth ���F�����\�b�h���w�������������p������ (2006.9.18 maya)
1485 if (pvar->ask4passwd == 1) {
1486 pvar->ssh2_autologin = 0;
1487 }
1488
1489 }
1490
1491 return 0;
1492 }
1493
1494 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1495 PCHAR DDETopic)
1496 {
1497 // �X�y�[�X�������t�@�C�������F�������������C�� (2006.10.7 maya)
1498 int i;
1499 BOOL inParam = FALSE;
1500 BOOL inQuotes = FALSE;
1501 BOOL inFileParam = FALSE;
1502 PCHAR option = NULL;
1503 GET_VAR();
1504
1505 if (pvar->hostdlg_activated) {
1506 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1507 }
1508
1509 for (i = 0; param[i] != 0; i++) {
1510 if (inQuotes ? param[i] == '"'
1511 : (param[i] == ' ' || param[i] == '\t')) {
1512 if (option != NULL) {
1513 char ch = param[i];
1514 PCHAR Equal;
1515
1516 param[i] = 0;
1517 Equal = strchr(option, '=');
1518 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1519 char *buf = (char *)calloc(strlen(option), sizeof(char));
1520 strncat(buf, option, Equal - option + 1);
1521 strcat(buf, Equal + 2);
1522 if (parse_option
1523 (pvar, *buf == '"' ? buf + 1 : buf)) {
1524 memset(option, ' ', i + 1 - (option - param));
1525 } else {
1526 param[i] = ch;
1527 }
1528 free(buf);
1529 }
1530 else {
1531 if (parse_option
1532 (pvar, *option == '"' ? option + 1 : option)) {
1533 memset(option, ' ', i + 1 - (option - param));
1534 } else {
1535 param[i] = ch;
1536 }
1537 }
1538 option = NULL;
1539 }
1540 inParam = FALSE;
1541 inQuotes = FALSE;
1542 inFileParam = FALSE;
1543 } else if (!inParam) {
1544 if (param[i] == '"') {
1545 inQuotes = TRUE;
1546 inParam = TRUE;
1547 option = param + i;
1548 } else if (param[i] != ' ' && param[i] != '\t') {
1549 inParam = TRUE;
1550 option = param + i;
1551 }
1552 } else {
1553 if (option == NULL) {
1554 continue;
1555 }
1556 if ((option[0] == '-' || option[0] == '/') &&
1557 (MATCH_STR(option + 1, "ssh-f=") == 0 ||
1558 MATCH_STR(option + 1, "ssh-consume=") == 0 ||
1559 MATCH_STR_I(option + 1, "f=") == 0)) {
1560 if (param[i] == '"') {
1561 inQuotes = TRUE;
1562 }
1563 inFileParam = TRUE;
1564 }
1565 }
1566 }
1567
1568 if (option != NULL) {
1569 PCHAR Equal = strchr(option, '=');
1570 if (inFileParam && Equal != NULL && *(Equal + 1) == '"') {
1571 char *buf = (char *)calloc(strlen(option), sizeof(char));
1572 strncat(buf, option, Equal - option + 1);
1573 strcat(buf, Equal + 2);
1574 if (parse_option
1575 (pvar, *buf == '"' ? buf + 1 : buf)) {
1576 memset(option, ' ', i + 1 - (option - param));
1577 }
1578 free(buf);
1579 }
1580 else {
1581 if (parse_option(pvar, option)) {
1582 memset(option, ' ', i - (option - param));
1583 }
1584 }
1585 }
1586
1587 FWDUI_load_settings(pvar);
1588
1589 (pvar->ParseParam) (param, ts, DDETopic);
1590
1591 }
1592
1593 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1594 {
1595 GET_VAR();
1596
1597 pvar->ReadIniFile = *hooks->ReadIniFile;
1598 pvar->WriteIniFile = *hooks->WriteIniFile;
1599 pvar->ParseParam = *hooks->ParseParam;
1600
1601 *hooks->ReadIniFile = TTXReadINIFile;
1602 *hooks->WriteIniFile = TTXWriteINIFile;
1603 *hooks->ParseParam = TTXParseParam;
1604 }
1605
1606 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1607 {
1608 GET_VAR();
1609
1610 SSH_notify_win_size(pvar, cols, rows);
1611 }
1612
1613 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1614 WORD newItemID, char FAR * text)
1615 {
1616 int i, j;
1617
1618 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1619 HMENU submenu = GetSubMenu(menu, i);
1620
1621 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1622 if (GetMenuItemID(submenu, j) == beforeItemID) {
1623 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1624 text);
1625 return;
1626 }
1627 }
1628 }
1629 }
1630
1631 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1632 {
1633 GET_VAR();
1634
1635 /* inserts before ID_HELP_ABOUT */
1636 #ifdef I18N
1637 strcpy(pvar->ts->UIMsg, "About &TTSSH...");
1638 UTIL_get_lang_msg("MENU_ABOUT", pvar);
1639 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU, pvar->ts->UIMsg);
1640 #else
1641 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1642 "About &TTSSH...");
1643 #endif
1644
1645 /* inserts before ID_SETUP_TCPIP */
1646 #ifdef I18N
1647 strcpy(pvar->ts->UIMsg, "SS&H...");
1648 UTIL_get_lang_msg("MENU_SSH", pvar);
1649 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU, pvar->ts->UIMsg);
1650 #else
1651 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1652 "SS&H...");
1653 #endif
1654 /* inserts before ID_SETUP_TCPIP */
1655 #ifdef I18N
1656 strcpy(pvar->ts->UIMsg, "SSH &Authentication...");
1657 UTIL_get_lang_msg("MENU_SSH_AUTH", pvar);
1658 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU, pvar->ts->UIMsg);
1659 #else
1660 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1661 "SSH &Authentication...");
1662 #endif
1663 /* inserts before ID_SETUP_TCPIP */
1664 #ifdef I18N
1665 strcpy(pvar->ts->UIMsg, "SSH F&orwarding...");
1666 UTIL_get_lang_msg("MENU_SSH_FORWARD", pvar);
1667 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU, pvar->ts->UIMsg);
1668 #else
1669 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1670 "SSH F&orwarding...");
1671 #endif
1672
1673 #ifdef I18N
1674 strcpy(pvar->ts->UIMsg, "SSH KeyGenerator...");
1675 UTIL_get_lang_msg("MENU_SSH_KEYGEN", pvar);
1676 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU, pvar->ts->UIMsg);
1677 #else
1678 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHKEYGENMENU,
1679 "SSH KeyGenerator...");
1680 #endif
1681 }
1682
1683 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1684 {
1685 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1686 (LPARAM) prefix);
1687 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1688 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1689 (LPARAM) (char FAR *) "\r\n");
1690 }
1691
1692 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1693 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1694 {
1695 typedef struct {
1696 WORD wLanguage;
1697 WORD wCodePage;
1698 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1699 LPLANGANDCODEPAGE lplgcode;
1700 UINT unLen;
1701 DWORD size;
1702 char *buf = NULL;
1703 BOOL ret;
1704 int i;
1705 char fmt[80];
1706 char *pbuf;
1707
1708 size = GetFileVersionInfoSize(exefile, NULL);
1709 if (size == 0) {
1710 goto error;
1711 }
1712 buf = malloc(size);
1713 ZeroMemory(buf, size);
1714
1715 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1716 goto error;
1717 }
1718
1719 ret = VerQueryValue(buf,
1720 "\\VarFileInfo\\Translation",
1721 (LPVOID *)&lplgcode, &unLen);
1722 if (ret == FALSE)
1723 goto error;
1724
1725 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1726 _snprintf(fmt, sizeof(fmt), "\\StringFileInfo\\%04x%04x\\FileVersion",
1727 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1728 VerQueryValue(buf, fmt, &pbuf, &unLen);
1729 if (unLen > 0) { // get success
1730 int n, a, b, c, d;
1731
1732 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1733 if (n == 4) { // convert success
1734 *major = a;
1735 *minor = b;
1736 *release = c;
1737 *build = d;
1738 break;
1739 }
1740 }
1741 }
1742
1743 free(buf);
1744 return;
1745
1746 error:
1747 free(buf);
1748 *major = *minor = *release = *build = 0;
1749 }
1750
1751 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1752 {
1753 char buf[1024];
1754 int a, b, c, d;
1755
1756 #ifdef I18N
1757 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1758 UTIL_get_lang_msg("DLG_ABOUT_TITLE", pvar);
1759 SetWindowText(dlg, pvar->ts->UIMsg);
1760
1761 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1762 UTIL_get_lang_msg("BTN_OK", pvar);
1763 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
1764 #endif
1765
1766 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1767 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1768 _snprintf(buf, sizeof(buf), "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1769 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1770
1771 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1772 // ���������� (2005.5.11 yutaka)
1773 #ifdef OPENSSL_VERSION_TEXT
1774 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1775 #else
1776 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)"Unknown");
1777 #endif
1778
1779 // zlib���o�[�W�������������� (2005.5.11 yutaka)
1780 #ifdef ZLIB_VERSION
1781 _snprintf(buf, sizeof(buf), "ZLib %s", ZLIB_VERSION);
1782 #else
1783 _snprintf(buf, sizeof(buf), "ZLib Unknown");
1784 #endif
1785 SendMessage(GetDlgItem(dlg, IDC_ZLIB_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1786
1787
1788 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1789 if (pvar->socket != INVALID_SOCKET) {
1790 if (SSHv1(pvar)) {
1791 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1792 append_about_text(dlg, "Server ID: ", buf);
1793 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1794 append_about_text(dlg, "Using protocol: ", buf);
1795 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1796 append_about_text(dlg, "Encryption: ", buf);
1797 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1798 append_about_text(dlg, "Server keys: ", buf);
1799 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1800 append_about_text(dlg, "Authentication: ", buf);
1801 SSH_get_compression_info(pvar, buf, sizeof(buf));
1802 append_about_text(dlg, "Compression: ", buf);
1803
1804 } else { // SSH2
1805 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1806 append_about_text(dlg, "Server ID: ", buf);
1807
1808 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1809
1810 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1811 append_about_text(dlg, "Using protocol: ", buf);
1812
1813 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1814 strcpy(buf, KEX_DH1);
1815 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1816 strcpy(buf, KEX_DH14);
1817 } else {
1818 strcpy(buf, KEX_DHGEX);
1819 }
1820 append_about_text(dlg, "KEX: ", buf);
1821
1822 if (pvar->hostkey_type == KEY_DSA) {
1823 strcpy(buf, "ssh-dss");
1824 } else {
1825 strcpy(buf, "ssh-rsa");
1826 }
1827 append_about_text(dlg, "Host Key: ", buf);
1828
1829 // add HMAC algorithm (2004.12.17 yutaka)
1830 buf[0] = '\0';
1831 if (pvar->ctos_hmac == HMAC_SHA1) {
1832 strcat(buf, "hmac-sha1");
1833 } else if (pvar->ctos_hmac == HMAC_MD5) {
1834 strcat(buf, "hmac-md5");
1835 }
1836 strcat(buf, " to server, ");
1837 if (pvar->stoc_hmac == HMAC_SHA1) {
1838 strcat(buf, "hmac-sha1");
1839 } else if (pvar->stoc_hmac == HMAC_MD5) {
1840 strcat(buf, "hmac-md5");
1841 }
1842 strcat(buf, " from server");
1843 append_about_text(dlg, "HMAC: ", buf);
1844
1845 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1846 append_about_text(dlg, "Encryption: ", buf);
1847 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1848 append_about_text(dlg, "Server keys: ", buf);
1849 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1850 append_about_text(dlg, "Authentication: ", buf);
1851
1852 SSH_get_compression_info(pvar, buf, sizeof(buf));
1853 if (pvar->ctos_compression == COMP_DELAYED) { // �x���p�P�b�g���k������ (2006.6.23 yutaka)
1854 append_about_text(dlg, "Delayed Compression: ", buf);
1855 } else {
1856 append_about_text(dlg, "Compression: ", buf);
1857 }
1858
1859 }
1860 }
1861 }
1862
1863 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1864 LPARAM lParam)
1865 {
1866 #ifdef I18N
1867 LOGFONT logfont;
1868 HFONT font;
1869 #endif
1870 switch (msg) {
1871 case WM_INITDIALOG:
1872 #ifdef I18N
1873 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
1874 GetObject(font, sizeof(LOGFONT), &logfont);
1875 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgAboutFont, pvar)) {
1876 SendDlgItemMessage(dlg, IDC_TTSSH_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1877 SendDlgItemMessage(dlg, IDC_SSHVERSIONS, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1878 SendDlgItemMessage(dlg, IDC_INCLUDES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1879 SendDlgItemMessage(dlg, IDC_OPENSSL_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1880 SendDlgItemMessage(dlg, IDC_ZLIB_VERSION, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1881 SendDlgItemMessage(dlg, IDC_WEBSITES, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1882 SendDlgItemMessage(dlg, IDC_CRYPTOGRAPHY, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1883 SendDlgItemMessage(dlg, IDC_CREDIT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1884 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1885 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgAboutFont, MAKELPARAM(TRUE,0));
1886 }
1887 else {
1888 DlgAboutFont = NULL;
1889 }
1890 #endif
1891 init_about_dlg((PTInstVar) lParam, dlg);
1892 return TRUE;
1893 case WM_COMMAND:
1894 switch (LOWORD(wParam)) {
1895 case IDOK:
1896 EndDialog(dlg, 1);
1897 #ifdef I18N
1898 if (DlgAboutFont != NULL) {
1899 DeleteObject(DlgAboutFont);
1900 }
1901 #endif
1902 return TRUE;
1903 case IDCANCEL: /* there isn't a cancel button, but other Windows
1904 UI things can send this message */
1905 EndDialog(dlg, 0);
1906 #ifdef I18N
1907 if (DlgAboutFont != NULL) {
1908 DeleteObject(DlgAboutFont);
1909 }
1910 #endif
1911 return TRUE;
1912 }
1913 break;
1914 }
1915
1916 return FALSE;
1917 }
1918
1919 static char FAR *get_cipher_name(int cipher)
1920 {
1921 switch (cipher) {
1922 case SSH_CIPHER_NONE:
1923 #ifdef I18N
1924 strcpy(pvar->ts->UIMsg, "<ciphers below this line are disabled>");
1925 UTIL_get_lang_msg("DLG_SSHSETUP_CIPHER_BORDER", pvar);
1926 return pvar->ts->UIMsg;
1927 #else
1928 return "<ciphers below this line are disabled>";
1929 #endif
1930 case SSH_CIPHER_RC4:
1931 return "RC4";
1932 case SSH_CIPHER_3DES:
1933 return "3DES";
1934 case SSH_CIPHER_DES:
1935 return "DES";
1936 case SSH_CIPHER_IDEA:
1937 return "IDEA";
1938 case SSH_CIPHER_TSS:
1939 return "TSS";
1940 case SSH_CIPHER_BLOWFISH:
1941 return "Blowfish";
1942
1943 // for SSH2(yutaka)
1944 case SSH_CIPHER_AES128:
1945 return "AES128(SSH2)";
1946 case SSH_CIPHER_3DES_CBC:
1947 return "3DES-CBC(SSH2)";
1948
1949 default:
1950 return NULL;
1951 }
1952 }
1953
1954 static void set_move_button_status(HWND dlg)
1955 {
1956 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1957 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1958 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1959
1960 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1961 && curPos <= maxPos);
1962 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1963 && curPos < maxPos);
1964 }
1965
1966 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1967 {
1968 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1969 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1970 int i;
1971 int ch;
1972
1973 #ifdef I18N
1974 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1975 UTIL_get_lang_msg("DLG_SSHSETUP_TITLE", pvar);
1976 SetWindowText(dlg, pvar->ts->UIMsg);
1977
1978 GetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1979 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS", pvar);
1980 SetDlgItemText(dlg, IDC_COMPRESSLABEL, pvar->ts->UIMsg);
1981
1982 GetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1983 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_NONE", pvar);
1984 SetDlgItemText(dlg, IDC_COMPRESSNONE, pvar->ts->UIMsg);
1985
1986 GetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1987 UTIL_get_lang_msg("DLG_SSHSETUP_COMPRESS_HIGHEST", pvar);
1988 SetDlgItemText(dlg, IDC_COMPRESSHIGH, pvar->ts->UIMsg);
1989
1990 GetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1991 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER", pvar);
1992 SetDlgItemText(dlg, IDC_CIPHERORDER, pvar->ts->UIMsg);
1993
1994 GetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1995 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_UP", pvar);
1996 SetDlgItemText(dlg, IDC_SSHMOVECIPHERUP, pvar->ts->UIMsg);
1997
1998 GetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
1999 UTIL_get_lang_msg("DLG_SSHSETUP_CHIPER_DOWN", pvar);
2000 SetDlgItemText(dlg, IDC_SSHMOVECIPHERDOWN, pvar->ts->UIMsg);
2001
2002 GetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2003 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST", pvar);
2004 SetDlgItemText(dlg, IDC_KNOWNHOSTS, pvar->ts->UIMsg);
2005
2006 GetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2007 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RW", pvar);
2008 SetDlgItemText(dlg, IDC_CHOOSEREADWRITEFILE, pvar->ts->UIMsg);
2009
2010 GetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2011 UTIL_get_lang_msg("DLG_SSHSETUP_KNOWNHOST_RO", pvar);
2012 SetDlgItemText(dlg, IDC_CHOOSEREADONLYFILE, pvar->ts->UIMsg);
2013
2014 GetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2015 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT", pvar);
2016 SetDlgItemText(dlg, IDC_HEARTBEATLABEL, pvar->ts->UIMsg);
2017
2018 GetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2019 UTIL_get_lang_msg("DLG_SSHSETUP_HEARTBEAT_UNIT", pvar);
2020 SetDlgItemText(dlg, IDC_HEARTBEATLABEL2, pvar->ts->UIMsg);
2021
2022 GetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2023 UTIL_get_lang_msg("DLG_SSHSETUP_NOTICE", pvar);
2024 SetDlgItemText(dlg, IDC_NOTICEBANNER, pvar->ts->UIMsg);
2025
2026 strcpy(pvar->ts->UIMsg, "OK");
2027 UTIL_get_lang_msg("BTN_OK", pvar);
2028 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2029
2030 strcpy(pvar->ts->UIMsg, "Cancel");
2031 UTIL_get_lang_msg("BTN_CANCEL", pvar);
2032 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2033 #endif
2034
2035 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
2036 SendMessage(compressionControl, TBM_SETPOS, TRUE,
2037 pvar->settings.CompressionLevel);
2038
2039 normalize_cipher_order(pvar->settings.CipherOrder);
2040
2041 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
2042 int cipher = pvar->settings.CipherOrder[i] - '0';
2043 char FAR *name = get_cipher_name(cipher);
2044
2045 if (name != NULL) {
2046 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
2047 }
2048 }
2049
2050 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
2051 set_move_button_status(dlg);
2052
2053 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
2054 i++) {
2055 }
2056 if (ch != 0) {
2057 pvar->settings.KnownHostsFiles[i] = 0;
2058 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2059 pvar->settings.KnownHostsFiles);
2060 pvar->settings.KnownHostsFiles[i] = ch;
2061 SetDlgItemText(dlg, IDC_READONLYFILENAME,
2062 pvar->settings.KnownHostsFiles + i + 1);
2063 } else {
2064 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
2065 pvar->settings.KnownHostsFiles);
2066 }
2067
2068 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
2069 {
2070 char buf[10];
2071 _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
2072 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
2073 }
2074
2075 }
2076
2077 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
2078 char FAR * basename)
2079 {
2080 int filename_start = 0;
2081 int i;
2082 int ch;
2083
2084 if (basename[0] == '\\' || basename[0] == '/'
2085 || (basename[0] != 0 && basename[1] == ':')) {
2086 strncpy(buf, basename, bufsize);
2087 buf[bufsize - 1] = 0;
2088 return;
2089 }
2090
2091 GetModuleFileName(NULL, buf, bufsize);
2092 for (i = 0; (ch = buf[i]) != 0; i++) {
2093 if (ch == '\\' || ch == '/' || ch == ':') {
2094 filename_start = i + 1;
2095 }
2096 }
2097
2098 if (bufsize > filename_start) {
2099 strncpy(buf + filename_start, basename, bufsize - filename_start);
2100 }
2101 buf[bufsize - 1] = 0;
2102 }
2103
2104 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
2105 char FAR * basename)
2106 {
2107 char buf[1024];
2108 int filename_start = 0;
2109 int i;
2110 int ch, ch2;
2111
2112 if (basename[0] != '\\' && basename[0] != '/'
2113 && (basename[0] == 0 || basename[1] != ':')) {
2114 strncpy(dest, basename, destsize);
2115 dest[destsize - 1] = 0;
2116 return strlen(dest);
2117 }
2118
2119 GetModuleFileName(NULL, buf, sizeof(buf));
2120 for (i = 0; (ch = buf[i]) != 0; i++) {
2121 if (ch == '\\' || ch == '/' || ch == ':') {
2122 filename_start = i + 1;
2123 }
2124 }
2125
2126 for (i = 0; i < filename_start; i++) {
2127 ch = toupper(buf[i]);
2128 ch2 = toupper(basename[i]);
2129
2130 if (ch == ch2
2131 || ((ch == '\\' || ch == '/')
2132 && (ch2 == '\\' || ch2 == '/'))) {
2133 } else {
2134 break;
2135 }
2136 }
2137
2138 if (i == filename_start) {
2139 strncpy(dest, basename + i, destsize);
2140 } else {
2141 strncpy(dest, basename, destsize);
2142 }
2143 dest[destsize - 1] = 0;
2144 return strlen(dest);
2145 }
2146
2147 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
2148 {
2149 char buf[4096];
2150 char buf2[1024];
2151 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
2152 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
2153 int i, j, buf2index, bufindex;
2154 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
2155
2156 pvar->settings.CompressionLevel =
2157 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
2158
2159 buf2index = 0;
2160 for (i = 0; i < count; i++) {
2161 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
2162
2163 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2164 buf[0] = 0;
2165 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
2166 for (j = 0;
2167 j <= SSH_CIPHER_MAX
2168 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
2169 }
2170 if (j <= SSH_CIPHER_MAX) {
2171 buf2[buf2index] = '0' + j;
2172 buf2index++;
2173 }
2174 }
2175 }
2176 buf2[buf2index] = 0;
2177 normalize_cipher_order(buf2);
2178 strcpy(pvar->settings.CipherOrder, buf2);
2179
2180 buf[0] = 0;
2181 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
2182 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
2183 sizeof(pvar->settings.
2184 KnownHostsFiles), buf);
2185 buf[0] = 0;
2186 bufindex = 0;
2187 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
2188 for (i = 0; buf[i] != 0; i++) {
2189 if (buf[i] == ';') {
2190 buf[i] = 0;
2191 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2192 pvar->settings.KnownHostsFiles[j] = ';';
2193 j++;
2194 j += copy_teraterm_dir_relative_path(pvar->settings.
2195 KnownHostsFiles + j,
2196 sizeof(pvar->settings.
2197 KnownHostsFiles)
2198 - j, buf + bufindex);
2199 }
2200 bufindex = i + 1;
2201 }
2202 }
2203 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
2204 pvar->settings.KnownHostsFiles[j] = ';';
2205 j++;
2206 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
2207 sizeof(pvar->settings.
2208 KnownHostsFiles) - j,
2209 buf + bufindex);
2210 }
2211
2212 // get SSH HeartBeat(keep-alive)
2213 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
2214 i = atoi(buf);
2215 if (i < 0)
2216 i = 60;
2217 pvar->settings.ssh_heartbeat_overtime = i;
2218
2219 }
2220
2221 static void move_cur_sel_delta(HWND listbox, int delta)
2222 {
2223 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
2224 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
2225 int newPos = curPos + delta;
2226 char buf[1024];
2227
2228 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
2229 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
2230
2231 if (len > 0 && len < sizeof(buf)) { /* should always be true */
2232 buf[0] = 0;
2233 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
2234 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
2235 SendMessage(listbox, LB_INSERTSTRING, newPos,
2236 (LPARAM) (char FAR *) buf);
2237 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
2238 }
2239 }
2240 }
2241
2242 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
2243 int readonly)
2244 {
2245 #ifdef TERATERM32
2246 OPENFILENAME params;
2247 char fullname_buf[2048] = "ssh_known_hosts";
2248
2249 params.lStructSize = sizeof(OPENFILENAME);
2250 params.hwndOwner = parent;
2251 params.lpstrFilter = NULL;
2252 params.lpstrCustomFilter = NULL;
2253 params.nFilterIndex = 0;
2254 buf[0] = 0;
2255 params.lpstrFile = fullname_buf;
2256 params.nMaxFile = sizeof(fullname_buf);
2257 params.lpstrFileTitle = NULL;
2258 params.lpstrInitialDir = NULL;
2259 #ifdef I18N
2260 if (readonly) {
2261 strcpy(pvar->ts->UIMsg, "Choose a read-only known-hosts file to add");
2262 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RO_TITLE", pvar);
2263 }
2264 else {
2265 strcpy(pvar->ts->UIMsg, "Choose a read/write known-hosts file");
2266 UTIL_get_lang_msg("MSG_OPEN_KNOWNHOSTS_RW_TITLE", pvar);
2267 }
2268 params.lpstrTitle = pvar->ts->UIMsg;
2269 #else
2270 params.lpstrTitle =
2271 readonly ? "Choose a read-only known-hosts file to add" :
2272 "Choose a read/write known-hosts file";
2273 #endif
2274 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
2275 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
2276 params.lpstrDefExt = NULL;
2277
2278 if (GetOpenFileName(&params) != 0) {
2279 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
2280 return 1;
2281 } else {
2282 int err = CommDlgExtendedError();
2283
2284 if (err != 0) {
2285 char buf[1024];
2286 #ifdef I18N
2287 strcpy(pvar->ts->UIMsg, "Cannot show file dialog box: error %d");
2288 UTIL_get_lang_msg("MSG_OPEN_FILEDLG_KNOWNHOSTS_ERROR", pvar);
2289 _snprintf(buf, sizeof(buf), pvar->ts->UIMsg, err);
2290 #else
2291 _snprintf(buf, sizeof(buf),
2292 "Cannot show file dialog box: error %d", err);
2293 #endif
2294 buf[sizeof(buf) - 1] = 0;
2295 MessageBox(parent, buf, "TTSSH Error",
2296 MB_OK | MB_ICONEXCLAMATION);
2297 }
2298
2299 return 0;
2300 }
2301 #else
2302 return 0;
2303 #endif
2304 }
2305
2306 static void choose_read_write_file(HWND dlg)
2307 {
2308 char buf[1024];
2309
2310 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
2311 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
2312 }
2313 }
2314
2315 static void choose_read_only_file(HWND dlg)
2316 {
2317 char buf[1024];
2318 char buf2[4096];
2319
2320 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
2321 buf2[0] = 0;
2322 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
2323 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
2324 strncat(buf2, ";", sizeof(buf2));
2325 }
2326 strncat(buf2, buf, sizeof(buf2));
2327 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
2328 }
2329 }
2330
2331 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
2332 LPARAM lParam)
2333 {
2334 #ifdef I18N
2335 LOGFONT logfont;
2336 HFONT font;
2337 #endif
2338 switch (msg) {
2339 case WM_INITDIALOG:
2340 SetWindowLong(dlg, DWL_USER, lParam);
2341 init_setup_dlg((PTInstVar) lParam, dlg);
2342 #ifdef I18N
2343 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2344 GetObject(font, sizeof(LOGFONT), &logfont);
2345 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgSetupFont, pvar)) {
2346 SendDlgItemMessage(dlg, IDC_COMPRESSLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2347 SendDlgItemMessage(dlg, IDC_CIPHERORDER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2348 SendDlgItemMessage(dlg, IDC_SSHCIPHERPREFS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2349 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERUP, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2350 SendDlgItemMessage(dlg, IDC_SSHMOVECIPHERDOWN, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2351 SendDlgItemMessage(dlg, IDC_CHOOSEREADWRITEFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2352 SendDlgItemMessage(dlg, IDC_READWRITEFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2353 SendDlgItemMessage(dlg, IDC_CHOOSEREADONLYFILE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2354 SendDlgItemMessage(dlg, IDC_READONLYFILENAME, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2355 SendDlgItemMessage(dlg, IDC_COMPRESSNONE, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2356 SendDlgItemMessage(dlg, IDC_COMPRESSHIGH, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2357 SendDlgItemMessage(dlg, IDC_NOTICEBANNER, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2358 SendDlgItemMessage(dlg, IDC_KNOWNHOSTS, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2359 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2360 SendDlgItemMessage(dlg, IDC_HEARTBEAT_EDIT, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2361 SendDlgItemMessage(dlg, IDC_HEARTBEATLABEL2, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2362 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2363 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgSetupFont, MAKELPARAM(TRUE,0));
2364 }
2365 else {
2366 DlgSetupFont = NULL;
2367 }
2368 #endif
2369 return TRUE;
2370 case WM_COMMAND:
2371 switch (LOWORD(wParam)) {
2372 case IDOK:
2373 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
2374 dlg);
2375 EndDialog(dlg, 1);
2376 #ifdef I18N
2377 if (DlgSetupFont != NULL) {
2378 DeleteObject(DlgSetupFont);
2379 }
2380 #endif
2381 return TRUE;
2382 case IDCANCEL: /* there isn't a cancel button, but other Windows
2383 UI things can send this message */
2384 EndDialog(dlg, 0);
2385 #ifdef I18N
2386 if (DlgSetupFont != NULL) {
2387 DeleteObject(DlgSetupFont);
2388 }
2389 #endif
2390 return TRUE;
2391 case IDC_SSHMOVECIPHERUP:
2392 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
2393 set_move_button_status(dlg);
2394 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2395 return TRUE;
2396 case IDC_SSHMOVECIPHERDOWN:
2397 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
2398 set_move_button_status(dlg);
2399 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
2400 return TRUE;
2401 case IDC_SSHCIPHERPREFS:
2402 set_move_button_status(dlg);
2403 return TRUE;
2404 case IDC_CHOOSEREADWRITEFILE:
2405 choose_read_write_file(dlg);
2406 return TRUE;
2407 case IDC_CHOOSEREADONLYFILE:
2408 choose_read_only_file(dlg);
2409 return TRUE;
2410 }
2411 break;
2412 }
2413
2414 return FALSE;
2415 }
2416
2417
2418 //
2419 // SSH key generator dialog (2005.4.10 yutaka)
2420 //
2421
2422 typedef struct {
2423 RSA *rsa;
2424 DSA *dsa;
2425 } ssh_private_key_t;
2426
2427 static ssh_private_key_t private_key = {NULL, NULL};
2428
2429 typedef struct {
2430 RSA *rsa;
2431 DSA *dsa;
2432 } ssh_public_key_t;
2433
2434 static ssh_public_key_t public_key = {NULL, NULL};;
2435
2436 static void free_ssh_key(void)
2437 {
2438 // DSA_free(), RSA_free()��NULL���n�����������������B
2439 DSA_free(private_key.dsa);
2440 private_key.dsa = NULL;
2441 DSA_free(public_key.dsa);
2442 public_key.dsa = NULL;
2443
2444 RSA_free(private_key.rsa);
2445 private_key.rsa = NULL;
2446 RSA_free(public_key.rsa);
2447 public_key.rsa = NULL;
2448 }
2449
2450
2451 static BOOL generate_ssh_key(enum hostkey_type type)
2452 {
2453 int bits = 1024;
2454
2455 // if SSH key already is generated, should free the resource.
2456 free_ssh_key();
2457
2458 if (type == KEY_RSA1 || type == KEY_RSA) {
2459 RSA *priv = NULL;
2460 RSA *pub = NULL;
2461
2462 // private key
2463 priv = RSA_generate_key(bits, 35, NULL, NULL);
2464 if (priv == NULL)
2465 goto error;
2466 private_key.rsa = priv;
2467
2468 // public key
2469 pub = RSA_new();
2470 pub->n = BN_new();
2471 pub->e = BN_new();
2472 if (pub->n == NULL || pub->e == NULL) {
2473 RSA_free(pub);
2474 goto error;
2475 }
2476
2477 BN_copy(pub->n, priv->n);
2478 BN_copy(pub->e, priv->e);
2479 public_key.rsa = pub;
2480
2481 } else if (type == KEY_DSA) {
2482 DSA *priv = NULL;
2483 DSA *pub = NULL;
2484
2485 // private key
2486 priv = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
2487 if (priv == NULL)
2488 goto error;
2489 if (!DSA_generate_key(priv)) {
2490 // TODO: free 'priv'?
2491 goto error;
2492 }
2493 private_key.dsa = priv;
2494
2495 // public key
2496 pub = DSA_new();
2497 if (pub == NULL)
2498 goto error;
2499 pub->p = BN_new();
2500 pub->q = BN_new();
2501 pub->g = BN_new();
2502 pub->pub_key = BN_new();
2503 if (pub->p == NULL || pub->q == NULL || pub->g == NULL || pub->pub_key == NULL) {
2504 DSA_free(pub);
2505 goto error;
2506 }
2507
2508 BN_copy(pub->p, priv->p);
2509 BN_copy(pub->q, priv->q);
2510 BN_copy(pub->g, priv->g);
2511 BN_copy(pub->pub_key, priv->pub_key);
2512 public_key.dsa = pub;
2513
2514 } else {
2515 goto error;
2516 }
2517
2518 return TRUE;
2519
2520 error:
2521 free_ssh_key();
2522 return FALSE;
2523 }
2524
2525
2526 //
2527 // RC4
2528 //
2529
2530 /* Size of key to use */
2531 #define SEED_SIZE 20
2532
2533 /* Number of bytes to reseed after */
2534 #define REKEY_BYTES (1 << 24)
2535
2536 static int rc4_ready = 0;
2537 static RC4_KEY rc4;
2538
2539 static void seed_rng(void)
2540 {
2541 if (RAND_status() != 1)
2542 return;
2543 }
2544
2545 static void arc4random_stir(void)
2546 {
2547 unsigned char rand_buf[SEED_SIZE];
2548 int i;
2549
2550 memset(&rc4, 0, sizeof(rc4));
2551 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) {
2552 //fatal("Couldn't obtain random bytes (error %ld)",
2553 // ERR_get_error());
2554 }
2555 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
2556
2557 /*
2558 * Discard early keystream, as per recommendations in:
2559 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
2560 */
2561 for(i = 0; i <= 256; i += sizeof(rand_buf))
2562 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
2563
2564 memset(rand_buf, 0, sizeof(rand_buf));
2565
2566 rc4_ready = REKEY_BYTES;
2567 }
2568
2569 static unsigned int arc4random(void)
2570 {
2571 unsigned int r = 0;
2572 static int first_time = 1;
2573
2574 if (rc4_ready <= 0) {
2575 if (first_time) {
2576 seed_rng();
2577 }
2578 first_time = 0;
2579 arc4random_stir();
2580 }
2581
2582 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
2583
2584 rc4_ready -= sizeof(r);
2585
2586 return(r);
2587 }
2588
2589 //
2590 // SSH1 3DES
2591 //
2592 /*
2593 * This is used by SSH1:
2594 *
2595 * What kind of triple DES are these 2 routines?
2596 *
2597 * Why is there a redundant initialization vector?
2598 *
2599 * If only iv3 was used, then, this would till effect have been
2600 * outer-cbc. However, there is also a private iv1 == iv2 which
2601 * perhaps makes differential analysis easier. On the other hand, the
2602 * private iv1 probably makes the CRC-32 attack ineffective. This is a
2603 * result of that there is no longer any known iv1 to use when
2604 * choosing the X block.
2605 */
2606 struct ssh1_3des_ctx
2607 {
2608 EVP_CIPHER_CTX k1, k2, k3;
2609 };
2610
2611 static int ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, int enc)
2612 {
2613 struct ssh1_3des_ctx *c;
2614 u_char *k1, *k2, *k3;
2615
2616 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2617 c = malloc(sizeof(*c));
2618 EVP_CIPHER_CTX_set_app_data(ctx, c);
2619 }
2620 if (key == NULL)
2621 return (1);
2622 if (enc == -1)
2623 enc = ctx->encrypt;
2624 k1 = k2 = k3 = (u_char *) key;
2625 k2 += 8;
2626 if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
2627 if (enc)
2628 k3 += 16;
2629 else
2630 k1 += 16;
2631 }
2632 EVP_CIPHER_CTX_init(&c->k1);
2633 EVP_CIPHER_CTX_init(&c->k2);
2634 EVP_CIPHER_CTX_init(&c->k3);
2635 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
2636 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
2637 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
2638 memset(c, 0, sizeof(*c));
2639 free(c);
2640 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2641 return (0);
2642 }
2643 return (1);
2644 }
2645
2646 static int ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
2647 {
2648 struct ssh1_3des_ctx *c;
2649
2650 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
2651 //error("ssh1_3des_cbc: no context");
2652 return (0);
2653 }
2654 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
2655 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
2656 EVP_Cipher(&c->k3, dest, dest, len) == 0)
2657 return (0);
2658 return (1);
2659 }
2660
2661 static int ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
2662 {
2663 struct ssh1_3des_ctx *c;
2664
2665 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
2666 EVP_CIPHER_CTX_cleanup(&c->k1);
2667 EVP_CIPHER_CTX_cleanup(&c->k2);
2668 EVP_CIPHER_CTX_cleanup(&c->k3);
2669 memset(c, 0, sizeof(*c));
2670 free(c);
2671 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
2672 }
2673 return (1);
2674 }
2675
2676 void ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
2677 {
2678 struct ssh1_3des_ctx *c;
2679
2680 if (len != 24)
2681 //fatal("%s: bad 3des iv length: %d", __func__, len);
2682 ;
2683
2684 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
2685 //fatal("%s: no 3des context", __func__);
2686 ;
2687
2688 if (doset) {
2689 //debug3("%s: Installed 3DES IV", __func__);
2690 memcpy(c->k1.iv, iv, 8);
2691 memcpy(c->k2.iv, iv + 8, 8);
2692 memcpy(c->k3.iv, iv + 16, 8);
2693 } else {
2694 //debug3("%s: Copying 3DES IV", __func__);
2695 memcpy(iv, c->k1.iv, 8);
2696 memcpy(iv + 8, c->k2.iv, 8);
2697 memcpy(iv + 16, c->k3.iv, 8);
2698 }
2699 }
2700
2701 const EVP_CIPHER *evp_ssh1_3des(void)
2702 {
2703 static EVP_CIPHER ssh1_3des;
2704
2705 memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
2706 ssh1_3des.nid = NID_undef;
2707 ssh1_3des.block_size = 8;
2708 ssh1_3des.iv_len = 0;
2709 ssh1_3des.key_len = 16;
2710 ssh1_3des.init = ssh1_3des_init;
2711 ssh1_3des.cleanup = ssh1_3des_cleanup;
2712 ssh1_3des.do_cipher = ssh1_3des_cbc;
2713 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
2714 return (&ssh1_3des);
2715 }
2716
2717 static void ssh_make_comment(char *comment, int maxlen)
2718 {
2719 char user[UNLEN + 1], host[128];
2720 DWORD dwSize;
2721 WSADATA wsaData;
2722 int ret;
2723
2724 // get Windows logon user name
2725 dwSize = sizeof(user);
2726 if (GetUserName(user, &dwSize) == 0) {
2727 strcpy(user, "yutaka");
2728 }
2729
2730 // get local hostname (by WinSock)
2731 ret = WSAStartup(MAKEWORD(2,2), &wsaData);
2732 if (ret == 0) {
2733 if (gethostname(host, sizeof(host)) != 0) {
2734 ret = WSAGetLastError();
2735 }
2736 WSACleanup();
2737 }
2738 if (ret != 0) {
2739 strcpy(host, "sai");
2740 }
2741
2742 _snprintf(comment, maxlen, "%s@%s", user, host);
2743 }
2744
2745 // uuencode (rfc1521)
2746 int uuencode(unsigned char *src, int srclen, unsigned char *target, int targsize)
2747 {
2748 char base64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2749 char pad = '=';
2750 int datalength = 0;
2751 unsigned char input[3];
2752 unsigned char output[4];
2753 int i;
2754
2755 while (srclen > 2) {
2756 input[0] = *src++;
2757 input[1] = *src++;
2758 input[2] = *src++;
2759 srclen -= 3;
2760
2761 output[0] = input[0] >> 2;
2762 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2763 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2764 output[3] = input[2] & 0x3f;
2765 if (output[0] >= 64 ||
2766 output[1] >= 64 ||
2767 output[2] >= 64 ||
2768 output[3] >= 64)
2769 return -1;
2770
2771 if (datalength + 4 > targsize)
2772 return (-1);
2773 target[datalength++] = base64[output[0]];
2774 target[datalength++] = base64[output[1]];
2775 target[datalength++] = base64[output[2]];
2776 target[datalength++] = base64[output[3]];
2777 }
2778
2779 if (srclen != 0) {
2780 /* Get what's left. */
2781 input[0] = input[1] = input[2] = '\0';
2782 for (i = 0; i < srclen; i++)
2783 input[i] = *src++;
2784
2785 output[0] = input[0] >> 2;
2786 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
2787 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
2788 if (output[0] >= 64 ||
2789 output[1] >= 64 ||
2790 output[2] >= 64)
2791 return -1;
2792
2793 if (datalength + 4 > targsize)
2794 return (-1);
2795 target[datalength++] = base64[output[0]];
2796 target[datalength++] = base64[output[1]];
2797 if (srclen == 1)
2798 target[datalength++] = pad;
2799 else
2800 target[datalength++] = base64[output[2]];
2801 target[datalength++] = pad;
2802 }
2803 if (datalength >= targsize)
2804 return (-1);
2805 target[datalength] = '\0'; /* Returned value doesn't count \0. */
2806
2807 return (datalength); // success
2808 }
2809
2810 static BOOL CALLBACK TTXKeyGenerator(HWND dlg, UINT msg, WPARAM wParam,
2811 LPARAM lParam)
2812 {
2813 static enum hostkey_type key_type;
2814 #ifdef I18N
2815 char uimsg[MAX_UIMSG];
2816 LOGFONT logfont;
2817 HFONT font;
2818 #endif
2819
2820 switch (msg) {
2821 case WM_INITDIALOG:
2822 {
2823 #ifdef I18N
2824 GetWindowText(dlg, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2825 UTIL_get_lang_msg("DLG_KEYGEN_TITLE", pvar);
2826 SetWindowText(dlg, pvar->ts->UIMsg);
2827
2828 GetDlgItemText(dlg, IDC_KEYTYPE, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2829 UTIL_get_lang_msg("DLG_KEYGEN_KEYTYPE", pvar);
2830 SetDlgItemText(dlg, IDC_KEYTYPE, pvar->ts->UIMsg);
2831
2832 GetDlgItemText(dlg, IDC_KEY_LABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2833 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE", pvar);
2834 SetDlgItemText(dlg, IDC_KEY_LABEL, pvar->ts->UIMsg);
2835
2836 GetDlgItemText(dlg, IDC_CONFIRM_LABEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2837 UTIL_get_lang_msg("DLG_KEYGEN_PASSPHRASE2", pvar);
2838 SetDlgItemText(dlg, IDC_CONFIRM_LABEL, pvar->ts->UIMsg);
2839
2840 GetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2841 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPUBLIC", pvar);
2842 SetDlgItemText(dlg, IDC_SAVE_PUBLIC_KEY, pvar->ts->UIMsg);
2843
2844 GetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2845 UTIL_get_lang_msg("DLG_KEYGEN_SAVEPRIVATE", pvar);
2846 SetDlgItemText(dlg, IDC_SAVE_PRIVATE_KEY, pvar->ts->UIMsg);
2847
2848 GetDlgItemText(dlg, IDOK, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2849 UTIL_get_lang_msg("DLG_KEYGEN_GENERATE", pvar);
2850 SetDlgItemText(dlg, IDOK, pvar->ts->UIMsg);
2851
2852 GetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg, sizeof(pvar->ts->UIMsg));
2853 UTIL_get_lang_msg("BTN_CANCEL", pvar);
2854 SetDlgItemText(dlg, IDCANCEL, pvar->ts->UIMsg);
2855
2856 font = (HFONT)SendMessage(dlg, WM_GETFONT, 0, 0);
2857 GetObject(font, sizeof(LOGFONT), &logfont);
2858 if (UTIL_get_lang_font("DLG_TAHOMA_FONT", dlg, &logfont, &DlgKeygenFont, pvar)) {
2859 SendDlgItemMessage(dlg, IDC_KEYTYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2860 SendDlgItemMessage(dlg, IDC_RSA1_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2861 SendDlgItemMessage(dlg, IDC_RSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2862 SendDlgItemMessage(dlg, IDC_DSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2863 SendDlgItemMessage(dlg, IDC_KEY_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2864 SendDlgItemMessage(dlg, IDC_CONFIRM_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2865 SendDlgItemMessage(dlg, IDC_KEY_EDIT, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2866 SendDlgItemMessage(dlg, IDC_CONFIRM_EDIT, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2867 SendDlgItemMessage(dlg, IDC_SAVE_PUBLIC_KEY, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2868 SendDlgItemMessage(dlg, IDC_SAVE_PRIVATE_KEY, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2869 SendDlgItemMessage(dlg, IDOK, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2870 SendDlgItemMessage(dlg, IDCANCEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0));
2871 }
2872 else {
2873 DlgHostFont = NULL;
2874 }
2875 #endif
2876
2877 // default key type
2878 SendMessage(GetDlgItem(dlg, IDC_RSA_TYPE), BM_SETCHECK, BST_CHECKED, 0);
2879 key_type = KEY_RSA;
2880
2881 // passphrase edit box disabled(default)
2882 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2883 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2884
2885 // file saving dialog disabled(default)
2886 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2887 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2888
2889 }
2890 return TRUE;
2891
2892 case WM_COMMAND:
2893 switch (LOWORD(wParam)) {
2894 case IDOK: // key generate button pressed
2895 // passphrase edit box disabled(default)
2896 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE);
2897 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE);
2898
2899 // file saving dialog disabled(default)
2900 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), FALSE);
2901 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), FALSE);
2902
2903 if (generate_ssh_key(key_type)) {
2904 // passphrase edit box disabled(default)
2905 EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), TRUE);
2906 EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), TRUE);
2907
2908 // file saving dialog disabled(default)
2909 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PUBLIC_KEY), TRUE);
2910 EnableWindow(GetDlgItem(dlg, IDC_SAVE_PRIBATE_KEY), TRUE);
2911 }
2912 return TRUE;
2913
2914 case IDCANCEL:
2915 // don't forget to free SSH resource!
2916