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 2784 - (show annotations) (download) (as text)
Thu Jan 27 13:30:33 2005 UTC (19 years, 2 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 57784 byte(s)
公開鍵認証自動ログインをサポート。
/auth=publickey, /keyfile オプションを新規追加した。
また、空白を含む引数をサポート。

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
1566 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1567 char FAR * basename)
1568 {
1569 int filename_start = 0;
1570 int i;
1571 int ch;
1572
1573 if (basename[0] == '\\' || basename[0] == '/'
1574 || (basename[0] != 0 && basename[1] == ':')) {
1575 strncpy(buf, basename, bufsize);
1576 buf[bufsize - 1] = 0;
1577 return;
1578 }
1579
1580 GetModuleFileName(NULL, buf, bufsize);
1581 for (i = 0; (ch = buf[i]) != 0; i++) {
1582 if (ch == '\\' || ch == '/' || ch == ':') {
1583 filename_start = i + 1;
1584 }
1585 }
1586
1587 if (bufsize > filename_start) {
1588 strncpy(buf + filename_start, basename, bufsize - filename_start);
1589 }
1590 buf[bufsize - 1] = 0;
1591 }
1592
1593 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1594 char FAR * basename)
1595 {
1596 char buf[1024];
1597 int filename_start = 0;
1598 int i;
1599 int ch, ch2;
1600
1601 if (basename[0] != '\\' && basename[0] != '/'
1602 && (basename[0] == 0 || basename[1] != ':')) {
1603 strncpy(dest, basename, destsize);
1604 dest[destsize - 1] = 0;
1605 return strlen(dest);
1606 }
1607
1608 GetModuleFileName(NULL, buf, sizeof(buf));
1609 for (i = 0; (ch = buf[i]) != 0; i++) {
1610 if (ch == '\\' || ch == '/' || ch == ':') {
1611 filename_start = i + 1;
1612 }
1613 }
1614
1615 for (i = 0; i < filename_start; i++) {
1616 ch = toupper(buf[i]);
1617 ch2 = toupper(basename[i]);
1618
1619 if (ch == ch2
1620 || ((ch == '\\' || ch == '/')
1621 && (ch2 == '\\' || ch2 == '/'))) {
1622 } else {
1623 break;
1624 }
1625 }
1626
1627 if (i == filename_start) {
1628 strncpy(dest, basename + i, destsize);
1629 } else {
1630 strncpy(dest, basename, destsize);
1631 }
1632 dest[destsize - 1] = 0;
1633 return strlen(dest);
1634 }
1635
1636 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1637 {
1638 char buf[4096];
1639 char buf2[1024];
1640 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1641 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1642 int i, j, buf2index, bufindex;
1643 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1644
1645 pvar->settings.CompressionLevel =
1646 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1647
1648 buf2index = 0;
1649 for (i = 0; i < count; i++) {
1650 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1651
1652 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1653 buf[0] = 0;
1654 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1655 for (j = 0;
1656 j <= SSH_CIPHER_MAX
1657 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1658 }
1659 if (j <= SSH_CIPHER_MAX) {
1660 buf2[buf2index] = '0' + j;
1661 buf2index++;
1662 }
1663 }
1664 }
1665 buf2[buf2index] = 0;
1666 normalize_cipher_order(buf2);
1667 strcpy(pvar->settings.CipherOrder, buf2);
1668 SSH2_update_cipher_myproposal(pvar); // yutaka
1669
1670 buf[0] = 0;
1671 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1672 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1673 sizeof(pvar->settings.
1674 KnownHostsFiles), buf);
1675 buf[0] = 0;
1676 bufindex = 0;
1677 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1678 for (i = 0; buf[i] != 0; i++) {
1679 if (buf[i] == ';') {
1680 buf[i] = 0;
1681 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1682 pvar->settings.KnownHostsFiles[j] = ';';
1683 j++;
1684 j += copy_teraterm_dir_relative_path(pvar->settings.
1685 KnownHostsFiles + j,
1686 sizeof(pvar->settings.
1687 KnownHostsFiles)
1688 - j, buf + bufindex);
1689 }
1690 bufindex = i + 1;
1691 }
1692 }
1693 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1694 pvar->settings.KnownHostsFiles[j] = ';';
1695 j++;
1696 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1697 sizeof(pvar->settings.
1698 KnownHostsFiles) - j,
1699 buf + bufindex);
1700 }
1701 }
1702
1703 static void move_cur_sel_delta(HWND listbox, int delta)
1704 {
1705 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1706 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1707 int newPos = curPos + delta;
1708 char buf[1024];
1709
1710 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1711 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1712
1713 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1714 buf[0] = 0;
1715 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1716 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1717 SendMessage(listbox, LB_INSERTSTRING, newPos,
1718 (LPARAM) (char FAR *) buf);
1719 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1720 }
1721 }
1722 }
1723
1724 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1725 int readonly)
1726 {
1727 #ifdef TERATERM32
1728 OPENFILENAME params;
1729 char fullname_buf[2048] = "ssh_known_hosts";
1730
1731 params.lStructSize = sizeof(OPENFILENAME);
1732 params.hwndOwner = parent;
1733 params.lpstrFilter = NULL;
1734 params.lpstrCustomFilter = NULL;
1735 params.nFilterIndex = 0;
1736 buf[0] = 0;
1737 params.lpstrFile = fullname_buf;
1738 params.nMaxFile = sizeof(fullname_buf);
1739 params.lpstrFileTitle = NULL;
1740 params.lpstrInitialDir = NULL;
1741 params.lpstrTitle =
1742 readonly ? "Choose a read-only known-hosts file to add" :
1743 "Choose a read/write known-hosts file";
1744 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1745 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1746 params.lpstrDefExt = NULL;
1747
1748 if (GetOpenFileName(&params) != 0) {
1749 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1750 return 1;
1751 } else {
1752 int err = CommDlgExtendedError();
1753
1754 if (err != 0) {
1755 char buf[1024];
1756
1757 _snprintf(buf, sizeof(buf),
1758 "Cannot show file dialog box: error %d", err);
1759 buf[sizeof(buf) - 1] = 0;
1760 MessageBox(parent, buf, "TTSSH Error",
1761 MB_OK | MB_ICONEXCLAMATION);
1762 }
1763
1764 return 0;
1765 }
1766 #else
1767 return 0;
1768 #endif
1769 }
1770
1771 static void choose_read_write_file(HWND dlg)
1772 {
1773 char buf[1024];
1774
1775 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1776 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1777 }
1778 }
1779
1780 static void choose_read_only_file(HWND dlg)
1781 {
1782 char buf[1024];
1783 char buf2[4096];
1784
1785 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1786 buf2[0] = 0;
1787 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1788 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1789 strncat(buf2, ";", sizeof(buf2));
1790 }
1791 strncat(buf2, buf, sizeof(buf2));
1792 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1793 }
1794 }
1795
1796 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1797 LPARAM lParam)
1798 {
1799 switch (msg) {
1800 case WM_INITDIALOG:
1801 SetWindowLong(dlg, DWL_USER, lParam);
1802 init_setup_dlg((PTInstVar) lParam, dlg);
1803 return TRUE;
1804 case WM_COMMAND:
1805 switch (LOWORD(wParam)) {
1806 case IDOK:
1807 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1808 dlg);
1809 EndDialog(dlg, 1);
1810 return TRUE;
1811 case IDCANCEL: /* there isn't a cancel button, but other Windows
1812 UI things can send this message */
1813 EndDialog(dlg, 0);
1814 return TRUE;
1815 case IDC_SSHMOVECIPHERUP:
1816 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1817 set_move_button_status(dlg);
1818 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1819 return TRUE;
1820 case IDC_SSHMOVECIPHERDOWN:
1821 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1822 set_move_button_status(dlg);
1823 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1824 return TRUE;
1825 case IDC_SSHCIPHERPREFS:
1826 set_move_button_status(dlg);
1827 return TRUE;
1828 case IDC_CHOOSEREADWRITEFILE:
1829 choose_read_write_file(dlg);
1830 return TRUE;
1831 case IDC_CHOOSEREADONLYFILE:
1832 choose_read_only_file(dlg);
1833 return TRUE;
1834 }
1835 break;
1836 }
1837
1838 return FALSE;
1839 }
1840
1841 static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1842 {
1843 GET_VAR();
1844
1845 if (pvar->fatal_error) {
1846 return 0;
1847 }
1848
1849 switch (cmd) {
1850 case ID_ABOUTMENU:
1851 if (DialogBoxParam
1852 (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1853 (LPARAM) pvar)
1854 == -1) {
1855 MessageBox(hWin, "Cannot create About box window.",
1856 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1857 }
1858 return 1;
1859 case ID_SSHAUTH:
1860 AUTH_do_cred_dialog(pvar);
1861 return 1;
1862 case ID_SSHSETUPMENU:
1863 if (DialogBoxParam
1864 (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1865 (LPARAM) pvar)
1866 == -1) {
1867 MessageBox(hWin, "Cannot create TTSSH Setup window.",
1868 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1869 }
1870 return 1;
1871 case ID_SSHAUTHSETUPMENU:
1872 AUTH_do_default_cred_dialog(pvar);
1873 return 1;
1874 case ID_SSHFWDSETUPMENU:
1875 FWDUI_do_forwarding_dialog(pvar);
1876 return 1;
1877 case ID_SSHUNKNOWNHOST:
1878 HOSTS_do_unknown_host_dialog(hWin, pvar);
1879 return 1;
1880 case ID_SSHDIFFERENTHOST:
1881 HOSTS_do_different_host_dialog(hWin, pvar);
1882 return 1;
1883 case ID_SSHASYNCMESSAGEBOX:
1884 if (pvar->err_msg != NULL) {
1885 char FAR *msg = pvar->err_msg;
1886
1887 /* Could there be a buffer overrun bug anywhere in Win32
1888 MessageBox? Who knows? I'm paranoid. */
1889 if (strlen(msg) > 2048) {
1890 msg[2048] = 0;
1891 }
1892
1893 pvar->showing_err = TRUE;
1894 pvar->err_msg = NULL;
1895 #if 1
1896 // XXX: "SECURITY WARINIG" dialog�� ESC �L�[�������������A
1897 // �������A�v���P�[�V�����G���[�����������A���LAPI�������B(2004.12.16 yutaka)
1898 if (!SSHv1(pvar)) {
1899 MessageBox(NULL, msg, "TTSSH",
1900 MB_TASKMODAL | MB_ICONEXCLAMATION);
1901 }
1902 #else
1903 MessageBox(NULL, msg, "TTSSH",
1904 MB_TASKMODAL | MB_ICONEXCLAMATION);
1905 #endif
1906 free(msg);
1907 pvar->showing_err = FALSE;
1908
1909 if (pvar->err_msg != NULL) {
1910 PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1911 } else {
1912 AUTH_notify_end_error(pvar);
1913 }
1914 }
1915 return 1;
1916 default:
1917 return 0;
1918 }
1919 }
1920
1921 static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
1922 PGetHNRec rec)
1923 {
1924 char tmpFile[MAX_PATH];
1925 char tmpPath[1024];
1926 char buf[1024];
1927 int i;
1928 GET_VAR();
1929
1930 GetTempPath(sizeof(tmpPath), tmpPath);
1931 GetTempFileName(tmpPath, "TTX", 0, tmpFile);
1932
1933 for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
1934 }
1935
1936 if (i < cmdlen) {
1937 strncpy(buf, cmd + i, sizeof(buf));
1938 cmd[i] = 0;
1939
1940 write_ssh_options(pvar, tmpFile, &pvar->settings);
1941
1942 strncat(cmd, " /ssh-consume=", cmdlen);
1943 strncat(cmd, tmpFile, cmdlen);
1944
1945 strncat(cmd, buf, cmdlen);
1946
1947 if (pvar->hostdlg_Enabled) {
1948 strncat(cmd, " /ssh", cmdlen);
1949
1950 // add option of SSH protcol version (2004.10.11 yutaka)
1951 if (pvar->settings.ssh_protocol_version == 2) {
1952 strncat(cmd, " /2", cmdlen);
1953 } else {
1954 strncat(cmd, " /1", cmdlen);
1955 }
1956
1957 }
1958 }
1959 }
1960
1961 /* This function is called when Teraterm is quitting. You can use it to clean
1962 up.
1963
1964 This function is called for each extension, in reverse load order (see
1965 below).
1966 */
1967 static void PASCAL FAR TTXEnd(void)
1968 {
1969 GET_VAR();
1970
1971 uninit_TTSSH(pvar);
1972
1973 if (pvar->err_msg != NULL) {
1974 /* Could there be a buffer overrun bug anywhere in Win32
1975 MessageBox? Who knows? I'm paranoid. */
1976 if (strlen(pvar->err_msg) > 2048) {
1977 pvar->err_msg[2048] = 0;
1978 }
1979
1980 MessageBox(NULL, pvar->err_msg, "TTSSH",
1981 MB_TASKMODAL | MB_ICONEXCLAMATION);
1982
1983 free(pvar->err_msg);
1984 pvar->err_msg = NULL;
1985 }
1986 #ifndef TERATERM32
1987 DelVar();
1988 #endif
1989 }
1990
1991 /* This record contains all the information that the extension forwards to the
1992 main Teraterm code. It mostly consists of pointers to the above functions.
1993 Any of the function pointers can be replaced with NULL, in which case
1994 Teraterm will just ignore that function and assume default behaviour, which
1995 means "do nothing".
1996 */
1997 static TTXExports Exports = {
1998 /* This must contain the size of the structure. See below for its usage. */
1999 sizeof(TTXExports),
2000 ORDER,
2001
2002 /* Now we just list the functions that we've implemented. */
2003 TTXInit,
2004 TTXGetUIHooks,
2005 TTXGetSetupHooks,
2006 TTXOpenTCP,
2007 TTXCloseTCP,
2008 TTXSetWinSize,
2009 TTXModifyMenu,
2010 NULL,
2011 TTXProcessCommand,
2012 TTXEnd,
2013 TTXSetCommandLine
2014 };
2015
2016 #ifdef TERATERM32
2017 BOOL __declspec(dllexport)
2018 PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2019 {
2020 #else
2021 BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2022 {
2023 #endif
2024 int size = sizeof(Exports) - sizeof(exports->size);
2025 /* do version checking if necessary */
2026 /* if (Version!=TTVERSION) return FALSE; */
2027
2028 if (size > exports->size) {
2029 size = exports->size;
2030 }
2031 memcpy((char FAR *) exports + sizeof(exports->size),
2032 (char FAR *) &Exports + sizeof(exports->size), size);
2033 return TRUE;
2034 }
2035
2036 #ifdef TERATERM32
2037 static HANDLE __mem_mapping = NULL;
2038
2039 BOOL WINAPI DllMain(HANDLE hInstance,
2040 ULONG ul_reason_for_call, LPVOID lpReserved)
2041 {
2042 switch (ul_reason_for_call) {
2043 case DLL_THREAD_ATTACH:
2044 /* do thread initialization */
2045 break;
2046 case DLL_THREAD_DETACH:
2047 /* do thread cleanup */
2048 break;
2049 case DLL_PROCESS_ATTACH:
2050 /* do process initialization */
2051 DisableThreadLibraryCalls(hInstance);
2052 hInst = hInstance;
2053 pvar = &InstVar;
2054 __mem_mapping =
2055 CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
2056 sizeof(TS_SSH), "TTSSH_1-4_TS_data");
2057 if (__mem_mapping == NULL) {
2058 /* fake it. The settings won't be shared, but what the heck. */
2059 pvar->ts_SSH = NULL;
2060 } else {
2061 pvar->ts_SSH =
2062 (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
2063 0, 0);
2064 }
2065 if (pvar->ts_SSH == NULL) {
2066 /* fake it. The settings won't be shared, but what the heck. */
2067 pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
2068 if (__mem_mapping != NULL) {
2069 CloseHandle(__mem_mapping);
2070 }
2071 }
2072 break;
2073 case DLL_PROCESS_DETACH:
2074 /* do process cleanup */
2075 if (__mem_mapping == NULL) {
2076 free(pvar->ts_SSH);
2077 } else {
2078 CloseHandle(__mem_mapping);
2079 UnmapViewOfFile(pvar->ts_SSH);
2080 }
2081 break;
2082 }
2083 return TRUE;
2084 }
2085 #else
2086 #ifdef WATCOM
2087 #pragma off (unreferenced);
2088 #endif
2089 int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
2090 WORD wHeapSize, LPSTR lpszCmdLine)
2091 #ifdef WATCOM
2092 #pragma on (unreferenced);
2093 #endif
2094 {
2095 int i;
2096 for (i = 0; i < MAXNUMINST; i++)
2097 TaskList[i] = NULL;
2098 hInst = hInstance;
2099 return (1);
2100 }
2101 #endif
2102
2103
2104 /*
2105 * $Log: not supported by cvs2svn $
2106 * Revision 1.9 2005/01/24 14:07:07 yutakakn
2107 * �Ekeyboard-interactive�F�����T�|�[�g�����B
2108 * �@�����������Ateraterm.ini�� "KeyboardInteractive" �G���g�������������B
2109 * �E�o�[�W�����_�C�A���O�� OpenSSL�o�[�W���� ������
2110 *
2111 * Revision 1.8 2004/12/27 14:05:08 yutakakn
2112 * 'Auto window close'���L���������A���f�������������������������C�������B
2113 * �@�E�X���b�h���I����������������������
2114 * �@�E�m������SSH���\�[�X������
2115 *
2116 * Revision 1.7 2004/12/17 14:28:36 yutakakn
2117 * ���b�Z�[�W�F���A���S���Y���� HMAC-MD5 �������B
2118 * TTSSH�o�[�W�����_�C�A���O��HMAC�A���S���Y���\���������B
2119 *
2120 * Revision 1.6 2004/12/16 13:57:43 yutakakn
2121 * "SECURITY WARINIG" dialog�� ESC �L�[�������������A
2122 * �A�v���P�[�V�����G���[���������������b�������B
2123 *
2124 * Revision 1.5 2004/12/11 07:31:00 yutakakn
2125 * SSH heartbeat�X���b�h�����������B�����������AIP�}�X�J���[�h�������������A���[�^��
2126 * NAT�e�[�u���N���A�������ASSH�R�l�N�V���������f�����������������������B
2127 * ���������������Ateraterm.ini��TTSSH�Z�N�V�������AHeartBeat �G���g���������B
2128 *
2129 * Revision 1.4 2004/12/01 15:37:49 yutakakn
2130 * SSH2�������O�C���@�\�������B
2131 * �����A�p�X���[�h�F�������������B
2132 * �E�R�}���h���C��
2133 * /ssh /auth=�F�����\�b�h /user=���[�U�� /passwd=�p�X���[�h
2134 *
2135 * Revision 1.3 2004/11/29 15:52:37 yutakakn
2136 * SSH��default protocol��SSH2�������B
2137 *
2138 * Revision 1.2 2004/11/23 14:32:26 yutakakn
2139 * �����_�C�A���O���N�������ATCP/IP���u�z�X�g���v���t�H�[�J�X�������������������B
2140 *
2141 *
2142 */

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