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 2930 - (hide annotations) (download) (as text)
Tue Nov 14 09:00:40 2006 UTC (17 years, 5 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 91392 byte(s)
エラーメッセージを修正した。

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