Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/ttxssh.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 yutakakn 2728 /*
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 yutakakn 2748 #include "ssh.h"
39 yutakakn 2728
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 yutakakn 2782 #include <openssl/opensslv.h>
59    
60 yutakakn 2728 #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 yutakakn 2748
178     ssh_heartbeat_lock_initialize();
179 yutakakn 2728 }
180    
181     static void uninit_TTSSH(PTInstVar pvar)
182     {
183 yutakakn 2766 halt_ssh_heartbeat_thread(pvar);
184    
185 yutakakn 2728 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 yutakakn 2766
204     ssh_heartbeat_lock_finalize();
205 yutakakn 2728 }
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 yutakakn 2738 // default is SSH2 (2004.11.30 yutaka)
375     settings->ssh_protocol_version = GetPrivateProfileInt("TTSSH", "ProtocolVersion", 2, fileName);
376 yutakakn 2728
377 yutakakn 2748 // SSH heartbeat time(second) (2004.12.11 yutaka)
378     settings->ssh_heartbeat_overtime = GetPrivateProfileInt("TTSSH", "HeartBeat", 60, fileName);
379    
380 yutakakn 2782 // SSH2 keyboard-interactive (2005.1.23 yutaka)
381     settings->ssh2_keyboard_interactive = GetPrivateProfileInt("TTSSH", "KeyboardInteractive", 1, fileName);
382    
383 yutakakn 2728 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 yutakakn 2748 // 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 yutakakn 2782 // SSH2 keyboard-interactive (2005.1.23 yutaka)
445     WritePrivateProfileString("TTSSH", "KeyboardInteractive",
446     settings->ssh2_keyboard_interactive ? "1" : "0",
447     fileName);
448    
449 yutakakn 2728 }
450    
451 yutakakn 2748
452 yutakakn 2728 /* 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 yutakakn 2748 int ret;
631    
632     ssh_heartbeat_lock();
633     ret = PKT_recv(pvar, buf, len);
634     ssh_heartbeat_unlock();
635     return (ret);
636    
637 yutakakn 2728 } 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 yutakakn 2748 ssh_heartbeat_lock();
649 yutakakn 2728 SSH_send(pvar, buf, len);
650 yutakakn 2748 ssh_heartbeat_unlock();
651 yutakakn 2728 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 yutakakn 2766 SSH_notify_disconnecting(pvar, NULL);
685     AUTH_notify_disconnecting(pvar);
686     HOSTS_notify_disconnecting(pvar);
687    
688 yutakakn 2728 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 yutakakn 2734 if (pvar->settings.ssh_protocol_version == 1) {
893     SendDlgItemMessage(dlg, IDC_SSH_VERSION, CB_SETCURSEL, 0, 0); // SSH1
894     } else {
895 yutakakn 2728 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 yutakakn 2734
941 yutakakn 2728 SetFocus(hwnd);
942 yutakakn 2734 //SendMessage(hwnd, BM_SETCHECK, BST_CHECKED, 0);
943     //style = GetClassLongPtr(hwnd, GCL_STYLE);
944     //SetClassLongPtr(hwnd, GCL_STYLE, style | WS_TABSTOP);
945 yutakakn 2728 }
946    
947 yutakakn 2734 // 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 yutakakn 2728
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 yutakakn 2734 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, TRUE); // disabled (2004.11.23 yutaka)
1030 yutakakn 2728 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 yutakakn 2734 enable_dlg_items(dlg, IDC_SSH_VERSION_LABEL, IDC_SSH_VERSION_LABEL, FALSE); // disabled (2004.11.23 yutaka)
1048 yutakakn 2728
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 yutakakn 2784
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 yutakakn 2728 /* 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 yutakakn 2739
1179 yutakakn 2728 } 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 yutakakn 2739 } else if (MATCH_STR(option + 1, "auth") == 0) {
1219 yutakakn 2784 // SSH2�������O�C���I�v�V����������
1220 yutakakn 2739 //
1221 yutakakn 2784 // 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 yutakakn 2739 //
1227 yutakakn 2784 // (2004.11.30 yutaka)
1228     // (2005.1.26 yutaka) ���������B���J���F���T�|�[�g�B
1229     //
1230 yutakakn 2739 pvar->ssh2_autologin = 1; // for SSH2 (2004.11.30 yutaka)
1231    
1232 yutakakn 2784 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 yutakakn 2739
1236 yutakakn 2784 } 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 yutakakn 2739 } else {
1241     // TODO:
1242    
1243     }
1244    
1245     } else if (MATCH_STR(option + 1, "user=") == 0) {
1246 yutakakn 2784 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 yutakakn 2739
1249     } else if (MATCH_STR(option + 1, "passwd=") == 0) {
1250 yutakakn 2784 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 yutakakn 2739
1253 yutakakn 2784 } else if (MATCH_STR(option + 1, "keyfile=") == 0) {
1254     replace_to_blank(option + 9, pvar->ssh2_keyfile, sizeof(pvar->ssh2_keyfile));
1255    
1256 yutakakn 2728 }
1257    
1258     }
1259    
1260     return 0;
1261     }
1262    
1263     static void FAR PASCAL TTXParseParam(PCHAR param, PTTSet ts,
1264     PCHAR DDETopic)
1265     {
1266     int i;
1267     BOOL inParam = FALSE;
1268     BOOL inQuotes = FALSE;
1269     PCHAR option = NULL;
1270     GET_VAR();
1271    
1272     if (pvar->hostdlg_activated) {
1273     pvar->settings.Enabled = pvar->hostdlg_Enabled;
1274     }
1275    
1276     for (i = 0; param[i] != 0; i++) {
1277     if (inQuotes ? param[i] ==
1278     '"' : (param[i] == ' ' || param[i] == '\t')) {
1279     if (option != NULL) {
1280     char ch = param[i];
1281    
1282     param[i] = 0;
1283     if (parse_option
1284     (pvar, *option == '"' ? option + 1 : option)) {
1285     memset(option, ' ', i + 1 - (option - param));
1286     } else {
1287     param[i] = ch;
1288     }
1289     option = NULL;
1290     }
1291     inParam = FALSE;
1292     inQuotes = FALSE;
1293     } else if (!inParam) {
1294     if (param[i] == '"') {
1295     inQuotes = TRUE;
1296     inParam = TRUE;
1297     option = param + i;
1298     } else if (param[i] != ' ' && param[i] != '\t') {
1299     inParam = TRUE;
1300     option = param + i;
1301     }
1302     }
1303     }
1304    
1305     if (option != NULL) {
1306     if (parse_option(pvar, option)) {
1307     memset(option, ' ', i - (option - param));
1308     }
1309     }
1310    
1311     FWDUI_load_settings(pvar);
1312    
1313     (pvar->ParseParam) (param, ts, DDETopic);
1314    
1315     }
1316    
1317     static void PASCAL FAR TTXGetSetupHooks(TTXSetupHooks FAR * hooks)
1318     {
1319     GET_VAR();
1320    
1321     pvar->ReadIniFile = *hooks->ReadIniFile;
1322     pvar->WriteIniFile = *hooks->WriteIniFile;
1323     pvar->ParseParam = *hooks->ParseParam;
1324    
1325     *hooks->ReadIniFile = TTXReadINIFile;
1326     *hooks->WriteIniFile = TTXWriteINIFile;
1327     *hooks->ParseParam = TTXParseParam;
1328     }
1329    
1330     static void PASCAL FAR TTXSetWinSize(int rows, int cols)
1331     {
1332     GET_VAR();
1333    
1334     SSH_notify_win_size(pvar, cols, rows);
1335     }
1336    
1337     static void insertMenuBeforeItem(HMENU menu, WORD beforeItemID, WORD flags,
1338     WORD newItemID, char FAR * text)
1339     {
1340     int i, j;
1341    
1342     for (i = GetMenuItemCount(menu) - 1; i >= 0; i--) {
1343     HMENU submenu = GetSubMenu(menu, i);
1344    
1345     for (j = GetMenuItemCount(submenu) - 1; j >= 0; j--) {
1346     if (GetMenuItemID(submenu, j) == beforeItemID) {
1347     InsertMenu(submenu, j, MF_BYPOSITION | flags, newItemID,
1348     text);
1349     return;
1350     }
1351     }
1352     }
1353     }
1354    
1355     static void PASCAL FAR TTXModifyMenu(HMENU menu)
1356     {
1357     GET_VAR();
1358    
1359     /* inserts before ID_HELP_ABOUT */
1360     insertMenuBeforeItem(menu, 50990, MF_ENABLED, ID_ABOUTMENU,
1361     "About &TTSSH...");
1362    
1363     /* inserts before ID_SETUP_TCPIP */
1364     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHSETUPMENU,
1365     "SS&H...");
1366     /* inserts before ID_SETUP_TCPIP */
1367     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHAUTHSETUPMENU,
1368     "SSH &Authentication...");
1369     /* inserts before ID_SETUP_TCPIP */
1370     insertMenuBeforeItem(menu, 50360, MF_ENABLED, ID_SSHFWDSETUPMENU,
1371     "SSH F&orwarding...");
1372     }
1373    
1374     static void append_about_text(HWND dlg, char FAR * prefix, char FAR * msg)
1375     {
1376     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1377     (LPARAM) prefix);
1378     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0, (LPARAM) msg);
1379     SendDlgItemMessage(dlg, IDC_ABOUTTEXT, EM_REPLACESEL, 0,
1380     (LPARAM) (char FAR *) "\r\n");
1381     }
1382    
1383     static void init_about_dlg(PTInstVar pvar, HWND dlg)
1384     {
1385     char buf[1024];
1386    
1387 yutakakn 2782 // OpenSSL���o�[�W�������������� (2005.1.24 yutaka)
1388     SendMessage(GetDlgItem(dlg, IDC_OPENSSL_VERSION), WM_SETTEXT, 0, (LPARAM)OPENSSL_VERSION_TEXT);
1389    
1390 yutakakn 2728 // TTSSH�_�C�A���O���\������SSH������������ (2004.10.30 yutaka)
1391     if (pvar->socket != INVALID_SOCKET) {
1392     if (SSHv1(pvar)) {
1393     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1394     append_about_text(dlg, "Server ID: ", buf);
1395     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1396     append_about_text(dlg, "Using protocol: ", buf);
1397     CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1398     append_about_text(dlg, "Encryption: ", buf);
1399     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1400     append_about_text(dlg, "Server keys: ", buf);
1401     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1402     append_about_text(dlg, "Authentication: ", buf);
1403     SSH_get_compression_info(pvar, buf, sizeof(buf));
1404     append_about_text(dlg, "Compression: ", buf);
1405    
1406     } else { // SSH2
1407     SSH_get_server_ID_info(pvar, buf, sizeof(buf));
1408     append_about_text(dlg, "Server ID: ", buf);
1409    
1410     append_about_text(dlg, "Client ID: ", pvar->client_version_string);
1411    
1412     SSH_get_protocol_version_info(pvar, buf, sizeof(buf));
1413     append_about_text(dlg, "Using protocol: ", buf);
1414    
1415     if (pvar->kex_type == KEX_DH_GRP1_SHA1) {
1416     strcpy(buf, KEX_DH1);
1417     } else if (pvar->kex_type == KEX_DH_GRP14_SHA1) {
1418     strcpy(buf, KEX_DH14);
1419     } else {
1420     strcpy(buf, KEX_DHGEX);
1421     }
1422     append_about_text(dlg, "KEX: ", buf);
1423    
1424     if (pvar->hostkey_type == KEY_DSA) {
1425     strcpy(buf, "ssh-dss");
1426     } else {
1427     strcpy(buf, "ssh-rsa");
1428     }
1429     append_about_text(dlg, "Host Key: ", buf);
1430    
1431 yutakakn 2758 // add HMAC algorithm (2004.12.17 yutaka)
1432     buf[0] = '\0';
1433     if (pvar->ctos_hmac == HMAC_SHA1) {
1434     strcat(buf, "hmac-sha1");
1435     } else if (pvar->ctos_hmac == HMAC_MD5) {
1436     strcat(buf, "hmac-md5");
1437     }
1438     strcat(buf, " to server, ");
1439     if (pvar->stoc_hmac == HMAC_SHA1) {
1440     strcat(buf, "hmac-sha1");
1441     } else if (pvar->stoc_hmac == HMAC_MD5) {
1442     strcat(buf, "hmac-md5");
1443     }
1444     strcat(buf, " from server");
1445     append_about_text(dlg, "HMAC: ", buf);
1446    
1447 yutakakn 2728 CRYPT_get_cipher_info(pvar, buf, sizeof(buf));
1448     append_about_text(dlg, "Encryption: ", buf);
1449     CRYPT_get_server_key_info(pvar, buf, sizeof(buf));
1450     append_about_text(dlg, "Server keys: ", buf);
1451     AUTH_get_auth_info(pvar, buf, sizeof(buf));
1452     append_about_text(dlg, "Authentication: ", buf);
1453     SSH_get_compression_info(pvar, buf, sizeof(buf));
1454     append_about_text(dlg, "Compression: ", buf);
1455    
1456     }
1457     }
1458     }
1459    
1460     static BOOL CALLBACK TTXAboutDlg(HWND dlg, UINT msg, WPARAM wParam,
1461     LPARAM lParam)
1462     {
1463     switch (msg) {
1464     case WM_INITDIALOG:
1465     init_about_dlg((PTInstVar) lParam, dlg);
1466     return TRUE;
1467     case WM_COMMAND:
1468     switch (LOWORD(wParam)) {
1469     case IDOK:
1470     EndDialog(dlg, 1);
1471     return TRUE;
1472     case IDCANCEL: /* there isn't a cancel button, but other Windows
1473     UI things can send this message */
1474     EndDialog(dlg, 0);
1475     return TRUE;
1476     }
1477     break;
1478     }
1479    
1480     return FALSE;
1481     }
1482    
1483     static char FAR *get_cipher_name(int cipher)
1484     {
1485     switch (cipher) {
1486     case SSH_CIPHER_NONE:
1487     return "<ciphers below this line are disabled>";
1488     case SSH_CIPHER_RC4:
1489     return "RC4";
1490     case SSH_CIPHER_3DES:
1491     return "3DES";
1492     case SSH_CIPHER_DES:
1493     return "DES";
1494     case SSH_CIPHER_IDEA:
1495     return "IDEA";
1496     case SSH_CIPHER_TSS:
1497     return "TSS";
1498     case SSH_CIPHER_BLOWFISH:
1499     return "Blowfish";
1500    
1501     // for SSH2(yutaka)
1502     case SSH_CIPHER_AES128:
1503     return "AES128(SSH2)";
1504     case SSH_CIPHER_3DES_CBC:
1505     return "3DES-CBC(SSH2)";
1506    
1507     default:
1508     return NULL;
1509     }
1510     }
1511    
1512     static void set_move_button_status(HWND dlg)
1513     {
1514     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1515     int curPos = (int) SendMessage(cipherControl, LB_GETCURSEL, 0, 0);
1516     int maxPos = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0) - 1;
1517    
1518     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERUP), curPos > 0
1519     && curPos <= maxPos);
1520     EnableWindow(GetDlgItem(dlg, IDC_SSHMOVECIPHERDOWN), curPos >= 0
1521     && curPos < maxPos);
1522     }
1523    
1524     static void init_setup_dlg(PTInstVar pvar, HWND dlg)
1525     {
1526     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1527     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1528     int i;
1529     int ch;
1530    
1531     SendMessage(compressionControl, TBM_SETRANGE, TRUE, MAKELONG(0, 9));
1532     SendMessage(compressionControl, TBM_SETPOS, TRUE,
1533     pvar->settings.CompressionLevel);
1534    
1535     normalize_cipher_order(pvar->settings.CipherOrder);
1536     SSH2_update_cipher_myproposal(pvar); // yutaka
1537    
1538     for (i = 0; pvar->settings.CipherOrder[i] != 0; i++) {
1539     int cipher = pvar->settings.CipherOrder[i] - '0';
1540     char FAR *name = get_cipher_name(cipher);
1541    
1542     if (name != NULL) {
1543     SendMessage(cipherControl, LB_ADDSTRING, 0, (LPARAM) name);
1544     }
1545     }
1546    
1547     SendMessage(cipherControl, LB_SETCURSEL, 0, 0);
1548     set_move_button_status(dlg);
1549    
1550     for (i = 0; (ch = pvar->settings.KnownHostsFiles[i]) != 0 && ch != ';';
1551     i++) {
1552     }
1553     if (ch != 0) {
1554     pvar->settings.KnownHostsFiles[i] = 0;
1555     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1556     pvar->settings.KnownHostsFiles);
1557     pvar->settings.KnownHostsFiles[i] = ch;
1558     SetDlgItemText(dlg, IDC_READONLYFILENAME,
1559     pvar->settings.KnownHostsFiles + i + 1);
1560     } else {
1561     SetDlgItemText(dlg, IDC_READWRITEFILENAME,
1562     pvar->settings.KnownHostsFiles);
1563     }
1564 yutakakn 2789
1565     // SSH2 HeartBeat(keep-alive)������ (2005.2.22 yutaka)
1566     {
1567     char buf[10];
1568     _snprintf(buf, sizeof(buf), "%d", pvar->settings.ssh_heartbeat_overtime);
1569     SetDlgItemText(dlg, IDC_HEARTBEAT_EDIT, buf);
1570     }
1571    
1572 yutakakn 2728 }
1573    
1574     void get_teraterm_dir_relative_name(char FAR * buf, int bufsize,
1575     char FAR * basename)
1576     {
1577     int filename_start = 0;
1578     int i;
1579     int ch;
1580    
1581     if (basename[0] == '\\' || basename[0] == '/'
1582     || (basename[0] != 0 && basename[1] == ':')) {
1583     strncpy(buf, basename, bufsize);
1584     buf[bufsize - 1] = 0;
1585     return;
1586     }
1587    
1588     GetModuleFileName(NULL, buf, bufsize);
1589     for (i = 0; (ch = buf[i]) != 0; i++) {
1590     if (ch == '\\' || ch == '/' || ch == ':') {
1591     filename_start = i + 1;
1592     }
1593     }
1594    
1595     if (bufsize > filename_start) {
1596     strncpy(buf + filename_start, basename, bufsize - filename_start);
1597     }
1598     buf[bufsize - 1] = 0;
1599     }
1600    
1601     int copy_teraterm_dir_relative_path(char FAR * dest, int destsize,
1602     char FAR * basename)
1603     {
1604     char buf[1024];
1605     int filename_start = 0;
1606     int i;
1607     int ch, ch2;
1608    
1609     if (basename[0] != '\\' && basename[0] != '/'
1610     && (basename[0] == 0 || basename[1] != ':')) {
1611     strncpy(dest, basename, destsize);
1612     dest[destsize - 1] = 0;
1613     return strlen(dest);
1614     }
1615    
1616     GetModuleFileName(NULL, buf, sizeof(buf));
1617     for (i = 0; (ch = buf[i]) != 0; i++) {
1618     if (ch == '\\' || ch == '/' || ch == ':') {
1619     filename_start = i + 1;
1620     }
1621     }
1622    
1623     for (i = 0; i < filename_start; i++) {
1624     ch = toupper(buf[i]);
1625     ch2 = toupper(basename[i]);
1626    
1627     if (ch == ch2
1628     || ((ch == '\\' || ch == '/')
1629     && (ch2 == '\\' || ch2 == '/'))) {
1630     } else {
1631     break;
1632     }
1633     }
1634    
1635     if (i == filename_start) {
1636     strncpy(dest, basename + i, destsize);
1637     } else {
1638     strncpy(dest, basename, destsize);
1639     }
1640     dest[destsize - 1] = 0;
1641     return strlen(dest);
1642     }
1643    
1644     static void complete_setup_dlg(PTInstVar pvar, HWND dlg)
1645     {
1646     char buf[4096];
1647     char buf2[1024];
1648     HWND compressionControl = GetDlgItem(dlg, IDC_SSHCOMPRESSIONLEVEL);
1649     HWND cipherControl = GetDlgItem(dlg, IDC_SSHCIPHERPREFS);
1650     int i, j, buf2index, bufindex;
1651     int count = (int) SendMessage(cipherControl, LB_GETCOUNT, 0, 0);
1652    
1653     pvar->settings.CompressionLevel =
1654     (int) SendMessage(compressionControl, TBM_GETPOS, 0, 0);
1655    
1656     buf2index = 0;
1657     for (i = 0; i < count; i++) {
1658     int len = SendMessage(cipherControl, LB_GETTEXTLEN, i, 0);
1659    
1660     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1661     buf[0] = 0;
1662     SendMessage(cipherControl, LB_GETTEXT, i, (LPARAM) buf);
1663     for (j = 0;
1664     j <= SSH_CIPHER_MAX
1665     && strcmp(buf, get_cipher_name(j)) != 0; j++) {
1666     }
1667     if (j <= SSH_CIPHER_MAX) {
1668     buf2[buf2index] = '0' + j;
1669     buf2index++;
1670     }
1671     }
1672     }
1673     buf2[buf2index] = 0;
1674     normalize_cipher_order(buf2);
1675     strcpy(pvar->settings.CipherOrder, buf2);
1676     SSH2_update_cipher_myproposal(pvar); // yutaka
1677    
1678     buf[0] = 0;
1679     GetDlgItemText(dlg, IDC_READWRITEFILENAME, buf, sizeof(buf));
1680     j = copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles,
1681     sizeof(pvar->settings.
1682     KnownHostsFiles), buf);
1683     buf[0] = 0;
1684     bufindex = 0;
1685     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf, sizeof(buf));
1686     for (i = 0; buf[i] != 0; i++) {
1687     if (buf[i] == ';') {
1688     buf[i] = 0;
1689     if (j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1690     pvar->settings.KnownHostsFiles[j] = ';';
1691     j++;
1692     j += copy_teraterm_dir_relative_path(pvar->settings.
1693     KnownHostsFiles + j,
1694     sizeof(pvar->settings.
1695     KnownHostsFiles)
1696     - j, buf + bufindex);
1697     }
1698     bufindex = i + 1;
1699     }
1700     }
1701     if (bufindex < i && j < sizeof(pvar->settings.KnownHostsFiles) - 1) {
1702     pvar->settings.KnownHostsFiles[j] = ';';
1703     j++;
1704     copy_teraterm_dir_relative_path(pvar->settings.KnownHostsFiles + j,
1705     sizeof(pvar->settings.
1706     KnownHostsFiles) - j,
1707     buf + bufindex);
1708     }
1709 yutakakn 2789
1710     // get SSH HeartBeat(keep-alive)
1711     SendMessage(GetDlgItem(dlg, IDC_HEARTBEAT_EDIT), WM_GETTEXT, sizeof(buf), (LPARAM)buf);
1712     i = atoi(buf);
1713     if (i < 0)
1714     i = 60;
1715     pvar->settings.ssh_heartbeat_overtime = i;
1716    
1717 yutakakn 2728 }
1718    
1719     static void move_cur_sel_delta(HWND listbox, int delta)
1720     {
1721     int curPos = (int) SendMessage(listbox, LB_GETCURSEL, 0, 0);
1722     int maxPos = (int) SendMessage(listbox, LB_GETCOUNT, 0, 0) - 1;
1723     int newPos = curPos + delta;
1724     char buf[1024];
1725    
1726     if (curPos >= 0 && newPos >= 0 && newPos <= maxPos) {
1727     int len = SendMessage(listbox, LB_GETTEXTLEN, curPos, 0);
1728    
1729     if (len > 0 && len < sizeof(buf)) { /* should always be true */
1730     buf[0] = 0;
1731     SendMessage(listbox, LB_GETTEXT, curPos, (LPARAM) buf);
1732     SendMessage(listbox, LB_DELETESTRING, curPos, 0);
1733     SendMessage(listbox, LB_INSERTSTRING, newPos,
1734     (LPARAM) (char FAR *) buf);
1735     SendMessage(listbox, LB_SETCURSEL, newPos, 0);
1736     }
1737     }
1738     }
1739    
1740     static int get_keys_file_name(HWND parent, char FAR * buf, int bufsize,
1741     int readonly)
1742     {
1743     #ifdef TERATERM32
1744     OPENFILENAME params;
1745     char fullname_buf[2048] = "ssh_known_hosts";
1746    
1747     params.lStructSize = sizeof(OPENFILENAME);
1748     params.hwndOwner = parent;
1749     params.lpstrFilter = NULL;
1750     params.lpstrCustomFilter = NULL;
1751     params.nFilterIndex = 0;
1752     buf[0] = 0;
1753     params.lpstrFile = fullname_buf;
1754     params.nMaxFile = sizeof(fullname_buf);
1755     params.lpstrFileTitle = NULL;
1756     params.lpstrInitialDir = NULL;
1757     params.lpstrTitle =
1758     readonly ? "Choose a read-only known-hosts file to add" :
1759     "Choose a read/write known-hosts file";
1760     params.Flags = (readonly ? OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST : 0)
1761     | OFN_HIDEREADONLY | (!readonly ? OFN_NOREADONLYRETURN : 0);
1762     params.lpstrDefExt = NULL;
1763    
1764     if (GetOpenFileName(&params) != 0) {
1765     copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
1766     return 1;
1767     } else {
1768     int err = CommDlgExtendedError();
1769    
1770     if (err != 0) {
1771     char buf[1024];
1772    
1773     _snprintf(buf, sizeof(buf),
1774     "Cannot show file dialog box: error %d", err);
1775     buf[sizeof(buf) - 1] = 0;
1776     MessageBox(parent, buf, "TTSSH Error",
1777     MB_OK | MB_ICONEXCLAMATION);
1778     }
1779    
1780     return 0;
1781     }
1782     #else
1783     return 0;
1784     #endif
1785     }
1786    
1787     static void choose_read_write_file(HWND dlg)
1788     {
1789     char buf[1024];
1790    
1791     if (get_keys_file_name(dlg, buf, sizeof(buf), 0)) {
1792     SetDlgItemText(dlg, IDC_READWRITEFILENAME, buf);
1793     }
1794     }
1795    
1796     static void choose_read_only_file(HWND dlg)
1797     {
1798     char buf[1024];
1799     char buf2[4096];
1800    
1801     if (get_keys_file_name(dlg, buf, sizeof(buf), 1)) {
1802     buf2[0] = 0;
1803     GetDlgItemText(dlg, IDC_READONLYFILENAME, buf2, sizeof(buf2));
1804     if (buf2[0] != 0 && buf2[strlen(buf2) - 1] != ';') {
1805     strncat(buf2, ";", sizeof(buf2));
1806     }
1807     strncat(buf2, buf, sizeof(buf2));
1808     SetDlgItemText(dlg, IDC_READONLYFILENAME, buf2);
1809     }
1810     }
1811    
1812     static BOOL CALLBACK TTXSetupDlg(HWND dlg, UINT msg, WPARAM wParam,
1813     LPARAM lParam)
1814     {
1815     switch (msg) {
1816     case WM_INITDIALOG:
1817     SetWindowLong(dlg, DWL_USER, lParam);
1818     init_setup_dlg((PTInstVar) lParam, dlg);
1819     return TRUE;
1820     case WM_COMMAND:
1821     switch (LOWORD(wParam)) {
1822     case IDOK:
1823     complete_setup_dlg((PTInstVar) GetWindowLong(dlg, DWL_USER),
1824     dlg);
1825     EndDialog(dlg, 1);
1826     return TRUE;
1827     case IDCANCEL: /* there isn't a cancel button, but other Windows
1828     UI things can send this message */
1829     EndDialog(dlg, 0);
1830     return TRUE;
1831     case IDC_SSHMOVECIPHERUP:
1832     move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), -1);
1833     set_move_button_status(dlg);
1834     SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1835     return TRUE;
1836     case IDC_SSHMOVECIPHERDOWN:
1837     move_cur_sel_delta(GetDlgItem(dlg, IDC_SSHCIPHERPREFS), 1);
1838     set_move_button_status(dlg);
1839     SetFocus(GetDlgItem(dlg, IDC_SSHCIPHERPREFS));
1840     return TRUE;
1841     case IDC_SSHCIPHERPREFS:
1842     set_move_button_status(dlg);
1843     return TRUE;
1844     case IDC_CHOOSEREADWRITEFILE:
1845     choose_read_write_file(dlg);
1846     return TRUE;
1847     case IDC_CHOOSEREADONLYFILE:
1848     choose_read_only_file(dlg);
1849     return TRUE;
1850     }
1851     break;
1852     }
1853    
1854     return FALSE;
1855     }
1856    
1857     static int PASCAL FAR TTXProcessCommand(HWND hWin, WORD cmd)
1858     {
1859     GET_VAR();
1860    
1861     if (pvar->fatal_error) {
1862     return 0;
1863     }
1864    
1865     switch (cmd) {
1866     case ID_ABOUTMENU:
1867     if (DialogBoxParam
1868     (hInst, MAKEINTRESOURCE(IDD_ABOUTDIALOG), hWin, TTXAboutDlg,
1869     (LPARAM) pvar)
1870     == -1) {
1871     MessageBox(hWin, "Cannot create About box window.",
1872     "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1873     }
1874     return 1;
1875     case ID_SSHAUTH:
1876     AUTH_do_cred_dialog(pvar);
1877     return 1;
1878     case ID_SSHSETUPMENU:
1879     if (DialogBoxParam
1880     (hInst, MAKEINTRESOURCE(IDD_SSHSETUP), hWin, TTXSetupDlg,
1881     (LPARAM) pvar)
1882     == -1) {
1883     MessageBox(hWin, "Cannot create TTSSH Setup window.",
1884     "TTSSH Error", MB_OK | MB_ICONEXCLAMATION);
1885     }
1886     return 1;
1887     case ID_SSHAUTHSETUPMENU:
1888     AUTH_do_default_cred_dialog(pvar);
1889     return 1;
1890     case ID_SSHFWDSETUPMENU:
1891     FWDUI_do_forwarding_dialog(pvar);
1892     return 1;
1893     case ID_SSHUNKNOWNHOST:
1894     HOSTS_do_unknown_host_dialog(hWin, pvar);
1895     return 1;
1896     case ID_SSHDIFFERENTHOST:
1897     HOSTS_do_different_host_dialog(hWin, pvar);
1898     return 1;
1899     case ID_SSHASYNCMESSAGEBOX:
1900     if (pvar->err_msg != NULL) {
1901     char FAR *msg = pvar->err_msg;
1902    
1903     /* Could there be a buffer overrun bug anywhere in Win32
1904     MessageBox? Who knows? I'm paranoid. */
1905     if (strlen(msg) > 2048) {
1906     msg[2048] = 0;
1907     }
1908    
1909     pvar->showing_err = TRUE;
1910     pvar->err_msg = NULL;
1911 yutakakn 2753 #if 1
1912     // XXX: "SECURITY WARINIG" dialog�� ESC �L�[�������������A
1913     // �������A�v���P�[�V�����G���[�����������A���LAPI�������B(2004.12.16 yutaka)
1914     if (!SSHv1(pvar)) {
1915     MessageBox(NULL, msg, "TTSSH",
1916     MB_TASKMODAL | MB_ICONEXCLAMATION);
1917     }
1918     #else
1919 yutakakn 2728 MessageBox(NULL, msg, "TTSSH",
1920     MB_TASKMODAL | MB_ICONEXCLAMATION);
1921 yutakakn 2753 #endif
1922 yutakakn 2728 free(msg);
1923     pvar->showing_err = FALSE;
1924 yutakakn 2753
1925 yutakakn 2728 if (pvar->err_msg != NULL) {
1926     PostMessage(hWin, WM_COMMAND, ID_SSHASYNCMESSAGEBOX, 0);
1927     } else {
1928     AUTH_notify_end_error(pvar);
1929     }
1930     }
1931     return 1;
1932     default:
1933     return 0;
1934     }
1935     }
1936    
1937     static void PASCAL FAR TTXSetCommandLine(PCHAR cmd, int cmdlen,
1938     PGetHNRec rec)
1939     {
1940     char tmpFile[MAX_PATH];
1941     char tmpPath[1024];
1942     char buf[1024];
1943     int i;
1944     GET_VAR();
1945    
1946     GetTempPath(sizeof(tmpPath), tmpPath);
1947     GetTempFileName(tmpPath, "TTX", 0, tmpFile);
1948    
1949     for (i = 0; cmd[i] != ' ' && cmd[i] != 0; i++) {
1950     }
1951    
1952     if (i < cmdlen) {
1953     strncpy(buf, cmd + i, sizeof(buf));
1954     cmd[i] = 0;
1955    
1956     write_ssh_options(pvar, tmpFile, &pvar->settings);
1957    
1958     strncat(cmd, " /ssh-consume=", cmdlen);
1959     strncat(cmd, tmpFile, cmdlen);
1960    
1961     strncat(cmd, buf, cmdlen);
1962    
1963     if (pvar->hostdlg_Enabled) {
1964     strncat(cmd, " /ssh", cmdlen);
1965    
1966     // add option of SSH protcol version (2004.10.11 yutaka)
1967     if (pvar->settings.ssh_protocol_version == 2) {
1968     strncat(cmd, " /2", cmdlen);
1969     } else {
1970     strncat(cmd, " /1", cmdlen);
1971     }
1972    
1973     }
1974     }
1975     }
1976    
1977     /* This function is called when Teraterm is quitting. You can use it to clean
1978     up.
1979    
1980     This function is called for each extension, in reverse load order (see
1981     below).
1982     */
1983     static void PASCAL FAR TTXEnd(void)
1984     {
1985     GET_VAR();
1986    
1987     uninit_TTSSH(pvar);
1988    
1989     if (pvar->err_msg != NULL) {
1990     /* Could there be a buffer overrun bug anywhere in Win32
1991     MessageBox? Who knows? I'm paranoid. */
1992     if (strlen(pvar->err_msg) > 2048) {
1993     pvar->err_msg[2048] = 0;
1994     }
1995    
1996     MessageBox(NULL, pvar->err_msg, "TTSSH",
1997     MB_TASKMODAL | MB_ICONEXCLAMATION);
1998    
1999     free(pvar->err_msg);
2000     pvar->err_msg = NULL;
2001     }
2002     #ifndef TERATERM32
2003     DelVar();
2004     #endif
2005     }
2006    
2007     /* This record contains all the information that the extension forwards to the
2008     main Teraterm code. It mostly consists of pointers to the above functions.
2009     Any of the function pointers can be replaced with NULL, in which case
2010     Teraterm will just ignore that function and assume default behaviour, which
2011     means "do nothing".
2012     */
2013     static TTXExports Exports = {
2014     /* This must contain the size of the structure. See below for its usage. */
2015     sizeof(TTXExports),
2016     ORDER,
2017    
2018     /* Now we just list the functions that we've implemented. */
2019     TTXInit,
2020     TTXGetUIHooks,
2021     TTXGetSetupHooks,
2022     TTXOpenTCP,
2023     TTXCloseTCP,
2024     TTXSetWinSize,
2025     TTXModifyMenu,
2026     NULL,
2027     TTXProcessCommand,
2028     TTXEnd,
2029     TTXSetCommandLine
2030     };
2031    
2032     #ifdef TERATERM32
2033     BOOL __declspec(dllexport)
2034     PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2035     {
2036     #else
2037     BOOL __export PASCAL FAR TTXBind(WORD Version, TTXExports FAR * exports)
2038     {
2039     #endif
2040     int size = sizeof(Exports) - sizeof(exports->size);
2041     /* do version checking if necessary */
2042     /* if (Version!=TTVERSION) return FALSE; */
2043    
2044     if (size > exports->size) {
2045     size = exports->size;
2046     }
2047     memcpy((char FAR *) exports + sizeof(exports->size),
2048     (char FAR *) &Exports + sizeof(exports->size), size);
2049     return TRUE;
2050     }
2051    
2052     #ifdef TERATERM32
2053     static HANDLE __mem_mapping = NULL;
2054    
2055     BOOL WINAPI DllMain(HANDLE hInstance,
2056     ULONG ul_reason_for_call, LPVOID lpReserved)
2057     {
2058     switch (ul_reason_for_call) {
2059     case DLL_THREAD_ATTACH:
2060     /* do thread initialization */
2061     break;
2062     case DLL_THREAD_DETACH:
2063     /* do thread cleanup */
2064     break;
2065     case DLL_PROCESS_ATTACH:
2066     /* do process initialization */
2067     DisableThreadLibraryCalls(hInstance);
2068     hInst = hInstance;
2069     pvar = &InstVar;
2070     __mem_mapping =
2071     CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0,
2072     sizeof(TS_SSH), "TTSSH_1-4_TS_data");
2073     if (__mem_mapping == NULL) {
2074     /* fake it. The settings won't be shared, but what the heck. */
2075     pvar->ts_SSH = NULL;
2076     } else {
2077     pvar->ts_SSH =
2078     (TS_SSH *) MapViewOfFile(__mem_mapping, FILE_MAP_WRITE, 0,
2079     0, 0);
2080     }
2081     if (pvar->ts_SSH == NULL) {
2082     /* fake it. The settings won't be shared, but what the heck. */
2083     pvar->ts_SSH = (TS_SSH *) malloc(sizeof(TS_SSH));
2084     if (__mem_mapping != NULL) {
2085     CloseHandle(__mem_mapping);
2086     }
2087     }
2088     break;
2089     case DLL_PROCESS_DETACH:
2090     /* do process cleanup */
2091     if (__mem_mapping == NULL) {
2092     free(pvar->ts_SSH);
2093     } else {
2094     CloseHandle(__mem_mapping);
2095     UnmapViewOfFile(pvar->ts_SSH);
2096     }
2097     break;
2098     }
2099     return TRUE;
2100     }
2101     #else
2102     #ifdef WATCOM
2103     #pragma off (unreferenced);
2104     #endif
2105     int CALLBACK LibMain(HANDLE hInstance, WORD wDataSegment,
2106     WORD wHeapSize, LPSTR lpszCmdLine)
2107     #ifdef WATCOM
2108     #pragma on (unreferenced);
2109     #endif
2110     {
2111     int i;
2112     for (i = 0; i < MAXNUMINST; i++)
2113     TaskList[i] = NULL;
2114     hInst = hInstance;
2115     return (1);
2116     }
2117     #endif
2118 yutakakn 2734
2119    
2120     /*
2121     * $Log: not supported by cvs2svn $
2122 yutakakn 2789 * Revision 1.10 2005/01/27 13:30:33 yutakakn
2123     * ���J���F���������O�C�����T�|�[�g�B
2124     * /auth=publickey, /keyfile �I�v�V�������V�K���������B
2125     * �����A�����������������T�|�[�g�B
2126     *
2127 yutakakn 2784 * Revision 1.9 2005/01/24 14:07:07 yutakakn
2128     * �Ekeyboard-interactive�F�����T�|�[�g�����B
2129     * �@�����������Ateraterm.ini�� "KeyboardInteractive" �G���g�������������B
2130     * �E�o�[�W�����_�C�A���O�� OpenSSL�o�[�W���� ������
2131     *
2132 yutakakn 2782 * Revision 1.8 2004/12/27 14:05:08 yutakakn
2133     * 'Auto window close'���L���������A���f�������������������������C�������B
2134     * �@�E�X���b�h���I����������������������
2135     * �@�E�m������SSH���\�[�X������
2136     *
2137 yutakakn 2766 * Revision 1.7 2004/12/17 14:28:36 yutakakn
2138     * ���b�Z�[�W�F���A���S���Y���� HMAC-MD5 �������B
2139     * TTSSH�o�[�W�����_�C�A���O��HMAC�A���S���Y���\���������B
2140     *
2141 yutakakn 2758 * Revision 1.6 2004/12/16 13:57:43 yutakakn
2142     * "SECURITY WARINIG" dialog�� ESC �L�[�������������A
2143     * �A�v���P�[�V�����G���[���������������b�������B
2144     *
2145 yutakakn 2753 * Revision 1.5 2004/12/11 07:31:00 yutakakn
2146     * SSH heartbeat�X���b�h�����������B�����������AIP�}�X�J���[�h�������������A���[�^��
2147     * NAT�e�[�u���N���A�������ASSH�R�l�N�V���������f�����������������������B
2148     * ���������������Ateraterm.ini��TTSSH�Z�N�V�������AHeartBeat �G���g���������B
2149     *
2150 yutakakn 2748 * Revision 1.4 2004/12/01 15:37:49 yutakakn
2151     * SSH2�������O�C���@�\�������B
2152     * �����A�p�X���[�h�F�������������B
2153     * �E�R�}���h���C��
2154     * /ssh /auth=�F�����\�b�h /user=���[�U�� /passwd=�p�X���[�h
2155     *
2156 yutakakn 2739 * Revision 1.3 2004/11/29 15:52:37 yutakakn
2157     * SSH��default protocol��SSH2�������B
2158     *
2159 yutakakn 2738 * Revision 1.2 2004/11/23 14:32:26 yutakakn
2160     * �����_�C�A���O���N�������ATCP/IP���u�z�X�g���v���t�H�[�J�X�������������������B
2161 yutakakn 2734 *
2162 yutakakn 2738 *
2163 yutakakn 2734 */

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