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 2728 - (hide annotations) (download) (as text)
Sun Nov 14 15:53:21 2004 UTC (19 years, 5 months ago) by yutakakn
Original Path: ttssh2/branches/avendor/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 51976 byte(s)
no message

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

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