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 2793 - (show annotations) (download) (as text)
Thu Mar 3 13:28:23 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 60248 byte(s)
クライアントのSSHバージョンを ttxssh.dll から取得して、サーバへ送るようにした。

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 // ���s�t�@�C�������o�[�W�������������� (2005.2.28 yutaka)
1384 void get_file_version(char *exefile, int *major, int *minor, int *release, int *build)
1385 {
1386 typedef struct {
1387 WORD wLanguage;
1388 WORD wCodePage;
1389 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
1390 LPLANGANDCODEPAGE lplgcode;
1391 UINT unLen;
1392 DWORD size;
1393 char *buf = NULL;
1394 BOOL ret;
1395 int i;
1396 char fmt[80];
1397 char *pbuf;
1398
1399 size = GetFileVersionInfoSize(exefile, NULL);
1400 if (size == 0) {
1401 goto error;
1402 }
1403 buf = malloc(size);
1404 ZeroMemory(buf, size);
1405
1406 if (GetFileVersionInfo(exefile, 0, size, buf) == FALSE) {
1407 goto error;
1408 }
1409
1410 ret = VerQueryValue(buf,
1411 "\\VarFileInfo\\Translation",
1412 (LPVOID *)&lplgcode, &unLen);
1413 if (ret == FALSE)
1414 goto error;
1415
1416 for (i = 0 ; i < (int)(unLen / sizeof(LANGANDCODEPAGE)) ; i++) {
1417 _snprintf(fmt, sizeof(fmt), "\\StringFileInfo\\%04x%04x\\FileVersion",
1418 lplgcode[i].wLanguage, lplgcode[i].wCodePage);
1419 VerQueryValue(buf, fmt, &pbuf, &unLen);
1420 if (unLen > 0) { // get success
1421 int n, a, b, c, d;
1422
1423 n = sscanf(pbuf, "%d, %d, %d, %d", &a, &b, &c, &d);
1424 if (n == 4) { // convert success
1425 *major = a;
1426 *minor = b;
1427 *release = c;
1428 *build = d;
1429 break;
1430 }
1431 }
1432 }
1433
1434 free(buf);
1435 return;
1436
1437 error:
1438 free(buf);
1439 *major = *minor = *release = *build = 0;
1440 }
1441
1442 static void init_about_dlg(PTInstVar pvar, HWND dlg)
1443 {
1444 char buf[1024];
1445 int a, b, c, d;
1446
1447 // TTSSH���o�[�W�������������� (2005.2.28 yutaka)
1448 get_file_version("ttxssh.dll", &a, &b, &c, &d);
1449 _snprintf(buf, sizeof(buf), "TTSSH\r\nTeraterm Secure Shell extension, %d.%d", a, b);
1450 SendMessage(GetDlgItem(dlg, IDC_TTSSH_VERSION), WM_SETTEXT, 0, (LPARAM)buf);
1451
1452 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1453 SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1454
1455 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1456 if (pvar->socket != INVALID_SOCKET) {
1457 if (SSHv1(pvar)) {
1458 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1459 append_about_text(dlg, "Server ID: ", buf);
1460 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1461 append_about_text(dlg, "Using protocol: ", buf);
1462 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1463 append_about_text(dlg, "Encryption: ", buf);
1464 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1465 append_about_text(dlg, "Server keys: ", buf);
1466 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1467 append_about_text(dlg, "Authentication: ", buf);
1468 SSH_get_compression_info(pvar, buf, sizeof(buf));
1469 append_about_text(dlg, "Compression: ", buf);
1470
1471 } else { // SSH2
1472 SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1473 append_about_text(dlg, "Server ID: ", buf);
1474
1475 append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1476
1477 SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1478 append_about_text(dlg, "Using protocol: ", buf);
1479
1480 if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1481 strcpy(buf, KEX_DH1);
1482 } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1483 strcpy(buf, KEX_DH14);
1484 } else {
1485 strcpy(buf, KEX_DHGEX);
1486 }
1487 append_about_text(dlg, "KEX: ", buf);
1488
1489 if (pvar->hostkey_type == KEY_DSA) {
1490 strcpy(buf, "ssh-dss");
1491 } else {
1492 strcpy(buf, "ssh-rsa");
1493 }
1494 append_about_text(dlg, "Host Key: ", buf);
1495
1496 // add HMAC algorithm (2004.12.17 yutaka)
1497 buf[0] = '\0';
1498 if (pvar->ctos_hmac == HMAC_SHA1) {
1499 strcat(buf, "hmac-sha1");
1500 } else if (pvar->ctos_hmac == HMAC_MD5) {
1501 strcat(buf, "hmac-md5");
1502 }
1503 strcat(buf, " to server, ");
1504 if (pvar->stoc_hmac == HMAC_SHA1) {
1505 strcat(buf, "hmac-sha1");
1506 } else if (pvar->stoc_hmac == HMAC_MD5) {
1507 strcat(buf, "hmac-md5");
1508 }
1509 strcat(buf, " from server");
1510 append_about_text(dlg, "HMAC: ", buf);
1511
1512 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1513 append_about_text(dlg, "Encryption: ", buf);
1514 CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1515 append_about_text(dlg, "Server keys: ", buf);
1516 AUTH_get_auth_info(pvar, buf, sizeof(buf));
1517 append_about_text(dlg, "Authentication: ", buf);
1518 SSH_get_compression_info(pvar, buf, sizeof(buf));
1519 append_about_text(dlg, "Compression: ", buf);
1520
1521 }
1522 }
1523 }
1524
1525 static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1526 LPARAM lParam)
1527 {
1528 switch (msg) {
1529 case WM_INITDIALOG:
1530 init_about_dlg((PTInstVar) lParam, dlg);
1531 return TRUE;
1532 case WM_COMMAND:
1533 switch (LOWORD(wParam)) {
1534 case IDOK:
1535 EndDialog(dlg, 1);
1536 return TRUE;
1537 case IDCANCEL: /* there isn't a cancel button, but other Windows
1538 UI things can send this message */
1539 EndDialog(dlg, 0);
1540 return TRUE;
1541 }
1542 break;
1543 }
1544
1545 return FALSE;
1546 }
1547
1548 static char FAR *get_cipher_name(int cipher)
1549 {
1550 switch (cipher) {
1551 case SSH_CIPHER_NONE:
1552 return "<ciphers below this line are disabled>";
1553 case SSH_CIPHER_RC4:
1554 return "RC4";
1555 case SSH_CIPHER_3DES:
1556 return "3DES";
1557 case SSH_CIPHER_DES:
1558 return "DES";
1559 case SSH_CIPHER_IDEA:
1560 return "IDEA";
1561 case SSH_CIPHER_TSS:
1562 return "TSS";
1563 case SSH_CIPHER_BLOWFISH:
1564 return "Blowfish";
1565
1566 // for SSH2(yutaka)
1567 case SSH_CIPHER_AES128:
1568 return "AES128(SSH2)";
1569 case SSH_CIPHER_3DES_CBC:
1570 return "3DES-CBC(SSH2)";
1571
1572 default:
1573 return NULL;
1574 }
1575 }
1576
1577 static void set_move_button_status(HWND dlg)
1578 {
1579 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1580 int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1581 int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1582
1583 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1584 && curPos <= maxPos);
1585 EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1586 && curPos < maxPos);
1587 }
1588
1589 static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1590 {
1591 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1592 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1593 int i;
1594 int ch;
1595
1596 SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1597 SendMessage(compressionControl, TBM_SETPOS, TRUE,
1598 pvar->settings.CompressionLevel);
1599
1600 normalize_cipher_order(pvar->settings.CipherOrder);
1601 SSH2_update_cipher_myproposal(pvar); // yutaka
1602
1603 for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1604 int cipher = pvar->settings.CipherOrder[i] - '0';
1605 char FAR *name = get_cipher_name(cipher);
1606
1607 if (name != NULL) {
1608 SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1609 }
1610 }
1611
1612 SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1613 set_move_button_status(dlg);
1614
1615 for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1616 i++) {
1617 }
1618 if (ch != 0) {
1619 pvar->settings.KnownHostsFiles[i] = 0;
1620 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1621 pvar->settings.KnownHostsFiles);
1622 pvar->settings.KnownHostsFiles[i] = ch;
1623 SetDlgItemText(dlg, IDC_READONLYFILENAME,
1624 pvar->settings.KnownHostsFiles + i + 1);
1625 } else {
1626 SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1627 pvar->settings.KnownHostsFiles);
1628 }
1629
1630 // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
1631 {
1632 char buf[10];
1633 _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
1634 SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
1635 }
1636
1637 }
1638
1639 void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1640 char FAR * basename)
1641 {
1642 int filename_start = 0;
1643 int i;
1644 int ch;
1645
1646 if (basename[0] == '\\' || basename[0] == '/'
1647 || (basename[0] != 0 && basename[1] == ':')) {
1648 strncpy(buf, basename, bufsize);
1649 buf[bufsize - 1] = 0;
1650 return;
1651 }
1652
1653 GetModuleFileName(NULL, buf, bufsize);
1654 for (i = 0; (ch = buf[i]) != 0; i++) {
1655 if (ch == '\\' || ch == '/' || ch == ':') {
1656 filename_start = i + 1;
1657 }
1658 }
1659
1660 if (bufsize > filename_start) {
1661 strncpy(buf + filename_start, basename, bufsize - filename_start);
1662 }
1663 buf[bufsize - 1] = 0;
1664 }
1665
1666 int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1667 char FAR * basename)
1668 {
1669 char buf[1024];
1670 int filename_start = 0;
1671 int i;
1672 int ch, ch2;
1673
1674 if (basename[0] != '\\' && basename[0] != '/'
1675 && (basename[0] == 0 || basename[1] != ':')) {
1676 strncpy(dest, basename, destsize);
1677 dest[destsize - 1] = 0;
1678 return strlen(dest);
1679 }
1680
1681 GetModuleFileName(NULL, buf, sizeof(buf));
1682 for (i = 0; (ch = buf[i]) != 0; i++) {
1683 if (ch == '\\' || ch == '/' || ch == ':') {
1684 filename_start = i + 1;
1685 }
1686 }
1687
1688 for (i = 0; i < filename_start; i++) {
1689 ch = toupper(buf[i]);
1690 ch2 = toupper(basename[i]);
1691
1692 if (ch == ch2
1693 || ((ch == '\\' || ch == '/')
1694 && (ch2 == '\\' || ch2 == '/'))) {
1695 } else {
1696 break;
1697 }
1698 }
1699
1700 if (i == filename_start) {
1701 strncpy(dest, basename + i, destsize);
1702 } else {
1703 strncpy(dest, basename, destsize);
1704 }
1705 dest[destsize - 1] = 0;
1706 return strlen(dest);
1707 }
1708
1709 static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1710 {
1711 char buf[4096];
1712 char buf2[1024];
1713 HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1714 HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1715 int i, j, buf2index, bufindex;
1716 int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1717
1718 pvar->settings.CompressionLevel =
1719 (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1720
1721 buf2index = 0;
1722 for (i = 0; i < count; i++) {
1723 int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1724
1725 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1726 buf[0] = 0;
1727 SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1728 for (j = 0;
1729 j <= SSH_CIPHER_MAX
1730 && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1731 }
1732 if (j <= SSH_CIPHER_MAX) {
1733 buf2[buf2index] = '0' + j;
1734 buf2index++;
1735 }
1736 }
1737 }
1738 buf2[buf2index] = 0;
1739 normalize_cipher_order(buf2);
1740 strcpy(pvar->settings.CipherOrder, buf2);
1741 SSH2_update_cipher_myproposal(pvar); // yutaka
1742
1743 buf[0] = 0;
1744 GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1745 j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1746 sizeof(pvar->settings.
1747 KnownHostsFiles), buf);
1748 buf[0] = 0;
1749 bufindex = 0;
1750 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1751 for (i = 0; buf[i] != 0; i++) {
1752 if (buf[i] == ';') {
1753 buf[i] = 0;
1754 if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1755 pvar->settings.KnownHostsFiles[j] = ';';
1756 j++;
1757 j += copy_teraterm_dir_relative_path(pvar->settings.
1758 KnownHostsFiles + j,
1759 sizeof(pvar->settings.
1760 KnownHostsFiles)
1761 - j, buf + bufindex);
1762 }
1763 bufindex = i + 1;
1764 }
1765 }
1766 if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1767 pvar->settings.KnownHostsFiles[j] = ';';
1768 j++;
1769 copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1770 sizeof(pvar->settings.
1771 KnownHostsFiles) - j,
1772 buf + bufindex);
1773 }
1774
1775 // get SSH HeartBeat(keep-alive)
1776 SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
1777 i = atoi(buf);
1778 if (i < 0)
1779 i = 60;
1780 pvar->settings.ssh_heartbeat_overtime = i;
1781
1782 }
1783
1784 static void move_cur_sel_delta(HWND listbox, int delta)
1785 {
1786 int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1787 int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1788 int newPos = curPos + delta;
1789 char buf[1024];
1790
1791 if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1792 int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1793
1794 if (len > 0 && len < sizeof(buf)) { /* should always be true */
1795 buf[0] = 0;
1796 SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1797 SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1798 SendMessage(listbox, LB_INSERTSTRING, newPos,
1799 (LPARAM) (char FAR *) buf);
1800 SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1801 }
1802 }
1803 }
1804
1805 static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1806 int readonly)
1807 {
1808 #ifdef TERATERM32
1809 OPENFILENAME params;
1810 char fullname_buf[2048] = "ssh_known_hosts";
1811
1812 params.lStructSize = sizeof(OPENFILENAME);
1813 params.hwndOwner = parent;
1814 params.lpstrFilter = NULL;
1815 params.lpstrCustomFilter = NULL;
1816 params.nFilterIndex = 0;
1817 buf[0] = 0;
1818 params.lpstrFile = fullname_buf;
1819 params.nMaxFile = sizeof(fullname_buf);
1820 params.lpstrFileTitle = NULL;
1821 params.lpstrInitialDir = NULL;
1822 params.lpstrTitle =
1823 readonly ? "Choose a read-only known-hosts file to add" :
1824 "Choose a read/write known-hosts file";
1825 params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1826 | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1827 params.lpstrDefExt = NULL;
1828
1829 if (GetOpenFileName(&params) != 0) {
1830 copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1831 return 1;
1832 } else {
1833 int err = CommDlgExtendedError();
1834
1835 if (err != 0) {
1836 char buf[1024];
1837
1838 _snprintf(buf, sizeof(buf),
1839 "Cannot show file dialog box: error %d", err);
1840 buf[sizeof(buf) - 1] = 0;
1841 MessageBox(parent, buf, "TTSSH Error",
1842 MB_OK | MB_ICONEXCLAMATION);
1843 }
1844
1845 return 0;
1846 }
1847 #else
1848 return 0;
1849 #endif
1850 }
1851
1852 static void choose_read_write_file(HWND dlg)
1853 {
1854 char buf[1024];
1855
1856 if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1857 SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1858 }
1859 }
1860
1861 static void choose_read_only_file(HWND dlg)
1862 {
1863 char buf[1024];
1864 char buf2[4096];
1865
1866 if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1867 buf2[0] = 0;
1868 GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1869 if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1870 strncat(buf2, ";", sizeof(buf2));
1871 }
1872 strncat(buf2, buf, sizeof(buf2));
1873 SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1874 }
1875 }
1876
1877 static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1878 LPARAM lParam)
1879 {
1880 switch (msg) {
1881 case WM_INITDIALOG:
1882 SetWindowLong(dlg, DWL_USER, lParam);
1883 init_setup_dlg((PTInstVar) lParam, dlg);
1884 return TRUE;
1885 case WM_COMMAND:
1886 switch (LOWORD(wParam)) {
1887 case IDOK:
1888 complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1889 dlg);
1890 EndDialog(dlg, 1);
1891 return TRUE;
1892 case IDCANCEL: /* there isn't a cancel button, but other Windows
1893 UI things can send this message */
1894 EndDialog(dlg, 0);
1895 return TRUE;
1896 case IDC_SSHMOVECIPHERUP:
1897 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1898 set_move_button_status(dlg);
1899 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1900 return TRUE;
1901 case IDC_SSHMOVECIPHERDOWN:
1902 move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1903 set_move_button_status(dlg);
1904 SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1905 return TRUE;
1906 case IDC_SSHCIPHERPREFS:
1907 set_move_button_status(dlg);
1908 return TRUE;
1909 case IDC_CHOOSEREADWRITEFILE:
1910 choose_read_write_file(dlg);
1911 return TRUE;
1912 case IDC_CHOOSEREADONLYFILE:
1913 choose_read_only_file(dlg);
1914 return TRUE;
1915 }
1916 break;
1917 }
1918
1919 return FALSE;
1920 }
1921
1922 static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1923 {
1924 GET_VAR();
1925
1926 if (pvar->fatal_error) {
1927 return 0;
1928 }
1929
1930 switch (cmd) {
1931 case ID_ABOUTMENU:
1932 if (DialogBoxParam
1933 (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1934 (LPARAM) pvar)
1935 == -1) {
1936 MessageBox(hWin, "Cannot create About box window.",
1937 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1938 }
1939 return 1;
1940 case ID_SSHAUTH:
1941 AUTH_do_cred_dialog(pvar);
1942 return 1;
1943 case ID_SSHSETUPMENU:
1944 if (DialogBoxParam
1945 (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1946 (LPARAM) pvar)
1947 == -1) {
1948 MessageBox(hWin, "Cannot create TTSSH Setup window.",
1949 "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1950 }
1951 return 1;
1952 case ID_SSHAUTHSETUPMENU:
1953 AUTH_do_default_cred_dialog(pvar);
1954 return 1;
1955 case ID_SSHFWDSETUPMENU:
1956 FWDUI_do_forwarding_dialog(pvar);
1957 return 1;
1958 case ID_SSHUNKNOWNHOST:
1959 HOSTS_do_unknown_host_dialog(hWin, pvar);
1960 return 1;
1961 case ID_SSHDIFFERENTHOST:
1962 HOSTS_do_different_host_dialog(hWin, pvar);
1963 return 1;
1964 case ID_SSHASYNCMESSAGEBOX:
1965 if (pvar->err_msg != NULL) {
1966 char FAR *msg = pvar->err_msg;
1967
1968 /* Could there be a buffer overrun bug anywhere in Win32
1969 MessageBox? Who knows? I'm paranoid. */
1970 if (strlen(msg) > 2048) {
1971 msg[2048] = 0;
1972 }
1973
1974 pvar->showing_err = TRUE;
1975 pvar->err_msg = NULL;
1976 #if 1
1977 // XXX: "SECURITY WARINIG" dialog�� ESC �L�[�������������A
1978 // �������A�v���P�[�V�����G���[�����������A���LAPI�������B(2004.12.16 yutaka)
1979 if (!SSHv1(pvar)) {
1980 MessageBox(NULL, msg, "TTSSH",
1981 MB_TASKMODAL | MB_ICONEXCLAMATION);
1982 }
1983 #else
1984 MessageBox(NULL, msg, "TTSSH",
1985 MB_TASKMODAL | MB_ICONEXCLAMATION);
1986 #endif
1987 free(msg);
1988 pvar->showing_err = FALSE;
1989
1990 if (pvar->err_msg != NULL) {
1991 PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1992 } else {
1993 AUTH_notify_end_error(pvar);
1994 }
1995 }
1996 return 1;
1997 default:
1998 return 0;
1999 }
2000 }
2001
2002 static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
2003 PGetHNRec rec)
2004 {
2005 char tmpFile[MAX_PATH];
2006 char tmpPath[1024];
2007 char buf[1024];
2008 int i;
2009 GET_VAR();
2010
2011 GetTempPath(sizeof(tmpPath), tmpPath);
2012 GetTempFileName(tmpPath, "TTX", 0, tmpFile);
2013
2014 for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
2015 }
2016
2017 if (i < cmdlen) {
2018 strncpy(buf, cmd + i, sizeof(buf));
2019 cmd[i] = 0;
2020
2021 write_ssh_options(pvar, tmpFile, &pvar->settings);
2022
2023 strncat(cmd, " /ssh-consume=", cmdlen);
2024 strncat(cmd, tmpFile, cmdlen);
2025
2026 strncat(cmd, buf, cmdlen);
2027
2028 if (pvar->hostdlg_Enabled) {
2029 strncat(cmd, " /ssh", cmdlen);
2030
2031 // add option of SSH protcol version (2004.10.11 yutaka)
2032 if (pvar->settings.ssh_protocol_version == 2) {
2033 strncat(cmd, " /2", cmdlen);
2034 } else {
2035 strncat(cmd, " /1", cmdlen);
2036 }
2037
2038 }
2039 }
2040 }
2041
2042 /* This function is called when Teraterm is quitting. You can use it to clean
2043 up.
2044
2045 This function is called for each extension, in reverse load order (see
2046 below).
2047 */
2048 static void PASCAL FAR TTXEnd(void)
2049 {
2050 GET_VAR();
2051
2052 uninit_TTSSH(pvar);
2053
2054 if (pvar->err_msg != NULL) {
2055 /* Could there be a buffer overrun bug anywhere in Win32
2056 MessageBox? Who knows? I'm paranoid. */
2057 if (strlen(pvar->err_msg) > 2048) {
2058 pvar->err_msg[2048] = 0;
2059 }
2060
2061 MessageBox(NULL, pvar->err_msg, "TTSSH",
2062 MB_TASKMODAL | MB_ICONEXCLAMATION);
2063
2064 free(pvar->err_msg);
2065 pvar->err_msg = NULL;
2066 }
2067 #ifndef TERATERM32
2068 DelVar();
2069 #endif
2070 }
2071
2072 /* This record contains all the information that the extension forwards to the
2073 main Teraterm code. It mostly consists of pointers to the above functions.
2074 Any of the function pointers can be replaced with NULL, in which case
2075 Teraterm will just ignore that function and assume default behaviour, which
2076 means "do nothing".
2077 */
2078 static TTXExports Exports = {
2079 /* This must contain the size of the structure. See below for its usage. */
2080 sizeof(TTXExports),
2081 ORDER,
2082
2083 /* Now we just list the functions that we've implemented. */
2084 TTXInit,
2085 TTXGetUIHooks,
2086 TTXGetSetupHooks,
2087 TTXOpenTCP,
2088 TTXCloseTCP,
2089 TTXSetWinSize,
2090 TTXModifyMenu,
2091 NULL,
2092 TTXProcessCommand,
2093 TTXEnd,
2094 TTXSetCommandLine
2095 };
2096
2097 #ifdef TERATERM32
2098 BOOL __declspec(dllexport)
2099 PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2100 {
2101 #else
2102 BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2103 {
2104 #endif
2105 int size = sizeof(Exports) - sizeof(exports->size);
2106 /* do version checking if necessary */
2107 /* if (Version!=TTVERSION) return FALSE; */
2108
2109 if (size > exports->size) {
2110 size = exports->size;
2111 }
2112 memcpy((char FAR *) exports + sizeof(exports->size),
2113 (char FAR *) &Exports + sizeof(exports->size), size);
2114 return TRUE;
2115 }
2116
2117 #ifdef TERATERM32
2118 static HANDLE __mem_mapping = NULL;
2119
2120 BOOL WINAPI DllMain(HANDLE hInstance,
2121 ULONG ul_reason_for_call, LPVOID lpReserved)
2122 {
2123 switch (ul_reason_for_call) {
2124 case DLL_THREAD_ATTACH:
2125 /* do thread initialization */
2126 break;
2127 case DLL_THREAD_DETACH:
2128 /* do thread cleanup */
2129 break;
2130 case DLL_PROCESS_ATTACH:
2131 /* do process initialization */
2132 DisableThreadLibraryCalls(hInstance);
2133 hInst = hInstance;
2134 pvar = &InstVar;
2135 __mem_mapping =
2136 CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
2137 sizeof(TS_SSH), "TTSSH_1-4_TS_data");
2138 if (__mem_mapping == NULL) {
2139 /* fake it. The settings won't be shared, but what the heck. */
2140 pvar->ts_SSH = NULL;
2141 } else {
2142 pvar->ts_SSH =
2143 (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
2144 0, 0);
2145 }
2146 if (pvar->ts_SSH == NULL) {
2147 /* fake it. The settings won't be shared, but what the heck. */
2148 pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
2149 if (__mem_mapping != NULL) {
2150 CloseHandle(__mem_mapping);
2151 }
2152 }
2153 break;
2154 case DLL_PROCESS_DETACH:
2155 /* do process cleanup */
2156 if (__mem_mapping == NULL) {
2157 free(pvar->ts_SSH);
2158 } else {
2159 CloseHandle(__mem_mapping);
2160 UnmapViewOfFile(pvar->ts_SSH);
2161 }
2162 break;
2163 }
2164 return TRUE;
2165 }
2166 #else
2167 #ifdef WATCOM
2168 #pragma off (unreferenced);
2169 #endif
2170 int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
2171 WORD wHeapSize, LPSTR lpszCmdLine)
2172 #ifdef WATCOM
2173 #pragma on (unreferenced);
2174 #endif
2175 {
2176 int i;
2177 for (i = 0; i < MAXNUMINST; i++)
2178 TaskList[i] = NULL;
2179 hInst = hInstance;
2180 return (1);
2181 }
2182 #endif
2183
2184
2185 /*
2186 * $Log: not supported by cvs2svn $
2187 * Revision 1.12 2005/02/28 14:51:44 yutakakn
2188 * �o�[�W�����_�C�A���O���\������TTSSH���o�[�W�������Attxssh.dll��
2189 * �o�[�W�������������������������������B
2190 *
2191 * Revision 1.11 2005/02/22 08:48:11 yutakakn
2192 * TTSSH setup�_�C�A���O�� HeartBeat �����������B
2193 * TTSSH authentication setup�_�C�A���O�� keyboard-interactive �����������B
2194 *
2195 * Revision 1.10 2005/01/27 13:30:33 yutakakn
2196 * ���J���F���������O�C�����T�|�[�g�B
2197 * /auth=publickey, /keyfile �I�v�V�������V�K���������B
2198 * �����A�����������������T�|�[�g�B
2199 *
2200 * Revision 1.9 2005/01/24 14:07:07 yutakakn
2201 * �Ekeyboard-interactive�F�����T�|�[�g�����B
2202 * �@�����������Ateraterm.ini�� "KeyboardInteractive" �G���g�������������B
2203 * �E�o�[�W�����_�C�A���O�� OpenSSL�o�[�W���� ������
2204 *
2205 * Revision 1.8 2004/12/27 14:05:08 yutakakn
2206 * 'Auto window close'���L���������A���f�������������������������C�������B
2207 * �@�E�X���b�h���I����������������������
2208 * �@�E�m������SSH���\�[�X������
2209 *
2210 * Revision 1.7 2004/12/17 14:28:36 yutakakn
2211 * ���b�Z�[�W�F���A���S���Y���� HMAC-MD5 �������B
2212 * TTSSH�o�[�W�����_�C�A���O��HMAC�A���S���Y���\���������B
2213 *
2214 * Revision 1.6 2004/12/16 13:57:43 yutakakn
2215 * "SECURITY WARINIG" dialog�� ESC �L�[�������������A
2216 * �A�v���P�[�V�����G���[���������������b�������B
2217 *
2218 * Revision 1.5 2004/12/11 07:31:00 yutakakn
2219 * SSH heartbeat�X���b�h�����������B�����������AIP�}�X�J���[�h�������������A���[�^��
2220 * NAT�e�[�u���N���A�������ASSH�R�l�N�V���������f�����������������������B
2221 * ���������������Ateraterm.ini��TTSSH�Z�N�V�������AHeartBeat �G���g���������B
2222 *
2223 * Revision 1.4 2004/12/01 15:37:49 yutakakn
2224 * SSH2�������O�C���@�\�������B
2225 * �����A�p�X���[�h�F�������������B
2226 * �E�R�}���h���C��
2227 * /ssh /auth=�F�����\�b�h /user=���[�U�� /passwd=�p�X���[�h
2228 *
2229 * Revision 1.3 2004/11/29 15:52:37 yutakakn
2230 * SSH��default protocol��SSH2�������B
2231 *
2232 * Revision 1.2 2004/11/23 14:32:26 yutakakn
2233 * �����_�C�A���O���N�������ATCP/IP���u�z�X�g���v���t�H�[�J�X�������������������B
2234 *
2235 *
2236 */

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