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

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

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