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 2738 - (hide annotations) (download) (as text)
Mon Nov 29 15:52:37 2004 UTC (19 years, 4 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 52533 byte(s)
SSHのdefault protocolをSSH2にした。

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

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