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 2800 - (show annotations) (download) (as text)
Sat Mar 12 15:07:34 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 60847 byte(s)
SSH2 keyboard-interactive認証をTISダイアログに実装した。

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 <openssl/opensslv.h>
59
60 #define MATCH_STR(s, o) _strnicmp((s), (o), NUM_ELEM(o) - 1)
61
62 /* This extension implements SSH, so we choose a load order in the
63 "protocols" range. */
64 #define ORDER 2500
65
66 #ifdef TERATERM32
67 static HICON SecureIcon = NULL;
68 #endif
69
70 static TInstVar FAR *pvar;
71
72 #ifdef TERATERM32
73 /* WIN32 allows multiple instances of a DLL */
74 static TInstVar InstVar;
75 #define GET_VAR()
76 #else
77 /* WIN16 does not allow multiple instances of a DLL */
78
79 /* maximum number of Tera Term instances */
80 #define MAXNUMINST 32
81 /* list of task handles for Tera Term instances */
82 static HANDLE FAR TaskList[MAXNUMINST];
83 /* variable sets for instances */
84 static TInstVar FAR *FAR InstVar[MAXNUMINST];
85
86 /* Here's how the TS settings work.
87 Whenever the TS settings are read or written to the INI file, then
88 the shared memory containing those settings is updated.
89 When Teraterm starts, the shared memory is read to initialize the TS
90 settings. */
91
92 /* TS settings shared across instances */
93 static TS_SSH ts_SSH_settings;
94
95
96 extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
97
98
99 static BOOL NewVar()
100 {
101 int i = 0;
102 HANDLE Task = GetCurrentTask();
103
104 if (TaskList[0] == NULL)
105
106 if (Task == NULL)
107 return FALSE;
108 while ((i < MAXNUMINST) && (TaskList[i] != NULL))
109 i++;
110 if (i >= MAXNUMINST)
111 return FALSE;
112 pvar = (TInstVar FAR *) malloc(sizeof(TInstVar));
113 InstVar[i] = pvar;
114 TaskList[i] = Task;
115 return TRUE;
116 }
117
118 void DelVar()
119 {
120 int i = 0;
121 HANDLE Task = GetCurrentTask();
122
123 if (Task == NULL)
124 return;
125 while ((i < MAXNUMINST) && (TaskList[i] != Task))
126 i++;
127 if (i >= MAXNUMINST)
128 return;
129 free(TaskList[i]);
130 TaskList[i] = NULL;
131 }
132
133 BOOL GetVar()
134 {
135 int i = 0;
136 HANDLE Task = GetCurrentTask();
137
138 if (Task == NULL)
139 return FALSE;
140 while ((i < MAXNUMINST) && (TaskList[i] != Task))
141 i++;
142 if (i >= MAXNUMINST)
143 return FALSE;
144 pvar = InstVar[i];
145 return TRUE;
146 }
147
148 #define GET_VAR() if (!GetVar()) return
149 #endif
150
151 /*
152 This code makes lots of assumptions about the order in which Teraterm
153 does things, and how. A key assumption is that the Notification window
154 passed into WSAAsyncSelect is the main terminal window. We also assume
155 that the socket used in the first WSAconnect is the main session socket.
156 */
157
158 static void init_TTSSH(PTInstVar pvar)
159 {
160 pvar->socket = INVALID_SOCKET;
161 pvar->OldLargeIcon = NULL;
162 pvar->OldSmallIcon = NULL;
163 pvar->NotificationWindow = NULL;
164 pvar->hostdlg_activated = FALSE;
165 pvar->socket = INVALID_SOCKET;
166 pvar->NotificationWindow = NULL;
167 pvar->protocol_major = 0;
168 pvar->protocol_minor = 0;
169
170 PKT_init(pvar);
171 SSH_init(pvar);
172 CRYPT_init(pvar);
173 AUTH_init(pvar);
174 HOSTS_init(pvar);
175 FWD_init(pvar);
176 FWDUI_init(pvar);
177
178 ssh_heartbeat_lock_initialize();
179 }
180
181 static void uninit_TTSSH(PTInstVar pvar)
182 {
183 halt_ssh_heartbeat_thread(pvar);
184
185 SSH_end(pvar);
186 PKT_end(pvar);
187 AUTH_end(pvar);
188 CRYPT_end(pvar);
189 HOSTS_end(pvar);
190 FWD_end(pvar);
191 FWDUI_end(pvar);
192
193 if (pvar->OldLargeIcon != NULL) {
194 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
195 (LPARAM) pvar->OldLargeIcon);
196 pvar->OldLargeIcon = NULL;
197 }
198 if (pvar->OldSmallIcon != NULL) {
199 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
200 (LPARAM) pvar->OldSmallIcon);
201 pvar->OldSmallIcon = NULL;
202 }
203
204 ssh_heartbeat_lock_finalize();
205 }
206
207 static void PASCAL FAR TTXInit(PTTSet ts, PComVar cv)
208 {
209 #ifndef TERATERM32
210 if (!NewVar())
211 return; /* should be called first */
212 pvar->ts_SSH = &ts_SSH_settings;
213 #endif
214 pvar->settings = *pvar->ts_SSH;
215 pvar->ts = ts;
216 pvar->cv = cv;
217 pvar->fatal_error = FALSE;
218 pvar->showing_err = FALSE;
219 pvar->err_msg = NULL;
220
221 init_TTSSH(pvar);
222 }
223
224 static void normalize_cipher_order(char FAR * buf)
225 {
226 char ciphers_listed[SSH_CIPHER_MAX + 1];
227 char ciphers_allowed[SSH_CIPHER_MAX + 1];
228 int i, j;
229
230 /* SSH_CIPHER_NONE means that all ciphers below that one are disabled.
231 We *never* allow no encryption. */
232 #if 0
233 static char default_ciphers[] = {
234 SSH_CIPHER_3DES,
235 SSH_CIPHER_NONE,
236 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
237 };
238 #else
239 // for SSH2(yutaka)
240 static char default_ciphers[] = {
241 SSH_CIPHER_AES128,
242 SSH_CIPHER_3DES_CBC,
243 SSH_CIPHER_3DES,
244 SSH_CIPHER_NONE,
245 SSH_CIPHER_DES, SSH_CIPHER_BLOWFISH
246 };
247 #endif
248
249 memset(ciphers_listed, 0, sizeof(ciphers_listed));
250
251 memset(ciphers_allowed, 0, sizeof(ciphers_allowed));
252 for (i = 0; i < NUM_ELEM(default_ciphers); i++) {
253 ciphers_allowed[default_ciphers[i]] = 1;
254 }
255
256 for (i = 0; buf[i] != 0; i++) {
257 int cipher_num = buf[i] - '0';
258
259 if (cipher_num < 0 || cipher_num > SSH_CIPHER_MAX
260 || !ciphers_allowed[cipher_num]
261 || ciphers_listed[cipher_num]) {
262 memmove(buf + i, buf + i + 1, strlen(buf + i + 1) + 1);
263 i--;
264 } else {
265 ciphers_listed[cipher_num] = 1;
266 }
267 }
268
269 for (j = 0; j < NUM_ELEM(default_ciphers); j++) {
270 int cipher_num = default_ciphers[j];
271
272 if (!ciphers_listed[cipher_num]) {
273 buf[i] = cipher_num + '0';
274 i++;
275 }
276 }
277
278 buf[i] = 0;
279 }
280
281 /* Remove local settings from the shared memory block. */
282 static void clear_local_settings(PTInstVar pvar)
283 {
284 pvar->ts_SSH->TryDefaultAuth = FALSE;
285 }
286
287 static BOOL read_BOOL_option(PCHAR fileName, char FAR * keyName, BOOL def)
288 {
289 char buf[1024];
290
291 buf[0] = 0;
292 GetPrivateProfileString("TTSSH", keyName, "", buf, sizeof(buf),
293 fileName);
294 if (buf[0] == 0) {
295 return def;
296 } else {
297 return atoi(buf) != 0 ||
298 stricmp(buf, "yes") == 0 || stricmp(buf, "y") == 0;
299 }
300 }
301
302 static void read_string_option(PCHAR fileName, char FAR * keyName,
303 char FAR * def, char FAR * buf, int bufSize)
304 {
305
306 buf[0] = 0;
307 GetPrivateProfileString("TTSSH", keyName, def, buf, bufSize, fileName);
308 }
309
310 static void read_ssh_options(PTInstVar pvar, PCHAR fileName)
311 {
312 extern void SSH2_update_cipher_myproposal(PTInstVar pvar);
313 char buf[1024];
314 TS_SSH FAR *settings = pvar->ts_SSH;
315
316 #define READ_STD_STRING_OPTION(name) \
317 read_string_option(fileName, #name, "", settings->name, sizeof(settings->name))
318
319 settings->Enabled = read_BOOL_option(fileName, "Enabled", FALSE);
320
321 buf[0] = 0;
322 GetPrivateProfileString("TTSSH", "Compression", "", buf, sizeof(buf),
323 fileName);
324 settings->CompressionLevel = atoi(buf);
325 if (settings->CompressionLevel < 0 || settings->CompressionLevel > 9) {
326 settings->CompressionLevel = 0;
327 }
328
329 READ_STD_STRING_OPTION(DefaultUserName);
330 READ_STD_STRING_OPTION(DefaultForwarding);
331 READ_STD_STRING_OPTION(DefaultRhostsLocalUserName);
332 READ_STD_STRING_OPTION(DefaultRhostsHostPrivateKeyFile);
333 READ_STD_STRING_OPTION(DefaultRSAPrivateKeyFile);
334
335 READ_STD_STRING_OPTION(CipherOrder);
336 normalize_cipher_order(settings->CipherOrder);
337 SSH2_update_cipher_myproposal(pvar); // yutaka
338
339 read_string_option(fileName, "KnownHostsFiles", "ssh_known_hosts",
340 settings->KnownHostsFiles,
341 sizeof(settings->KnownHostsFiles));
342
343 buf[0] = 0;
344 GetPrivateProfileString("TTSSH", "DefaultAuthMethod", "", buf,
345 sizeof(buf), fileName);
346 settings->DefaultAuthMethod = atoi(buf);
347 if (settings->DefaultAuthMethod != SSH_AUTH_PASSWORD
348 && settings->DefaultAuthMethod != SSH_AUTH_RSA
349 && settings->DefaultAuthMethod != SSH_AUTH_TIS // add (2005.3.12 yutaka)
350 && settings->DefaultAuthMethod != SSH_AUTH_RHOSTS) {
351 /* this default can never be SSH_AUTH_RHOSTS_RSA because that is not a
352 selection in the dialog box; SSH_AUTH_RHOSTS_RSA is automatically chosen
353 when the dialog box has rhosts selected and an host private key file
354 is supplied. */
355 settings->DefaultAuthMethod = SSH_AUTH_PASSWORD;
356 }
357
358 buf[0] = 0;
359 GetPrivateProfileString("TTSSH", "LogLevel", "", buf, sizeof(buf),
360 fileName);
361 settings->LogLevel = atoi(buf);
362
363 buf[0] = 0;
364 GetPrivateProfileString("TTSSH", "WriteBufferSize", "", buf,
365 sizeof(buf), fileName);
366 settings->WriteBufferSize = atoi(buf);
367 if (settings->WriteBufferSize <= 0) {
368 settings->WriteBufferSize = 2 * 1024 * 1024;
369 }
370
371 settings->LocalForwardingIdentityCheck =
372 read_BOOL_option(fileName, "LocalForwardingIdentityCheck", TRUE);
373
374 // SSH protocol version (2004.10.11 yutaka)
375 // default is SSH2 (2004.11.30 yutaka)
376 settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
377
378 // SSH heartbeat time(second) (2004.12.11 yutaka)
379 settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
380
381 // SSH2 keyboard-interactive (2005.1.23 yutaka)
382 // �f�t�H���g���������������BOpenSSH 4.0����keyboard-interactive���\�b�h�����`�������������������A
383 // ���Y���\�b�h���g�����R�l�N�V���������������������B(2005.3.12 yutaka)
384 settings->ssh2_keyboard_interactive = GetPrivateProfileInt("TTSSH", "KeyboardInteractive", 0, fileName);
385
386 clear_local_settings(pvar);
387 }
388
389 static void write_ssh_options(PTInstVar pvar, PCHAR fileName,
390 TS_SSH FAR * settings)
391 {
392 char buf[1024];
393
394 WritePrivateProfileString("TTSSH", "Enabled",
395 settings->Enabled ? "1" : "0", fileName);
396
397 _itoa(settings->CompressionLevel, buf, 10);
398 WritePrivateProfileString("TTSSH", "Compression", buf, fileName);
399
400 WritePrivateProfileString("TTSSH", "DefaultUserName",
401 settings->DefaultUserName, fileName);
402
403 WritePrivateProfileString("TTSSH", "DefaultForwarding",
404 settings->DefaultForwarding, fileName);
405
406 WritePrivateProfileString("TTSSH", "CipherOrder",
407 settings->CipherOrder, fileName);
408
409 WritePrivateProfileString("TTSSH", "KnownHostsFiles",
410 settings->KnownHostsFiles, fileName);
411
412 WritePrivateProfileString("TTSSH", "DefaultRhostsLocalUserName",
413 settings->DefaultRhostsLocalUserName,
414 fileName);
415
416 WritePrivateProfileString("TTSSH", "DefaultRhostsHostPrivateKeyFile",
417 settings->DefaultRhostsHostPrivateKeyFile,
418 fileName);
419
420 WritePrivateProfileString("TTSSH", "DefaultRSAPrivateKeyFile",
421 settings->DefaultRSAPrivateKeyFile,
422 fileName);
423
424 _itoa(settings->DefaultAuthMethod, buf, 10);
425 WritePrivateProfileString("TTSSH", "DefaultAuthMethod", buf, fileName);
426
427 _itoa(settings->LogLevel, buf, 10);
428 WritePrivateProfileString("TTSSH", "LogLevel", buf, fileName);
429
430 _itoa(settings->WriteBufferSize, buf, 10);
431 WritePrivateProfileString("TTSSH", "WriteBufferSize", buf, fileName);
432
433 WritePrivateProfileString("TTSSH", "LocalForwardingIdentityCheck",
434 settings->
435 LocalForwardingIdentityCheck ? "1" : "0",
436 fileName);
437
438 // SSH protocol version (2004.10.11 yutaka)
439 WritePrivateProfileString("TTSSH", "ProtocolVersion",
440 settings->ssh_protocol_version==2 ? "2" : "1",
441 fileName);
442
443 // SSH heartbeat time(second) (2004.12.11 yutaka)
444 _snprintf(buf, sizeof(buf), "%d", settings->ssh_heartbeat_overtime);
445 WritePrivateProfileString("TTSSH", "HeartBeat", buf, fileName);
446
447 // SSH2 keyboard-interactive (2005.1.23 yutaka)
448 WritePrivateProfileString("TTSSH", "KeyboardInteractive",
449 settings->ssh2_keyboard_interactive ? "1" : "0",
450 fileName);
451
452 }
453
454
455 /* find free port in all protocol family */
456 static unsigned short find_local_port(PTInstVar pvar)
457 {
458 int tries;
459 #ifdef INET6
460 SOCKET connecter;
461 struct addrinfo hints;
462 struct addrinfo FAR *res;
463 struct addrinfo FAR *res0;
464 unsigned short port;
465 char pname[NI_MAXHOST];
466 #endif /* INET6 */
467
468 if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
469 return 0;
470 }
471
472 /* The random numbers here are only used to try to get fresh
473 ports across runs (dangling ports can cause bind errors
474 if we're unlucky). They do not need to be (and are not)
475 cryptographically strong.
476 */
477 srand((unsigned) GetTickCount());
478
479 #ifdef INET6
480 for (tries = 20; tries > 0; tries--) {
481 memset(&hints, 0, sizeof(hints));
482 hints.ai_family = pvar->ts->ProtocolFamily;
483 hints.ai_flags = AI_PASSIVE;
484 hints.ai_socktype = SOCK_STREAM;
485 port = (unsigned) rand() % 512 + 512;
486 _snprintf(pname, sizeof(pname), "%d", (int) port);
487 if (getaddrinfo(NULL, pname, &hints, &res0)) {
488 return 0;
489 /* NOT REACHED */
490 }
491
492 for (res = res0; res; res = res->ai_next) {
493 if (res->ai_family == AF_INET || res->ai_family == AF_INET6)
494 continue;
495
496 connecter =
497 socket(res->ai_family, res->ai_socktype, res->ai_protocol);
498 if (connecter == INVALID_SOCKET) {
499 freeaddrinfo(res0);
500 return 0;
501 }
502
503 if (bind(connecter, res->ai_addr, res->ai_addrlen) !=
504 SOCKET_ERROR) {
505 return port;
506 freeaddrinfo(res0);
507 closesocket(connecter);
508 } else if (WSAGetLastError() != WSAEADDRINUSE) {
509 closesocket(connecter);
510 freeaddrinfo(res0);
511 return 0;
512 }
513
514 closesocket(connecter);
515 }
516 freeaddrinfo(res0);
517 }
518
519 return 0;
520 #else
521 for (tries = 20; tries > 0; tries--) {
522 SOCKET connecter = socket(AF_INET, SOCK_STREAM, 0);
523 struct sockaddr_in connecter_addr;
524
525 connecter_addr.sin_family = AF_INET;
526 connecter_addr.sin_port = (unsigned) rand() % 512 + 512;
527 connecter_addr.sin_addr.s_addr = htonl(INADDR_ANY);
528
529 if (connecter == INVALID_SOCKET) {
530 return 0;
531 }
532
533 if (bind
534 (connecter, (struct sockaddr FAR *) &connecter_addr,
535 sizeof(connecter_addr)) != SOCKET_ERROR) {
536 closesocket(connecter);
537 return connecter_addr.sin_port;
538 } else if (WSAGetLastError() != WSAEADDRINUSE) {
539 closesocket(connecter);
540 return 0;
541 }
542
543 closesocket(connecter);
544 }
545
546 return 0;
547 #endif /* INET6 */
548 }
549
550 static int PASCAL FAR TTXconnect(SOCKET s,
551 const struct sockaddr FAR * name,
552 int namelen)
553 {
554 GET_VAR();
555
556 #ifdef INET6
557 if (pvar->socket == INVALID_SOCKET) {
558 struct sockaddr_storage ss;
559 int len;
560
561 pvar->socket = s;
562
563 memset(&ss, 0, sizeof(ss));
564 switch (pvar->ts->ProtocolFamily) {
565 case AF_INET:
566 len = sizeof(struct sockaddr_in);
567 ((struct sockaddr_in FAR *) &ss)->sin_family = AF_INET;
568 ((struct sockaddr_in FAR *) &ss)->sin_addr.s_addr = INADDR_ANY;
569 ((struct sockaddr_in FAR *) &ss)->sin_port =
570 htons(find_local_port(pvar));
571 break;
572 case AF_INET6:
573 len = sizeof(struct sockaddr_in6);
574 ((struct sockaddr_in6 FAR *) &ss)->sin6_family = AF_INET6;
575 #if 0 /* symbol "in6addr_any" is not included in wsock32.lib */
576 /* if wsock32.lib will be linked, we can't refer "in6addr_any" */
577 ((struct sockaddr_in6 FAR *) &ss)->sin6_addr = in6addr_any;
578 #eles
579 memset(&((struct sockaddr_in6 FAR *) &ss)->sin6_addr, 0,
580 sizeof(struct in_addr6));
581 #endif /* 0 */
582 ((struct sockaddr_in6 FAR *) &ss)->sin6_port =
583 htons(find_local_port(pvar));
584 break;
585 default:
586 /* NOT REACHED */
587 break;
588 }
589
590 bind(s, (struct sockaddr FAR *) &ss, len);
591 }
592 #else
593 if (pvar->socket == INVALID_SOCKET) {
594 struct sockaddr_in addr;
595
596 pvar->socket = s;
597
598 addr.sin_family = AF_INET;
599 addr.sin_port = htons(find_local_port(pvar));
600 addr.sin_addr.s_addr = INADDR_ANY;
601 memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
602
603 bind(s, (struct sockaddr FAR *) &addr, sizeof(addr));
604 }
605 #endif /* INET6 */
606
607 return (pvar->Pconnect) (s, name, namelen);
608 }
609
610 static int PASCAL FAR TTXWSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
611 long lEvent)
612 {
613 GET_VAR();
614
615 if (s == pvar->socket) {
616 pvar->notification_events = lEvent;
617 pvar->notification_msg = wMsg;
618
619 if (pvar->NotificationWindow == NULL) {
620 pvar->NotificationWindow = hWnd;
621 AUTH_advance_to_next_cred(pvar);
622 }
623 }
624
625 return (pvar->PWSAAsyncSelect) (s, hWnd, wMsg, lEvent);
626 }
627
628 static int PASCAL FAR TTXrecv(SOCKET s, char FAR * buf, int len, int flags)
629 {
630 GET_VAR();
631
632 if (s == pvar->socket) {
633 int ret;
634
635 ssh_heartbeat_lock();
636 ret = PKT_recv(pvar, buf, len);
637 ssh_heartbeat_unlock();
638 return (ret);
639
640 } else {
641 return (pvar->Precv) (s, buf, len, flags);
642 }
643 }
644
645 static int PASCAL FAR TTXsend(SOCKET s, char const FAR * buf, int len,
646 int flags)
647 {
648 GET_VAR();
649
650 if (s == pvar->socket) {
651 ssh_heartbeat_lock();
652 SSH_send(pvar, buf, len);
653 ssh_heartbeat_unlock();
654 return len;
655 } else {
656 return (pvar->Psend) (s, buf, len, flags);
657 }
658 }
659
660 void notify_established_secure_connection(PTInstVar pvar)
661 {
662 #ifdef TERATERM32
663 if (SecureIcon == NULL) {
664 SecureIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SECURETT));
665 }
666
667 if (SecureIcon != NULL) {
668 pvar->OldSmallIcon =
669 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
670 ICON_SMALL, 0);
671 pvar->OldLargeIcon =
672 (HICON) SendMessage(pvar->NotificationWindow, WM_GETICON,
673 ICON_BIG, 0);
674 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_BIG,
675 (LPARAM) SecureIcon);
676 PostMessage(pvar->NotificationWindow, WM_SETICON, ICON_SMALL,
677 (LPARAM) SecureIcon);
678 }
679 #endif
680
681 notify_verbose_message(pvar, "Entering secure mode",
682 LOG_LEVEL_VERBOSE);
683 }
684
685 void notify_closed_connection(PTInstVar pvar)
686 {
687 SSH_notify_disconnecting(pvar, NULL);
688 AUTH_notify_disconnecting(pvar);
689 HOSTS_notify_disconnecting(pvar);
690
691 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
692 pvar->socket, MAKELPARAM(FD_CLOSE, 0));
693
694 }
695
696 static void add_err_msg(PTInstVar pvar, char FAR * msg)
697 {
698 if (pvar->err_msg != NULL) {
699 char FAR *buf =
700 (char FAR *) malloc(strlen(pvar->err_msg) + 3 + strlen(msg));
701
702 strcpy(buf, pvar->err_msg);
703 strcat(buf, "\n\n");
704 strcat(buf, msg);
705 free(pvar->err_msg);
706 pvar->err_msg = buf;
707 } else {
708 pvar->err_msg = _strdup(msg);
709 }
710 }
711
712 void notify_nonfatal_error(PTInstVar pvar, char FAR * msg)
713 {
714 if (!pvar->showing_err) {
715 PostMessage(pvar->NotificationWindow, WM_COMMAND,
716 ID_SSHASYNCMESSAGEBOX, 0);
717 }
718 if (msg[0] != 0) {
719 notify_verbose_message(pvar, msg, LOG_LEVEL_ERROR);
720 add_err_msg(pvar, msg);
721 }
722 }
723
724 void notify_fatal_error(PTInstVar pvar, char FAR * msg)
725 {
726 if (msg[0] != 0) {
727 notify_verbose_message(pvar, msg, LOG_LEVEL_FATAL);
728 add_err_msg(pvar, msg);
729 }
730
731 if (!pvar->fatal_error) {
732 pvar->fatal_error = TRUE;
733
734 SSH_notify_disconnecting(pvar, msg);
735 AUTH_notify_disconnecting(pvar);
736 HOSTS_notify_disconnecting(pvar);
737
738 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
739 pvar->socket, MAKELPARAM(FD_CLOSE,
740 (pvar->PWSAGetLastError) ()));
741 }
742 }
743
744 void notify_verbose_message(PTInstVar pvar, char FAR * msg, int level)
745 {
746 if (level <= pvar->session_settings.LogLevel) {
747 char buf[1024];
748 int file;
749
750 get_teraterm_dir_relative_name(buf, NUM_ELEM(buf), "TTSSH.LOG");
751 file = _open(buf, _O_RDWR | _O_APPEND | _O_CREAT | _O_TEXT,
752 _S_IREAD | _S_IWRITE);
753
754 if (file >= 0) {
755 _write(file, msg, strlen(msg));
756 _write(file, "\n", 1);
757 _close(file);
758 }
759 }
760 }
761
762 static void PASCAL FAR TTXOpenTCP(TTXSockHooks FAR * hooks)
763 {
764 GET_VAR();
765
766 if (pvar->settings.Enabled) {
767 char buf[1024] = "\nInitiating SSH session at ";
768 struct tm FAR *newtime;
769 time_t long_time;
770
771 pvar->session_settings = pvar->settings;
772
773 time(&long_time);
774 newtime = localtime(&long_time);
775 strcat(buf, asctime(newtime));
776 buf[strlen(buf) - 1] = 0;
777 notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
778
779 FWDUI_load_settings(pvar);
780
781 pvar->cv->TelAutoDetect = FALSE;
782 /* This next line should not be needed because Teraterm's
783 CommLib should find ts->Telnet == 0 ... but we'll do this
784 just to be on the safe side. */
785 pvar->cv->TelFlag = FALSE;
786
787 pvar->Precv = *hooks->Precv;
788 pvar->Psend = *hooks->Psend;
789 pvar->PWSAAsyncSelect = *hooks->PWSAAsyncSelect;
790 pvar->Pconnect = *hooks->Pconnect;
791 pvar->PWSAGetLastError = *hooks->PWSAGetLastError;
792
793 *hooks->Precv = TTXrecv;
794 *hooks->Psend = TTXsend;
795 *hooks->PWSAAsyncSelect = TTXWSAAsyncSelect;
796 *hooks->Pconnect = TTXconnect;
797
798 SSH_open(pvar);
799 HOSTS_open(pvar);
800 FWDUI_open(pvar);
801 }
802 }
803
804 static void PASCAL FAR TTXCloseTCP(TTXSockHooks FAR * hooks)
805 {
806 GET_VAR();
807
808 if (pvar->session_settings.Enabled) {
809 pvar->socket = INVALID_SOCKET;
810
811 notify_verbose_message(pvar, "Terminating SSH session...",
812 LOG_LEVEL_VERBOSE);
813
814 *hooks->Precv = pvar->Precv;
815 *hooks->Psend = pvar->Psend;
816 *hooks->PWSAAsyncSelect = pvar->PWSAAsyncSelect;
817 *hooks->Pconnect = pvar->Pconnect;
818 }
819
820 uninit_TTSSH(pvar);
821 init_TTSSH(pvar);
822 }
823
824 static void enable_dlg_items(HWND dlg, int from, int to, BOOL enabled)
825 {
826 for (; from <= to; from++) {
827 EnableWindow(GetDlgItem(dlg, from), enabled);
828 }
829 }
830
831 static BOOL CALLBACK TTXHostDlg(HWND dlg, UINT msg, WPARAM wParam,
832 LPARAM lParam)
833 {
834 static char *ssh_version[] = {"SSH1", "SSH2", NULL};
835 PGetHNRec GetHNRec;
836 char EntName[7];
837 char TempHost[HostNameMaxLength + 1];
838 WORD i, j, w;
839 BOOL Ok;
840
841 GET_VAR();
842
843 switch (msg) {
844 case WM_INITDIALOG:
845 GetHNRec = (PGetHNRec) lParam;
846 SetWindowLong(dlg, DWL_USER, lParam);
847
848 if (GetHNRec->PortType == IdFile)
849 GetHNRec->PortType = IdTCPIP;
850 CheckRadioButton(dlg, IDC_HOSTTCPIP, IDC_HOSTSERIAL,
851 IDC_HOSTTCPIP + GetHNRec->PortType - 1);
852
853 strcpy(EntName, "Host");
854
855 i = 1;
856 do {
857 sprintf(&EntName[4], "%d", i);
858 GetPrivateProfileString("Hosts", EntName, "",
859 TempHost, sizeof(TempHost),
860 GetHNRec->SetupFN);
861 if (strlen(TempHost) > 0)
862 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_ADDSTRING,
863 0, (LPARAM) TempHost);
864 i++;
865 } while ((i <= 99) && (strlen(TempHost) > 0));
866
867 SendDlgItemMessage(dlg, IDC_HOSTNAME, EM_LIMITTEXT,
868 HostNameMaxLength - 1, 0);
869
870 SendDlgItemMessage(dlg, IDC_HOSTNAME, CB_SETCURSEL, 0, 0);
871
872 CheckRadioButton(dlg, IDC_HOSTTELNET, IDC_HOSTOTHER,
873 pvar->settings.Enabled ? IDC_HOSTSSH : GetHNRec->
874 Telnet ? IDC_HOSTTELNET : IDC_HOSTOTHER);
875 SendDlgItemMessage(dlg, IDC_HOSTTCPPORT, EM_LIMITTEXT, 5, 0);
876 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TCPPort, FALSE);
877 #ifdef INET6
878 for (i = 0; ProtocolFamilyList[i]; ++i) {
879 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_ADDSTRING,
880 0, (LPARAM) ProtocolFamilyList[i]);
881 }
882 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, EM_LIMITTEXT,
883 ProtocolFamilyMaxLength - 1, 0);
884 SendDlgItemMessage(dlg, IDC_HOSTTCPPROTOCOL, CB_SETCURSEL, 0, 0);
885 #endif /* INET6 */
886
887 /////// SSH version
888 for (i = 0; ssh_version[i]; ++i) {
889 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_ADDSTRING,
890 0, (LPARAM) ssh_version[i]);
891 }
892 SendDlgItemMessage(dlg, IDC_SSH_VERSION, EM_LIMITTEXT,
893 NUM_ELEM(ssh_version) - 1, 0);
894
895 if (pvar->settings.ssh_protocol_version == 1) {
896 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
897 } else {
898 SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 1, 0); // SSH2
899 }
900
901 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
902 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE); // enabled
903 } else {
904 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
905 }
906 /////// SSH version
907
908
909 j = 0;
910 w = 1;
911 strcpy(EntName, "COM");
912 for (i = 1; i <= GetHNRec->MaxComPort; i++) {
913 sprintf(&EntName[3], "%d", i);
914 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_ADDSTRING,
915 0, (LPARAM) EntName);
916 j++;
917 if (GetHNRec->ComPort == i)
918 w = j;
919 }
920 if (j > 0)
921 SendDlgItemMessage(dlg, IDC_HOSTCOM, CB_SETCURSEL, w - 1, 0);
922 else /* All com ports are already used */
923 GetHNRec->PortType = IdTCPIP;
924
925 if (GetHNRec->PortType == IdTCPIP)
926 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
927 #ifdef INET6
928 else {
929 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
930 FALSE);
931 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
932 IDC_HOSTTCPPROTOCOL, FALSE);
933 }
934 #else
935 else
936 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
937 FALSE);
938 #endif /* INET6 */
939
940 // Host dialog���t�H�[�J�X�������� (2004.10.2 yutaka)
941 {
942 HWND hwnd = GetDlgItem(dlg, IDC_HOSTNAME);
943
944 SetFocus(hwnd);
945 //SendMessage(hwnd, BM_SETCHECK, BST_CHECKED, 0);
946 //style = GetClassLongPtr(hwnd, GCL_STYLE);
947 //SetClassLongPtr(hwnd, GCL_STYLE, style | WS_TABSTOP);
948 }
949
950 // SetFocus()���t�H�[�J�X���������������AFALSE�������K�v�������B
951 // TRUE���������ATABSTOP�������������������R���g���[�����I�������B
952 // (2004.11.23 yutaka)
953 return FALSE;
954 //return TRUE;
955
956 case WM_COMMAND:
957 switch (LOWORD(wParam)) {
958 case IDOK:
959 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
960 if (GetHNRec != NULL) {
961 if (IsDlgButtonChecked(dlg, IDC_HOSTTCPIP)) {
962 #ifdef INET6
963 char afstr[BUFSIZ];
964 #endif /* INET6 */
965 i = GetDlgItemInt(dlg, IDC_HOSTTCPPORT, &Ok, FALSE);
966 if (Ok) {
967 GetHNRec->TCPPort = i;
968 } else {
969 MessageBox(dlg, "Teraterm",
970 "The TCP port must be a number.",
971 MB_OK | MB_ICONEXCLAMATION);
972 return TRUE;
973 }
974 #ifdef INET6
975 #define getaf(str) \
976 ((strcmp((str), "IPv6") == 0) ? AF_INET6 : \
977 ((strcmp((str), "IPv4") == 0) ? AF_INET : AF_UNSPEC))
978 memset(afstr, 0, sizeof(afstr));
979 GetDlgItemText(dlg, IDC_HOSTTCPPROTOCOL, afstr,
980 sizeof(afstr));
981 GetHNRec->ProtocolFamily = getaf(afstr);
982 #endif /* INET6 */
983 GetHNRec->PortType = IdTCPIP;
984 GetDlgItemText(dlg, IDC_HOSTNAME, GetHNRec->HostName,
985 HostNameMaxLength);
986 GetHNRec->Telnet = FALSE;
987 pvar->hostdlg_activated = TRUE;
988 pvar->hostdlg_Enabled = FALSE;
989 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
990 GetHNRec->Telnet = TRUE;
991 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
992 pvar->hostdlg_Enabled = TRUE;
993
994 // check SSH protocol version
995 memset(afstr, 0, sizeof(afstr));
996 GetDlgItemText(dlg, IDC_SSH_VERSION, afstr, sizeof(afstr));
997 if (stricmp(afstr, "SSH1") == 0) {
998 pvar->settings.ssh_protocol_version = 1;
999 } else {
1000 pvar->settings.ssh_protocol_version = 2;
1001 }
1002 }
1003 } else {
1004 GetHNRec->PortType = IdSerial;
1005 GetHNRec->HostName[0] = 0;
1006 memset(EntName, 0, sizeof(EntName));
1007 GetDlgItemText(dlg, IDC_HOSTCOM, EntName,
1008 sizeof(EntName) - 1);
1009 GetHNRec->ComPort = (BYTE) (EntName[3]) - 0x30;
1010 if (strlen(EntName) > 4)
1011 GetHNRec->ComPort =
1012 GetHNRec->ComPort * 10 + (BYTE) (EntName[4]) -
1013 0x30;
1014 }
1015 }
1016 EndDialog(dlg, 1);
1017 return TRUE;
1018
1019 case IDCANCEL:
1020 EndDialog(dlg, 0);
1021 return TRUE;
1022
1023 case IDC_HOSTTCPIP:
1024 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1025 TRUE);
1026 #ifdef INET6
1027 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1028 IDC_HOSTTCPPROTOCOL, TRUE);
1029 #endif /* INET6 */
1030 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, FALSE);
1031
1032 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1033 if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1034 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, TRUE);
1035 } else {
1036 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1037 }
1038
1039 return TRUE;
1040
1041 case IDC_HOSTSERIAL:
1042 enable_dlg_items(dlg, IDC_HOSTCOMLABEL, IDC_HOSTCOM, TRUE);
1043 enable_dlg_items(dlg, IDC_HOSTNAMELABEL, IDC_HOSTTCPPORT,
1044 FALSE);
1045 #ifdef INET6
1046 enable_dlg_items(dlg, IDC_HOSTTCPPROTOCOLLABEL,
1047 IDC_HOSTTCPPROTOCOL, FALSE);
1048 #endif /* INET6 */
1049 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1050 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1051
1052 return TRUE;
1053
1054 case IDC_HOSTSSH:
1055 enable_dlg_items(dlg, IDC_SSH_VERSION,
1056 IDC_SSH_VERSION, TRUE);
1057 goto hostssh_enabled;
1058
1059 case IDC_HOSTTELNET:
1060 case IDC_HOSTOTHER:
1061 enable_dlg_items(dlg, IDC_SSH_VERSION, IDC_SSH_VERSION, FALSE); // disabled
1062 hostssh_enabled:
1063
1064 GetHNRec = (PGetHNRec) GetWindowLong(dlg, DWL_USER);
1065
1066 if (IsDlgButtonChecked(dlg, IDC_HOSTTELNET)) {
1067 if (GetHNRec != NULL)
1068 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, GetHNRec->TelPort,
1069 FALSE);
1070 } else if (IsDlgButtonChecked(dlg, IDC_HOSTSSH)) {
1071 SetDlgItemInt(dlg, IDC_HOSTTCPPORT, 22, FALSE);
1072 }
1073 return TRUE;
1074
1075 case IDC_HOSTHELP:
1076 PostMessage(GetParent(dlg), WM_USER_DLGHELP2, 0, 0);
1077 }
1078 }
1079 return FALSE;
1080 }
1081
1082 static BOOL FAR PASCAL TTXGetHostName(HWND parent, PGetHNRec rec)
1083 {
1084 return (BOOL) DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_HOSTDLG),
1085 parent, TTXHostDlg, (LONG) rec);
1086 }
1087
1088 static void PASCAL FAR TTXGetUIHooks(TTXUIHooks FAR * hooks)
1089 {
1090 GET_VAR();
1091
1092 *hooks->GetHostName = TTXGetHostName;
1093 }
1094
1095 static void FAR PASCAL TTXReadINIFile(PCHAR fileName, PTTSet ts)
1096 {
1097 GET_VAR();
1098
1099 (pvar->ReadIniFile) (fileName, ts);
1100 read_ssh_options(pvar, fileName);
1101 pvar->settings = *pvar->ts_SSH;
1102 notify_verbose_message(pvar, "Reading INI file", LOG_LEVEL_VERBOSE);
1103 FWDUI_load_settings(pvar);
1104 }
1105
1106 static void FAR PASCAL TTXWriteINIFile(PCHAR fileName, PTTSet ts)
1107 {
1108 GET_VAR();
1109
1110 (pvar->WriteIniFile) (fileName, ts);
1111 *pvar->ts_SSH = pvar->settings;
1112 clear_local_settings(pvar);
1113 notify_verbose_message(pvar, "Writing INI file", LOG_LEVEL_VERBOSE);
1114 write_ssh_options(pvar, fileName, pvar->ts_SSH);
1115 }
1116
1117 static void read_ssh_options_from_user_file(PTInstVar pvar,
1118 char FAR * user_file_name)
1119 {
1120 if (user_file_name[0] == '.') {
1121 read_ssh_options(pvar, user_file_name);
1122 } else {
1123 char buf[1024];
1124
1125 get_teraterm_dir_relative_name(buf, sizeof(buf), user_file_name);
1126 read_ssh_options(pvar, buf);
1127 }
1128
1129 pvar->settings = *pvar->ts_SSH;
1130 FWDUI_load_settings(pvar);
1131 }
1132
1133
1134 // @���u�����N���u�������B (2005.1.26 yutaka)
1135 static void replace_to_blank(char *src, char *dst, int dst_len)
1136 {
1137 int len, i;
1138
1139 len = strlen(src);
1140 if (dst_len < len) // buffer overflow check
1141 return;
1142
1143 for (i = 0 ; i < len ; i++) {
1144 if (src[i] == '@') { // @ ���o��������
1145 if (i < len - 1 && src[i + 1] == '@') { // �������� @ �����A�b�g�}�[�N���F������
1146 *dst++ = '@';
1147 i++;
1148 } else {
1149 *dst++ = ' '; // �������u��������
1150 }
1151 } else {
1152 *dst++ = src[i];
1153 }
1154 }
1155 *dst = '\0';
1156 }
1157
1158 /* returns 1 if the option text must be deleted */
1159 static int parse_option(PTInstVar pvar, char FAR * option)
1160 {
1161 if ((option[0] == '-' || option[0] == '/')) {
1162 if (MATCH_STR(option + 1, "ssh") == 0) {
1163 if (option[4] == 0) {
1164 pvar->settings.Enabled = 1;
1165 } else if (MATCH_STR(option + 4, "-L") == 0
1166 || MATCH_STR(option + 4, "-R") == 0
1167 || stricmp(option + 4, "-X") == 0) {
1168 if (pvar->settings.DefaultForwarding[0] == 0) {
1169 strcpy(pvar->settings.DefaultForwarding, option + 5);
1170 } else {
1171 strcat(pvar->settings.DefaultForwarding, ";");
1172 strcat(pvar->settings.DefaultForwarding, option + 5);
1173 }
1174 } else if (MATCH_STR(option + 4, "-f=") == 0) {
1175 read_ssh_options_from_user_file(pvar, option + 7);
1176 } else if (MATCH_STR(option + 4, "-v") == 0) {
1177 pvar->settings.LogLevel = LOG_LEVEL_VERBOSE;
1178 } else if (stricmp(option + 4, "-autologin") == 0
1179 || stricmp(option + 4, "-autologon") == 0) {
1180 pvar->settings.TryDefaultAuth = TRUE;
1181
1182 } else if (MATCH_STR(option + 4, "-consume=") == 0) {
1183 read_ssh_options_from_user_file(pvar, option + 13);
1184 DeleteFile(option + 13);
1185 } else {
1186 char buf[1024];
1187
1188 _snprintf(buf, sizeof(buf),
1189 "Unrecognized command-line option: %s", option);
1190 buf[sizeof(buf) - 1] = 0;
1191
1192 MessageBox(NULL, buf, "TTSSH", MB_OK | MB_ICONEXCLAMATION);
1193 }
1194
1195 return 1;
1196 } else if (MATCH_STR(option + 1, "t=") == 0) {
1197 if (strcmp(option + 3, "2") == 0) {
1198 pvar->settings.Enabled = 1;
1199 return 1;
1200 } else {
1201 pvar->settings.Enabled = 0;
1202 }
1203 } else if (MATCH_STR(option + 1, "f=") == 0) {
1204 read_ssh_options_from_user_file(pvar, option + 3);
1205
1206 // /1 ������ /2 �I�v�V�������V�K���� (2004.10.3 yutaka)
1207 } else if (MATCH_STR(option + 1, "1") == 0) {
1208 // command line: /ssh /1 is SSH1 only
1209 pvar->settings.ssh_protocol_version = 1;
1210
1211 } else if (MATCH_STR(option + 1, "2") == 0) {
1212 // command line: /ssh /2 is SSH2 & SSH1
1213 pvar->settings.ssh_protocol_version = 2;
1214
1215 } else if (MATCH_STR(option + 1, "nossh") == 0) {
1216 // '/nossh' �I�v�V�����������B
1217 // TERATERM.INI ��SSH���L�������������������A������Cygterm���N��������������
1218 // �����������������B(2004.10.11 yutaka)
1219 pvar->settings.Enabled = 0;
1220
1221 } else if (MATCH_STR(option + 1, "auth") == 0) {
1222 // SSH2�������O�C���I�v�V����������
1223 //
1224 // SYNOPSIS: /ssh /auth=passowrd /user=���[�U�� /passwd=�p�X���[�h
1225 // /ssh /auth=publickey /user=���[�U�� /passwd=�p�X���[�h /keyfile=�p�X
1226 // EXAMPLE: /ssh /auth=password /user=nike /passwd=a@bc
1227 // /ssh /auth=publickey /user=foo /passwd=bar /keyfile=d:\tmp\id_rsa
1228 // NOTICE: �p�X���[�h���p�X�������������������A�u�����N���������� @ ���g�������B
1229 //
1230 // (2004.11.30 yutaka)
1231 // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1232 //
1233 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1234
1235 if (MATCH_STR(option + 5, "=password") == 0) { // �p�X���[�h/keyboard-interactive�F��
1236 //pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
1237 pvar->ssh2_authmethod = SSH_AUTH_PASSWORD;
1238
1239 } else if (MATCH_STR(option + 5, "=publickey") == 0) { // ���J���F��
1240 //pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
1241 pvar->ssh2_authmethod = SSH_AUTH_RSA;
1242
1243 } else {
1244 // TODO:
1245
1246 }
1247
1248 } else if (MATCH_STR(option + 1, "user=") == 0) {
1249 replace_to_blank(option + 6, pvar->ssh2_username, sizeof(pvar->ssh2_username));
1250 //_snprintf(pvar->ssh2_username, sizeof(pvar->ssh2_username), "%s", option + 6);
1251
1252 } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1253 replace_to_blank(option + 8, pvar->ssh2_password, sizeof(pvar->ssh2_password));
1254 //_snprintf(pvar->ssh2_password, sizeof(pvar->ssh2_password), "%s", option + 8);
1255
1256 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1257 replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1258
1259 }
1260
1261 }
1262
1263 return 0;
1264 }
1265
1266 static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1267 PCHAR DDETopic)
1268 {
1269 int i;
1270 BOOL inParam = FALSE;
1271 BOOL inQuotes = FALSE;
1272 PCHAR option = NULL;
1273 GET_VAR();
1274
1275 if (pvar->hostdlg_activated) {
1276 pvar->settings.Enabled = pvar->hostdlg_Enabled;
1277 }
1278
1279 for (i = 0; param[i] != 0; i++) {
1280 if (inQuotes ? param[i] ==
1281 '"' : (param[i] == ' ' || param[i] == '\t')) {
1282 if (option != NULL) {
1283 char ch = param[i];
1284
1285 param[i] = 0;
1286 if (parse_option
1287 (pvar, *option == '"' ? option + 1 : option)) {
1288 memset(option, ' ', i + 1 - (option - param));
1289 } else {
1290 param[i] = ch;
1291 }
1292 option = NULL;
1293 }
1294 inParam = FALSE;
1295 inQuotes = FALSE;
1296 } else if (!inParam) {
1297 if (param[i] == '"') {
1298 inQuotes = TRUE;
1299 inParam = TRUE;
1300 option = param + i;
1301 } else if (param[i] != ' ' && param[i] != '\t') {
1302 inParam = TRUE;
1303 option = param + i;
1304 }
1305 }
1306 }
1307
1308 if (option != NULL) {
1309 if (parse_option(pvar, option)) {
1310 memset(option, ' ', i - (option - param));
1311 }
1312 }
1313
1314 FWDUI_load_settings(pvar);
1315
1316 (pvar->ParseParam) (param, ts, DDETopic);
1317
1318 }
1319
1320 static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1321 {
1322 GET_VAR();
1323
1324 pvar->ReadIniFile = *hooks->ReadIniFile;
1325 pvar->WriteIniFile = *hooks->WriteIniFile;
1326 pvar->ParseParam = *hooks->ParseParam;
1327
1328 *hooks->ReadIniFile = TTXReadINIFile;
1329 *hooks->WriteIniFile = TTXWriteINIFile;
1330 *hooks->ParseParam = TTXParseParam;
1331 }
1332
1333 static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1334 {
1335 GET_VAR();
1336
1337 SSH_notify_win_size(pvar, cols, rows);
1338 }
1339
1340 static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1341 WORD newItemID, char FAR * text)
1342 {
1343 int i, j;
1344
1345 for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1346 HMENU submenu = GetSubMenu(menu, i);
1347
1348 for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1349 if (GetMenuItemID(submenu, j) == beforeItemID) {
1350 InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1351 text);
1352 return;
1353 }
1354 }
1355 }
1356 }
1357
1358 static void PASCAL FAR TTXModifyMenu(HMENU menu)
1359 {
1360 GET_VAR();
1361
1362 /* inserts before ID_HELP_ABOUT */
1363 insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1364 "About &TTSSH...");
1365
1366 /* inserts before ID_SETUP_TCPIP */
1367 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1368 "SS&H...");
1369 /* inserts before ID_SETUP_TCPIP */
1370 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1371 "SSH &Authentication...");
1372 /* inserts before ID_SETUP_TCPIP */
1373 insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1374 "SSH F&orwarding...");
1375 }
1376
1377 static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1378 {
1379 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1380 (LPARAM) prefix);
1381 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1382 SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1383 (LPARAM) (char FAR *) "\r\n");
1384 }
1385
1386 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1387 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1388 {
1389 typedef struct {
1390 WORD wLanguage;
1391 WORD wCodePage;
1392 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1393 LPLANGANDCODEPAGE lplgcode;
1394 UINT unLen;
1395 DWORD size;
1396 char *buf = NULL;
1397 BOOL ret;
1398 int i;
1399 char fmt[80];
1400 char *pbuf;
1401
1402 size = GetFileVersionInfoSize(exefile, NULL);
1403 if (size == 0) {
1404 goto error;
1405 }
1406 buf = malloc(size);
1407 ZeroMemory(buf, size);
1408
1409 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1410 goto error;
1411 }
1412
1413 ret = VerQueryValue(buf,
1414 "\\VarFileInfo\\Translation",
1415 (LPVOID *)&lplgcode, &unLen);
1416 if (ret == FALSE)
1417 goto error;
1418
1419 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1420 _snprintf(fmt, sizeof(fmt), "\\StringFileInfo\\%04x%04x\\FileVersion",
1421 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1422 VerQueryValue(buf, fmt, &pbuf, &unLen);
1423 if (unLen > 0) { // get success
1424 int n, a, b, c, d;
1425
1426 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1427 if (n == 4) { // convert success
1428 *major = a;
1429 *minor = b;
1430 *release = c;
1431 *build = d;
1432 break;
1433 }
1434 }
1435 }
1436
1437 free(buf);
1438 return;
1439
1440 error:
1441 free(buf);
1442 *major = *minor = *release = *build = 0;
1443 }
1444
1445 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1446 {
1447 char buf[1024];
1448 int a, b, c, d;
1449
1450 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1451 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1452 _snprintf(buf, sizeof(buf), "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1453 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1454
1455 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1456 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1457
1458 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1459 if (pvar->socket != INVALID_SOCKET) {
1460 if (SSHv1(pvar)) {
1461 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1462 append_about_text(dlg, "Server ID: ", buf);
1463 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1464 append_about_text(dlg, "Using protocol: ", buf);
1465 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1466 append_about_text(dlg, "Encryption: ", buf);
1467 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1468 append_about_text(dlg, "Server keys: ", buf);
1469 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1470 append_about_text(dlg, "Authentication: ", buf);
1471 SSH_get_compression_info(pvar, buf, sizeof(buf));
1472 append_about_text(dlg, "Compression: ", buf);
1473
1474 } else { // SSH2
1475 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1476 append_about_text(dlg, "Server ID: ", buf);
1477
1478 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1479
1480 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1481 append_about_text(dlg, "Using protocol: ", buf);
1482
1483 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1484 strcpy(buf, KEX_DH1);
1485 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1486 strcpy(buf, KEX_DH14);
1487 } else {
1488 strcpy(buf, KEX_DHGEX);
1489 }
1490 append_about_text(dlg, "KEX: ", buf);
1491
1492 if (pvar->hostkey_type == KEY_DSA) {
1493 strcpy(buf, "ssh-dss");
1494 } else {
1495 strcpy(buf, "ssh-rsa");
1496 }
1497 append_about_text(dlg, "Host Key: ", buf);
1498
1499 // add HMAC algorithm (2004.12.17 yutaka)
1500 buf[0] = '\0';
1501 if (pvar->ctos_hmac == HMAC_SHA1) {
1502 strcat(buf, "hmac-sha1");
1503 } else if (pvar->ctos_hmac == HMAC_MD5) {
1504 strcat(buf, "hmac-md5");
1505 }
1506 strcat(buf, " to server, ");
1507 if (pvar->stoc_hmac == HMAC_SHA1) {
1508 strcat(buf, "hmac-sha1");
1509 } else if (pvar->stoc_hmac == HMAC_MD5) {
1510 strcat(buf, "hmac-md5");
1511 }
1512 strcat(buf, " from server");
1513 append_about_text(dlg, "HMAC: ", buf);
1514
1515 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1516 append_about_text(dlg, "Encryption: ", buf);
1517 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1518 append_about_text(dlg, "Server keys: ", buf);
1519 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1520 append_about_text(dlg, "Authentication: ", buf);
1521 SSH_get_compression_info(pvar, buf, sizeof(buf));
1522 append_about_text(dlg, "Compression: ", buf);
1523
1524 }
1525 }
1526 }
1527
1528 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1529 LPARAM lParam)
1530 {
1531 switch (msg) {
1532 case WM_INITDIALOG:
1533 init_about_dlg((PTInstVar) lParam, dlg);
1534 return TRUE;
1535 case WM_COMMAND:
1536 switch (LOWORD(wParam)) {
1537 case IDOK:
1538 EndDialog(dlg, 1);
1539 return TRUE;
1540 case IDCANCEL: /* there isn't a cancel button, but other Windows
1541 UI things can send this message */
1542 EndDialog(dlg, 0);
1543 return TRUE;
1544 }
1545 break;
1546 }
1547
1548 return FALSE;
1549 }
1550
1551 static char FAR *get_cipher_name(int cipher)
1552 {
1553 switch (cipher) {
1554 case SSH_CIPHER_NONE:
1555 return "<ciphers below this line are disabled>";
1556 case SSH_CIPHER_RC4:
1557 return "RC4";
1558 case SSH_CIPHER_3DES:
1559 return "3DES";
1560 case SSH_CIPHER_DES:
1561 return "DES";
1562 case SSH_CIPHER_IDEA:
1563 return "IDEA";
1564 case SSH_CIPHER_TSS:
1565 return "TSS";
1566 case SSH_CIPHER_BLOWFISH:
1567 return "Blowfish";
1568
1569 // for SSH2(yutaka)
1570 case SSH_CIPHER_AES128:
1571 return "AES128(SSH2)";
1572 case SSH_CIPHER_3DES_CBC:
1573 return "3DES-CBC(SSH2)";
1574
1575 default:
1576 return NULL;
1577 }
1578 }
1579
1580 static void set_move_button_status(HWND dlg)
1581 {
1582 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1583 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1584 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1585
1586 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1587 && curPos <= maxPos);
1588 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1589 && curPos < maxPos);
1590 }
1591
1592 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1593 {
1594 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1595 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1596 int i;
1597 int ch;
1598
1599 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1600 SendMessage(compressionControl, TBM_SETPOS, TRUE,
1601 pvar->settings.CompressionLevel);
1602
1603 normalize_cipher_order(pvar->settings.CipherOrder);
1604 SSH2_update_cipher_myproposal(pvar); // yutaka
1605
1606 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1607 int cipher = pvar->settings.CipherOrder[i] - '0';
1608 char FAR *name = get_cipher_name(cipher);
1609
1610 if (name != NULL) {
1611 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1612 }
1613 }
1614
1615 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1616 set_move_button_status(dlg);
1617
1618 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1619 i++) {
1620 }
1621 if (ch != 0) {
1622 pvar->settings.KnownHostsFiles[i] = 0;
1623 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1624 pvar->settings.KnownHostsFiles);
1625 pvar->settings.KnownHostsFiles[i] = ch;
1626 SetDlgItemText(dlg, IDC_READONLYFILENAME,
1627 pvar->settings.KnownHostsFiles + i + 1);
1628 } else {
1629 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1630 pvar->settings.KnownHostsFiles);
1631 }
1632
1633 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
1634 {
1635 char buf[10];
1636 _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
1637 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
1638 }
1639
1640 }
1641
1642 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1643 char FAR * basename)
1644 {
1645 int filename_start = 0;
1646 int i;
1647 int ch;
1648
1649 if (basename[0] == '\\' || basename[0] == '/'
1650 || (basename[0] != 0 && basename[1] == ':')) {
1651 strncpy(buf, basename, bufsize);
1652 buf[bufsize - 1] = 0;
1653 return;
1654 }
1655
1656 GetModuleFileName(NULL, buf, bufsize);
1657 for (i = 0; (ch = buf[i]) != 0; i++) {
1658 if (ch == '\\' || ch == '/' || ch == ':') {
1659 filename_start = i + 1;
1660 }
1661 }
1662
1663 if (bufsize > filename_start) {
1664 strncpy(buf + filename_start, basename, bufsize - filename_start);
1665 }
1666 buf[bufsize - 1] = 0;
1667 }
1668
1669 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1670 char FAR * basename)
1671 {
1672 char buf[1024];
1673 int filename_start = 0;
1674 int i;
1675 int ch, ch2;
1676
1677 if (basename[0] != '\\' && basename[0] != '/'
1678 && (basename[0] == 0 || basename[1] != ':')) {
1679 strncpy(dest, basename, destsize);
1680 dest[destsize - 1] = 0;
1681 return strlen(dest);
1682 }
1683
1684 GetModuleFileName(NULL, buf, sizeof(buf));
1685 for (i = 0; (ch = buf[i]) != 0; i++) {
1686 if (ch == '\\' || ch == '/' || ch == ':') {
1687 filename_start = i + 1;
1688 }
1689 }
1690
1691 for (i = 0; i < filename_start; i++) {
1692 ch = toupper(buf[i]);
1693 ch2 = toupper(basename[i]);
1694
1695 if (ch == ch2
1696 || ((ch == '\\' || ch == '/')
1697 && (ch2 == '\\' || ch2 == '/'))) {
1698 } else {
1699 break;
1700 }
1701 }
1702
1703 if (i == filename_start) {
1704 strncpy(dest, basename + i, destsize);
1705 } else {
1706 strncpy(dest, basename, destsize);
1707 }
1708 dest[destsize - 1] = 0;
1709 return strlen(dest);
1710 }
1711
1712 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1713 {
1714 char buf[4096];
1715 char buf2[1024];
1716 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1717 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1718 int i, j, buf2index, bufindex;
1719 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1720
1721 pvar->settings.CompressionLevel =
1722 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1723
1724 buf2index = 0;
1725 for (i = 0; i < count; i++) {
1726 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1727
1728 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1729 buf[0] = 0;
1730 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1731 for (j = 0;
1732 j <= SSH_CIPHER_MAX
1733 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1734 }
1735 if (j <= SSH_CIPHER_MAX) {
1736 buf2[buf2index] = '0' + j;
1737 buf2index++;
1738 }
1739 }
1740 }
1741 buf2[buf2index] = 0;
1742 normalize_cipher_order(buf2);
1743 strcpy(pvar->settings.CipherOrder, buf2);
1744 SSH2_update_cipher_myproposal(pvar); // yutaka
1745
1746 buf[0] = 0;
1747 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1748 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1749 sizeof(pvar->settings.
1750 KnownHostsFiles), buf);
1751 buf[0] = 0;
1752 bufindex = 0;
1753 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1754 for (i = 0; buf[i] != 0; i++) {
1755 if (buf[i] == ';') {
1756 buf[i] = 0;
1757 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1758 pvar->settings.KnownHostsFiles[j] = ';';
1759 j++;
1760 j += copy_teraterm_dir_relative_path(pvar->settings.
1761 KnownHostsFiles + j,
1762 sizeof(pvar->settings.
1763 KnownHostsFiles)
1764 - j, buf + bufindex);
1765 }
1766 bufindex = i + 1;
1767 }
1768 }
1769 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1770 pvar->settings.KnownHostsFiles[j] = ';';
1771 j++;
1772 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1773 sizeof(pvar->settings.
1774 KnownHostsFiles) - j,
1775 buf + bufindex);
1776 }
1777
1778 // get SSH HeartBeat(keep-alive)
1779 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
1780 i = atoi(buf);
1781 if (i < 0)
1782 i = 60;
1783 pvar->settings.ssh_heartbeat_overtime = i;
1784
1785 }
1786
1787 static void move_cur_sel_delta(HWND listbox, int delta)
1788 {
1789 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1790 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1791 int newPos = curPos + delta;
1792 char buf[1024];
1793
1794 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1795 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1796
1797 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1798 buf[0] = 0;
1799 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1800 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1801 SendMessage(listbox, LB_INSERTSTRING, newPos,
1802 (LPARAM) (char FAR *) buf);
1803 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1804 }
1805 }
1806 }
1807
1808 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1809 int readonly)
1810 {
1811 #ifdef TERATERM32
1812 OPENFILENAME params;
1813 char fullname_buf[2048] = "ssh_known_hosts";
1814
1815 params.lStructSize = sizeof(OPENFILENAME);
1816 params.hwndOwner = parent;
1817 params.lpstrFilter = NULL;
1818 params.lpstrCustomFilter = NULL;
1819 params.nFilterIndex = 0;
1820 buf[0] = 0;
1821 params.lpstrFile = fullname_buf;
1822 params.nMaxFile = sizeof(fullname_buf);
1823 params.lpstrFileTitle = NULL;
1824 params.lpstrInitialDir = NULL;
1825 params.lpstrTitle =
1826 readonly ? "Choose a read-only known-hosts file to add" :
1827 "Choose a read/write known-hosts file";
1828 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1829 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1830 params.lpstrDefExt = NULL;
1831
1832 if (GetOpenFileName(&params) != 0) {
1833 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1834 return 1;
1835 } else {
1836 int err = CommDlgExtendedError();
1837
1838 if (err != 0) {
1839 char buf[1024];
1840
1841 _snprintf(buf, sizeof(buf),
1842 "Cannot show file dialog box: error %d", err);
1843 buf[sizeof(buf) - 1] = 0;
1844 MessageBox(parent, buf, "TTSSH Error",
1845 MB_OK | MB_ICONEXCLAMATION);
1846 }
1847
1848 return 0;
1849 }
1850 #else
1851 return 0;
1852 #endif
1853 }
1854
1855 static void choose_read_write_file(HWND dlg)
1856 {
1857 char buf[1024];
1858
1859 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1860 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1861 }
1862 }
1863
1864 static void choose_read_only_file(HWND dlg)
1865 {
1866 char buf[1024];
1867 char buf2[4096];
1868
1869 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1870 buf2[0] = 0;
1871 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1872 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1873 strncat(buf2, ";", sizeof(buf2));
1874 }
1875 strncat(buf2, buf, sizeof(buf2));
1876 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1877 }
1878 }
1879
1880 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1881 LPARAM lParam)
1882 {
1883 switch (msg) {
1884 case WM_INITDIALOG:
1885 SetWindowLong(dlg, DWL_USER, lParam);
1886 init_setup_dlg((PTInstVar) lParam, dlg);
1887 return TRUE;
1888 case WM_COMMAND:
1889 switch (LOWORD(wParam)) {
1890 case IDOK:
1891 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1892 dlg);
1893 EndDialog(dlg, 1);
1894 return TRUE;
1895 case IDCANCEL: /* there isn't a cancel button, but other Windows
1896 UI things can send this message */
1897 EndDialog(dlg, 0);
1898 return TRUE;
1899 case IDC_SSHMOVECIPHERUP:
1900 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1901 set_move_button_status(dlg);
1902 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1903 return TRUE;
1904 case IDC_SSHMOVECIPHERDOWN:
1905 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1906 set_move_button_status(dlg);
1907 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1908 return TRUE;
1909 case IDC_SSHCIPHERPREFS:
1910 set_move_button_status(dlg);
1911 return TRUE;
1912 case IDC_CHOOSEREADWRITEFILE:
1913 choose_read_write_file(dlg);
1914 return TRUE;
1915 case IDC_CHOOSEREADONLYFILE:
1916 choose_read_only_file(dlg);
1917 return TRUE;
1918 }
1919 break;
1920 }
1921
1922 return FALSE;
1923 }
1924
1925 static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1926 {
1927 GET_VAR();
1928
1929 if (pvar->fatal_error) {
1930 return 0;
1931 }
1932
1933 switch (cmd) {
1934 case ID_ABOUTMENU:
1935 if (DialogBoxParam
1936 (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1937 (LPARAM) pvar)
1938 == -1) {
1939 MessageBox(hWin, "Cannot create About box window.",
1940 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1941 }
1942 return 1;
1943 case ID_SSHAUTH:
1944 AUTH_do_cred_dialog(pvar);
1945 return 1;
1946 case ID_SSHSETUPMENU:
1947 if (DialogBoxParam
1948 (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1949 (LPARAM) pvar)
1950 == -1) {
1951 MessageBox(hWin, "Cannot create TTSSH Setup window.",
1952 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1953 }
1954 return 1;
1955 case ID_SSHAUTHSETUPMENU:
1956 AUTH_do_default_cred_dialog(pvar);
1957 return 1;
1958 case ID_SSHFWDSETUPMENU:
1959 FWDUI_do_forwarding_dialog(pvar);
1960 return 1;
1961 case ID_SSHUNKNOWNHOST:
1962 HOSTS_do_unknown_host_dialog(hWin, pvar);
1963 return 1;
1964 case ID_SSHDIFFERENTHOST:
1965 HOSTS_do_different_host_dialog(hWin, pvar);
1966 return 1;
1967 case ID_SSHASYNCMESSAGEBOX:
1968 if (pvar->err_msg != NULL) {
1969 char FAR *msg = pvar->err_msg;
1970
1971 /* Could there be a buffer overrun bug anywhere in Win32
1972 MessageBox? Who knows? I'm paranoid. */
1973 if (strlen(msg) > 2048) {
1974 msg[2048] = 0;
1975 }
1976
1977 pvar->showing_err = TRUE;
1978 pvar->err_msg = NULL;
1979 #if 1
1980 // XXX: "SECURITY WARINIG" dialog�� ESC �L�[�������������A
1981 // �������A�v���P�[�V�����G���[�����������A���LAPI�������B(2004.12.16 yutaka)
1982 if (!SSHv1(pvar)) {
1983 MessageBox(NULL, msg, "TTSSH",
1984 MB_TASKMODAL | MB_ICONEXCLAMATION);
1985 }
1986 #else
1987 MessageBox(NULL, msg, "TTSSH",
1988 MB_TASKMODAL | MB_ICONEXCLAMATION);
1989 #endif
1990 free(msg);
1991 pvar->showing_err = FALSE;
1992
1993 if (pvar->err_msg != NULL) {
1994 PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1995 } else {
1996 AUTH_notify_end_error(pvar);
1997 }
1998 }
1999 return 1;
2000 default:
2001 return 0;
2002 }
2003 }
2004
2005 static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
2006 PGetHNRec rec)
2007 {
2008 char tmpFile[MAX_PATH];
2009 char tmpPath[1024];
2010 char buf[1024];
2011 int i;
2012 GET_VAR();
2013
2014 GetTempPath(sizeof(tmpPath), tmpPath);
2015 GetTempFileName(tmpPath, "TTX", 0, tmpFile);
2016
2017 for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
2018 }
2019
2020 if (i < cmdlen) {
2021 strncpy(buf, cmd + i, sizeof(buf));
2022 cmd[i] = 0;
2023
2024 write_ssh_options(pvar, tmpFile, &pvar->settings);
2025
2026 strncat(cmd, " /ssh-consume=", cmdlen);
2027 strncat(cmd, tmpFile, cmdlen);
2028
2029 strncat(cmd, buf, cmdlen);
2030
2031 if (pvar->hostdlg_Enabled) {
2032 strncat(cmd, " /ssh", cmdlen);
2033
2034 // add option of SSH protcol version (2004.10.11 yutaka)
2035 if (pvar->settings.ssh_protocol_version == 2) {
2036 strncat(cmd, " /2", cmdlen);
2037 } else {
2038 strncat(cmd, " /1", cmdlen);
2039 }
2040
2041 }
2042 }
2043 }
2044
2045 /* This function is called when Teraterm is quitting. You can use it to clean
2046 up.
2047
2048 This function is called for each extension, in reverse load order (see
2049 below).
2050 */
2051 static void PASCAL FAR TTXEnd(void)
2052 {
2053 GET_VAR();
2054
2055 uninit_TTSSH(pvar);
2056
2057 if (pvar->err_msg != NULL) {
2058 /* Could there be a buffer overrun bug anywhere in Win32
2059 MessageBox? Who knows? I'm paranoid. */
2060 if (strlen(pvar->err_msg) > 2048) {
2061 pvar->err_msg[2048] = 0;
2062 }
2063
2064 MessageBox(NULL, pvar->err_msg, "TTSSH",
2065 MB_TASKMODAL | MB_ICONEXCLAMATION);
2066
2067 free(pvar->err_msg);
2068 pvar->err_msg = NULL;
2069 }
2070 #ifndef TERATERM32
2071 DelVar();
2072 #endif
2073 }
2074
2075 /* This record contains all the information that the extension forwards to the
2076 main Teraterm code. It mostly consists of pointers to the above functions.
2077 Any of the function pointers can be replaced with NULL, in which case
2078 Teraterm will just ignore that function and assume default behaviour, which
2079 means "do nothing".
2080 */
2081 static TTXExports Exports = {
2082 /* This must contain the size of the structure. See below for its usage. */
2083 sizeof(TTXExports),
2084 ORDER,
2085
2086 /* Now we just list the functions that we've implemented. */
2087 TTXInit,
2088 TTXGetUIHooks,
2089 TTXGetSetupHooks,
2090 TTXOpenTCP,
2091 TTXCloseTCP,
2092 TTXSetWinSize,
2093 TTXModifyMenu,
2094 NULL,
2095 TTXProcessCommand,
2096 TTXEnd,
2097 TTXSetCommandLine
2098 };
2099
2100 #ifdef TERATERM32
2101 BOOL __declspec(dllexport)
2102 PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2103 {
2104 #else
2105 BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2106 {
2107 #endif
2108 int size = sizeof(Exports) - sizeof(exports->size);
2109 /* do version checking if necessary */
2110 /* if (Version!=TTVERSION) return FALSE; */
2111
2112 if (size > exports->size) {
2113 size = exports->size;
2114 }
2115 memcpy((char FAR *) exports + sizeof(exports->size),
2116 (char FAR *) &Exports + sizeof(exports->size), size);
2117 return TRUE;
2118 }
2119
2120 #ifdef TERATERM32
2121 static HANDLE __mem_mapping = NULL;
2122
2123 BOOL WINAPI DllMain(HANDLE hInstance,
2124 ULONG ul_reason_for_call, LPVOID lpReserved)
2125 {
2126 switch (ul_reason_for_call) {
2127 case DLL_THREAD_ATTACH:
2128 /* do thread initialization */
2129 break;
2130 case DLL_THREAD_DETACH:
2131 /* do thread cleanup */
2132 break;
2133 case DLL_PROCESS_ATTACH:
2134 /* do process initialization */
2135 DisableThreadLibraryCalls(hInstance);
2136 hInst = hInstance;
2137 pvar = &InstVar;
2138 __mem_mapping =
2139 CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
2140 sizeof(TS_SSH), "TTSSH_1-4_TS_data");
2141 if (__mem_mapping == NULL) {
2142 /* fake it. The settings won't be shared, but what the heck. */
2143 pvar->ts_SSH = NULL;
2144 } else {
2145 pvar->ts_SSH =
2146 (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
2147 0, 0);
2148 }
2149 if (pvar->ts_SSH == NULL) {
2150 /* fake it. The settings won't be shared, but what the heck. */
2151 pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
2152 if (__mem_mapping != NULL) {
2153 CloseHandle(__mem_mapping);
2154 }
2155 }
2156 break;
2157 case DLL_PROCESS_DETACH:
2158 /* do process cleanup */
2159 if (__mem_mapping == NULL) {
2160 free(pvar->ts_SSH);
2161 } else {
2162 CloseHandle(__mem_mapping);
2163 UnmapViewOfFile(pvar->ts_SSH);
2164 }
2165 break;
2166 }
2167 return TRUE;
2168 }
2169 #else
2170 #ifdef WATCOM
2171 #pragma off (unreferenced);
2172 #endif
2173 int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
2174 WORD wHeapSize, LPSTR lpszCmdLine)
2175 #ifdef WATCOM
2176 #pragma on (unreferenced);
2177 #endif
2178 {
2179 int i;
2180 for (i = 0; i < MAXNUMINST; i++)
2181 TaskList[i] = NULL;
2182 hInst = hInstance;
2183 return (1);
2184 }
2185 #endif
2186
2187
2188 /*
2189 * $Log: not supported by cvs2svn $
2190 * Revision 1.14 2005/03/12 12:08:05 yutakakn
2191 * �p�X���[�h�F�����O���s��keyboard-interactive���\�b�h���A�f�t�H���g�����l������(0)�������B
2192 * �����A�F���_�C�A���O�����x�������������L�����������X���������������B
2193 *
2194 * Revision 1.13 2005/03/03 13:28:23 yutakakn
2195 * �N���C�A���g��SSH�o�[�W������ ttxssh.dll �������������A�T�[�o�����������������B
2196 *
2197 * Revision 1.12 2005/02/28 14:51:44 yutakakn
2198 * �o�[�W�����_�C�A���O���\������TTSSH���o�[�W�������Attxssh.dll��
2199 * �o�[�W�������������������������������B
2200 *
2201 * Revision 1.11 2005/02/22 08:48:11 yutakakn
2202 * TTSSH setup�_�C�A���O�� HeartBeat �����������B
2203 * TTSSH authentication setup�_�C�A���O�� keyboard-interactive �����������B
2204 *
2205 * Revision 1.10 2005/01/27 13:30:33 yutakakn
2206 * ���J���F���������O�C�����T�|�[�g�B
2207 * /auth=publickey, /keyfile �I�v�V�������V�K���������B
2208 * �����A�����������������T�|�[�g�B
2209 *
2210 * Revision 1.9 2005/01/24 14:07:07 yutakakn
2211 * �Ekeyboard-interactive�F�����T�|�[�g�����B
2212 * �@�����������Ateraterm.ini�� "KeyboardInteractive" �G���g�������������B
2213 * �E�o�[�W�����_�C�A���O�� OpenSSL�o�[�W���� ������
2214 *
2215 * Revision 1.8 2004/12/27 14:05:08 yutakakn
2216 * 'Auto window close'���L���������A���f�������������������������C�������B
2217 * �@�E�X���b�h���I����������������������
2218 * �@�E�m������SSH���\�[�X������
2219 *
2220 * Revision 1.7 2004/12/17 14:28:36 yutakakn
2221 * ���b�Z�[�W�F���A���S���Y���� HMAC-MD5 �������B
2222 * TTSSH�o�[�W�����_�C�A���O��HMAC�A���S���Y���\���������B
2223 *
2224 * Revision 1.6 2004/12/16 13:57:43 yutakakn
2225 * "SECURITY WARINIG" dialog�� ESC �L�[�������������A
2226 * �A�v���P�[�V�����G���[���������������b�������B
2227 *
2228 * Revision 1.5 2004/12/11 07:31:00 yutakakn
2229 * SSH heartbeat�X���b�h�����������B�����������AIP�}�X�J���[�h�������������A���[�^��
2230 * NAT�e�[�u���N���A�������ASSH�R�l�N�V���������f�����������������������B
2231 * ���������������Ateraterm.ini��TTSSH�Z�N�V�������AHeartBeat �G���g���������B
2232 *
2233 * Revision 1.4 2004/12/01 15:37:49 yutakakn
2234 * SSH2�������O�C���@�\�������B
2235 * �����A�p�X���[�h�F�������������B
2236 * �E�R�}���h���C��
2237 * /ssh /auth=�F�����\�b�h /user=���[�U�� /passwd=�p�X���[�h
2238 *
2239 * Revision 1.3 2004/11/29 15:52:37 yutakakn
2240 * SSH��default protocol��SSH2�������B
2241 *
2242 * Revision 1.2 2004/11/23 14:32:26 yutakakn
2243 * �����_�C�A���O���N�������ATCP/IP���u�z�X�g���v���t�H�[�J�X�������������������B
2244 *
2245 *
2246 */

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26