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 2739 - (show annotations) (download) (as text)
Wed Dec 1 15:37:49 2004 UTC (19 years, 4 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 53457 byte(s)
SSH2自動ログイン機能を追加。
現状、パスワード認証のみに対応。
・コマンドライン
  /ssh /auth=認証メソッド /user=ユーザ名 /passwd=パスワード

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

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