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 2789 - (show annotations) (download) (as text)
Tue Feb 22 08:48:11 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 58376 byte(s)
TTSSH setupダイアログに HeartBeat 設定を追加。
TTSSH authentication setupダイアログに keyboard-interactive 設定を追加。

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

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