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 2792 - (hide annotations) (download) (as text)
Mon Feb 28 14:51:44 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 60095 byte(s)
バージョンダイアログに表示するTTSSHのバージョンを、ttxssh.dllの
バージョン情報から取得するようにした。

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

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