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 2800 - (hide annotations) (download) (as text)
Sat Mar 12 15:07:34 2005 UTC (19 years, 1 month ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 60847 byte(s)
SSH2 keyboard-interactive認証をTISダイアログに実装した。

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

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