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 2913 - (hide annotations) (download) (as text)
Tue Oct 10 16:54:54 2006 UTC (17 years, 6 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/ttxssh.c
File MIME type: text/x-csrc
File size: 91141 byte(s)
ttermpro.exeの/Fパラメータで指定されたファイルからTTSSHの設定が読まれなくなっていたのを修正した。

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