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