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 2913 - (show annotations) (download) (as text)
Tue Oct 10 16:54:54 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 91141 byte(s)
ttermpro.exeの/Fパラメータで指定されたファイルからTTSSHの設定が読まれなくなっていたのを修正した。

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